1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved.
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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20 #define _RTW_BEAMFORMING_C_
21
22 #include <drv_types.h>
23 #include <hal_data.h>
24
25 #ifdef CONFIG_BEAMFORMING
26
27 #if (BEAMFORMING_SUPPORT == 0) /*for diver defined beamforming*/
28 #ifdef RTW_BEAMFORMING_VERSION_2
29 /*
30 * For phydm
31 */
beamforming_get_entry_beam_cap_by_mac_id(void * mlme,u8 mac_id)32 BEAMFORMING_CAP beamforming_get_entry_beam_cap_by_mac_id(void *mlme, u8 mac_id)
33 {
34 PADAPTER adapter;
35 struct beamforming_info *pBeamInfo;
36 struct beamformee_entry *bfee;
37 BEAMFORMING_CAP cap = BEAMFORMING_CAP_NONE;
38 u8 i = 0;
39
40
41 adapter = mlme_to_adapter((struct mlme_priv *)mlme);
42 pBeamInfo = GET_BEAMFORM_INFO(adapter);
43
44 for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) {
45 bfee = &pBeamInfo->bfee_entry[i];
46 if ((bfee->used == _TRUE)
47 && (bfee->mac_id == mac_id)) {
48 cap = bfee->cap;
49 break;
50 }
51 }
52
53 return cap;
54 }
55
beamforming_get_bfer_entry_by_addr(PADAPTER adapter,u8 * ra)56 struct beamformer_entry *beamforming_get_bfer_entry_by_addr(PADAPTER adapter, u8 *ra)
57 {
58 u8 i = 0;
59 struct beamforming_info *bf_info;
60 struct beamformer_entry *entry;
61
62
63 bf_info = GET_BEAMFORM_INFO(adapter);
64
65 for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) {
66 entry = &bf_info->bfer_entry[i];
67 if (entry->used == _FALSE)
68 continue;
69 if (_rtw_memcmp(ra, entry->mac_addr, ETH_ALEN) == _TRUE) {
70 return entry;
71 }
72 }
73
74 return NULL;
75 }
76
beamforming_get_bfee_entry_by_addr(PADAPTER adapter,u8 * ra)77 struct beamformee_entry *beamforming_get_bfee_entry_by_addr(PADAPTER adapter, u8 *ra)
78 {
79 u8 i = 0;
80 struct beamforming_info *bf_info;
81 struct beamformee_entry *entry;
82
83
84 bf_info = GET_BEAMFORM_INFO(adapter);
85
86 for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
87 entry = &bf_info->bfee_entry[i];
88 if (entry->used == _FALSE)
89 continue;
90 if (_rtw_memcmp(ra, entry->mac_addr, ETH_ALEN) == _TRUE)
91 return entry;
92 }
93
94 return NULL;
95 }
96
_get_bfer_free_entry(PADAPTER adapter)97 static struct beamformer_entry *_get_bfer_free_entry(PADAPTER adapter)
98 {
99 u8 i = 0;
100 struct beamforming_info *bf_info;
101 struct beamformer_entry *entry;
102
103
104 bf_info = GET_BEAMFORM_INFO(adapter);
105
106 for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) {
107 entry = &bf_info->bfer_entry[i];
108 if (entry->used == _FALSE)
109 return entry;
110 }
111
112 return NULL;
113 }
114
_get_bfee_free_entry(PADAPTER adapter)115 static struct beamformee_entry *_get_bfee_free_entry(PADAPTER adapter)
116 {
117 u8 i = 0;
118 struct beamforming_info *bf_info;
119 struct beamformee_entry *entry;
120
121
122 bf_info = GET_BEAMFORM_INFO(adapter);
123
124 for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
125 entry = &bf_info->bfee_entry[i];
126 if (entry->used == _FALSE)
127 return entry;
128 }
129
130 return NULL;
131 }
132
133 /*
134 * Description:
135 * Get the first entry index of MU Beamformee.
136 *
137 * Return Value:
138 * Index of the first MU sta.
139 *
140 * 2015.05.25. Created by tynli.
141 *
142 */
_get_first_mu_bfee_entry_idx(PADAPTER adapter,struct beamformee_entry * ignore)143 static u8 _get_first_mu_bfee_entry_idx(PADAPTER adapter, struct beamformee_entry *ignore)
144 {
145 struct beamforming_info *bf_info;
146 struct beamformee_entry *entry;
147 u8 idx = 0xFF;
148 u8 bFound = _FALSE;
149
150
151 bf_info = GET_BEAMFORM_INFO(adapter);
152
153 for (idx = 0; idx < MAX_BEAMFORMEE_ENTRY_NUM; idx++) {
154 entry = &bf_info->bfee_entry[idx];
155 if (ignore && (entry == ignore))
156 continue;
157 if ((entry->used == _TRUE) &&
158 TEST_FLAG(entry->cap, BEAMFORMEE_CAP_VHT_MU)) {
159 bFound = _TRUE;
160 break;
161 }
162 }
163
164 if (bFound == _FALSE)
165 idx = 0xFF;
166
167 return idx;
168 }
169
_update_min_sounding_period(PADAPTER adapter,u16 period,u8 leave)170 static void _update_min_sounding_period(PADAPTER adapter, u16 period, u8 leave)
171 {
172 struct beamforming_info *bf_info;
173 struct beamformee_entry *entry;
174 u8 i = 0;
175 u16 min_val = 0xFFFF;
176
177
178 bf_info = GET_BEAMFORM_INFO(adapter);
179
180 if (_TRUE == leave) {
181 /*
182 * When a BFee left,
183 * we need to find the latest min sounding period
184 * from the remaining BFees
185 */
186 for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
187 entry = &bf_info->bfee_entry[i];
188 if ((entry->used == _TRUE)
189 && (entry->sound_period < min_val))
190 min_val = entry->sound_period;
191 }
192
193 if (min_val == 0xFFFF)
194 bf_info->sounding_info.min_sounding_period = 0;
195 else
196 bf_info->sounding_info.min_sounding_period = min_val;
197 } else {
198 if ((bf_info->sounding_info.min_sounding_period == 0)
199 || (period < bf_info->sounding_info.min_sounding_period))
200 bf_info->sounding_info.min_sounding_period = period;
201 }
202 }
203
_add_bfer_entry(PADAPTER adapter,struct sta_info * sta,u8 bf_cap,u8 sounding_dim,u8 comp_steering)204 static struct beamformer_entry *_add_bfer_entry(PADAPTER adapter,
205 struct sta_info *sta, u8 bf_cap, u8 sounding_dim, u8 comp_steering)
206 {
207 struct mlme_priv *mlme;
208 struct beamforming_info *bf_info;
209 struct beamformer_entry *entry;
210 u8 *bssid;
211 u16 val16;
212 u8 i;
213
214
215 mlme = &adapter->mlmepriv;
216 bf_info = GET_BEAMFORM_INFO(adapter);
217
218 entry = beamforming_get_bfer_entry_by_addr(adapter, sta->hwaddr);
219 if (!entry) {
220 entry = _get_bfer_free_entry(adapter);
221 if (!entry)
222 return NULL;
223 }
224
225 entry->used = _TRUE;
226
227 if (check_fwstate(mlme, WIFI_AP_STATE)) {
228 bssid = adapter_mac_addr(adapter);
229 /* BSSID[44:47] xor BSSID[40:43] */
230 val16 = ((bssid[5] & 0xF0) >> 4) ^ (bssid[5] & 0xF);
231 /* (dec(A) + dec(B)*32) mod 512 */
232 entry->p_aid = (sta->aid + val16 * 32) & 0x1FF;
233 entry->g_id = 63;
234 } else if ((check_fwstate(mlme, WIFI_ADHOC_STATE) == _TRUE)
235 || (check_fwstate(mlme, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {
236 entry->p_aid = 0;
237 entry->g_id = 63;
238 } else {
239 bssid = sta->hwaddr;
240 /* BSSID[39:47] */
241 entry->p_aid = (bssid[5] << 1) | (bssid[4] >> 7);
242 entry->g_id = 0;
243 }
244 RTW_INFO("%s: p_aid=0x%04x g_id=0x%04x aid=0x%x\n",
245 __FUNCTION__, entry->p_aid, entry->g_id, sta->aid);
246
247 _rtw_memcpy(entry->mac_addr, sta->hwaddr, ETH_ALEN);
248 entry->cap = bf_cap;
249 entry->state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT;
250 entry->NumofSoundingDim = sounding_dim;
251
252 if (TEST_FLAG(bf_cap, BEAMFORMER_CAP_VHT_MU)) {
253 bf_info->beamformer_mu_cnt += 1;
254 entry->aid = sta->aid;
255 } else if (TEST_FLAG(bf_cap, BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT)) {
256 bf_info->beamformer_su_cnt += 1;
257
258 /* Record HW idx info */
259 for (i = 0; i < MAX_NUM_BEAMFORMER_SU; i++) {
260 if ((bf_info->beamformer_su_reg_maping & BIT(i)) == 0) {
261 bf_info->beamformer_su_reg_maping |= BIT(i);
262 entry->su_reg_index = i;
263 break;
264 }
265 }
266 RTW_INFO("%s: Add BFer entry beamformer_su_reg_maping=%#X, su_reg_index=%d\n",
267 __FUNCTION__, bf_info->beamformer_su_reg_maping, entry->su_reg_index);
268 }
269
270 return entry;
271 }
272
_add_bfee_entry(PADAPTER adapter,struct sta_info * sta,u8 bf_cap,u8 sounding_dim,u8 comp_steering)273 static struct beamformee_entry *_add_bfee_entry(PADAPTER adapter,
274 struct sta_info *sta, u8 bf_cap, u8 sounding_dim, u8 comp_steering)
275 {
276 struct mlme_priv *mlme;
277 struct beamforming_info *bf_info;
278 struct beamformee_entry *entry;
279 u8 *bssid;
280 u16 val16;
281 u8 i;
282
283
284 mlme = &adapter->mlmepriv;
285 bf_info = GET_BEAMFORM_INFO(adapter);
286
287 entry = beamforming_get_bfee_entry_by_addr(adapter, sta->hwaddr);
288 if (!entry) {
289 entry = _get_bfee_free_entry(adapter);
290 if (!entry)
291 return NULL;
292 }
293
294 entry->used = _TRUE;
295 entry->aid = sta->aid;
296 entry->mac_id = sta->mac_id;
297 entry->sound_bw = sta->bw_mode;
298
299 if (check_fwstate(mlme, WIFI_AP_STATE)) {
300 bssid = adapter_mac_addr(adapter);
301 /* BSSID[44:47] xor BSSID[40:43] */
302 val16 = ((bssid[5] & 0xF0) >> 4) ^ (bssid[5] & 0xF);
303 /* (dec(A) + dec(B)*32) mod 512 */
304 entry->p_aid = (sta->aid + val16 * 32) & 0x1FF;
305 entry->g_id = 63;
306 } else if (check_fwstate(mlme, WIFI_ADHOC_STATE) || check_fwstate(mlme, WIFI_ADHOC_MASTER_STATE)) {
307 entry->p_aid = 0;
308 entry->g_id = 63;
309 } else {
310 bssid = sta->hwaddr;
311 /* BSSID[39:47] */
312 entry->p_aid = (bssid[5] << 1) | (bssid[4] >> 7);
313 entry->g_id = 0;
314 }
315
316 _rtw_memcpy(entry->mac_addr, sta->hwaddr, ETH_ALEN);
317 entry->txbf = _FALSE;
318 entry->sounding = _FALSE;
319 entry->sound_period = 40;
320 entry->cap = bf_cap;
321
322 _update_min_sounding_period(adapter, entry->sound_period, _FALSE);
323 entry->SoundCnt = GetInitSoundCnt(entry->sound_period, bf_info->sounding_info.min_sounding_period);
324
325 entry->LogStatusFailCnt = 0;
326
327 entry->NumofSoundingDim = sounding_dim;
328 entry->CompSteeringNumofBFer = comp_steering;
329 entry->state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT;
330
331 if (TEST_FLAG(bf_cap, BEAMFORMEE_CAP_VHT_MU)) {
332 bf_info->beamformee_mu_cnt += 1;
333 bf_info->first_mu_bfee_index = _get_first_mu_bfee_entry_idx(adapter, NULL);
334
335 /* Record HW idx info */
336 for (i = 0; i < MAX_NUM_BEAMFORMEE_MU; i++) {
337 if ((bf_info->beamformee_mu_reg_maping & BIT(i)) == 0) {
338 bf_info->beamformee_mu_reg_maping |= BIT(i);
339 entry->mu_reg_index = i;
340 break;
341 }
342 }
343 RTW_INFO("%s: Add BFee entry beamformee_mu_reg_maping=%#X, mu_reg_index=%d\n",
344 __FUNCTION__, bf_info->beamformee_mu_reg_maping, entry->mu_reg_index);
345
346 } else if (TEST_FLAG(bf_cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) {
347 bf_info->beamformee_su_cnt += 1;
348
349 /* Record HW idx info */
350 for (i = 0; i < MAX_NUM_BEAMFORMEE_SU; i++) {
351 if ((bf_info->beamformee_su_reg_maping & BIT(i)) == 0) {
352 bf_info->beamformee_su_reg_maping |= BIT(i);
353 entry->su_reg_index = i;
354 break;
355 }
356 }
357 RTW_INFO("%s: Add BFee entry beamformee_su_reg_maping=%#X, su_reg_index=%d\n",
358 __FUNCTION__, bf_info->beamformee_su_reg_maping, entry->su_reg_index);
359 }
360
361 return entry;
362 }
363
_remove_bfer_entry(PADAPTER adapter,struct beamformer_entry * entry)364 static void _remove_bfer_entry(PADAPTER adapter, struct beamformer_entry *entry)
365 {
366 struct beamforming_info *bf_info;
367
368
369 bf_info = GET_BEAMFORM_INFO(adapter);
370
371 entry->state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT;
372
373 if (TEST_FLAG(entry->cap, BEAMFORMER_CAP_VHT_MU)) {
374 bf_info->beamformer_mu_cnt -= 1;
375 _rtw_memset(entry->gid_valid, 0, 8);
376 _rtw_memset(entry->user_position, 0, 16);
377 } else if (TEST_FLAG(entry->cap, BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT)) {
378 bf_info->beamformer_su_cnt -= 1;
379 }
380
381 if (bf_info->beamformer_mu_cnt == 0)
382 bf_info->beamforming_cap &= ~BEAMFORMEE_CAP_VHT_MU;
383 if (bf_info->beamformer_su_cnt == 0)
384 bf_info->beamforming_cap &= ~(BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT);
385 }
386
_remove_bfee_entry(PADAPTER adapter,struct beamformee_entry * entry)387 static void _remove_bfee_entry(PADAPTER adapter, struct beamformee_entry *entry)
388 {
389 struct beamforming_info *bf_info;
390
391
392 bf_info = GET_BEAMFORM_INFO(adapter);
393
394 entry->state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT;
395
396 if (TEST_FLAG(entry->cap, BEAMFORMEE_CAP_VHT_MU)) {
397 bf_info->beamformee_mu_cnt -= 1;
398 bf_info->first_mu_bfee_index = _get_first_mu_bfee_entry_idx(adapter, entry);
399 } else if (TEST_FLAG(entry->cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) {
400 bf_info->beamformee_su_cnt -= 1;
401 }
402
403 if (bf_info->beamformee_mu_cnt == 0)
404 bf_info->beamforming_cap &= ~BEAMFORMER_CAP_VHT_MU;
405 if (bf_info->beamformee_su_cnt == 0)
406 bf_info->beamforming_cap &= ~(BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT);
407
408 _update_min_sounding_period(adapter, 0, _TRUE);
409 }
410
411 /*
412 * Parameters
413 * adapter struct _adapter*
414 * sta struct sta_info*
415 * sta_bf_cap beamforming capabe of sta
416 * sounding_dim Number of Sounding Dimensions
417 * comp_steering Compressed Steering Number of Beamformer Antennas Supported
418 */
_get_sta_beamform_cap(PADAPTER adapter,struct sta_info * sta,u8 * sta_bf_cap,u8 * sounding_dim,u8 * comp_steering)419 static void _get_sta_beamform_cap(PADAPTER adapter, struct sta_info *sta,
420 u8 *sta_bf_cap, u8 *sounding_dim, u8 *comp_steering)
421 {
422 struct ht_priv *ht;
423 #ifdef CONFIG_80211AC_VHT
424 struct vht_priv *vht;
425 #endif /* CONFIG_80211AC_VHT */
426 u16 bf_cap;
427
428
429 *sta_bf_cap = 0;
430 *sounding_dim = 0;
431 *comp_steering = 0;
432
433 ht = &adapter->mlmepriv.htpriv;
434 #ifdef CONFIG_80211AC_VHT
435 vht = &adapter->mlmepriv.vhtpriv;
436 #endif /* CONFIG_80211AC_VHT */
437
438 if (IsSupportedHT(sta->wireless_mode) == _TRUE) {
439 /* HT */
440 bf_cap = ht->beamform_cap;
441
442 if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {
443 *sta_bf_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
444 *sounding_dim = (bf_cap & BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP) >> 6;
445 }
446 if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {
447 *sta_bf_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
448 *comp_steering = (bf_cap & BEAMFORMING_HT_BEAMFORMER_STEER_NUM) >> 4;
449 }
450 }
451
452 #ifdef CONFIG_80211AC_VHT
453 if (IsSupportedVHT(sta->wireless_mode) == _TRUE) {
454 /* VHT */
455 bf_cap = vht->beamform_cap;
456
457 /* We are SU Beamformee because the STA is SU Beamformer */
458 if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
459 *sta_bf_cap |= BEAMFORMER_CAP_VHT_SU;
460
461 /* We are MU Beamformee because the STA is MU Beamformer */
462 if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE))
463 *sta_bf_cap |= BEAMFORMER_CAP_VHT_MU;
464
465 *sounding_dim = (bf_cap & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM) >> 12;
466 }
467 /* We are SU Beamformer because the STA is SU Beamformee */
468 if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
469 *sta_bf_cap |= BEAMFORMEE_CAP_VHT_SU;
470
471 /* We are MU Beamformer because the STA is MU Beamformee */
472 if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE))
473 *sta_bf_cap |= BEAMFORMEE_CAP_VHT_MU;
474
475 *comp_steering = (bf_cap & BEAMFORMING_VHT_BEAMFORMER_STS_CAP) >> 8;
476 }
477 }
478 #endif /* CONFIG_80211AC_VHT */
479 }
480 /*
481 * Return:
482 * _TRUE success
483 * _FALSE fail
484 */
_init_entry(PADAPTER adapter,struct sta_info * sta)485 static u8 _init_entry(PADAPTER adapter, struct sta_info *sta)
486 {
487 struct mlme_priv *mlme;
488 struct ht_priv *htpriv;
489 #ifdef CONFIG_80211AC_VHT
490 struct vht_priv *vhtpriv;
491 #endif
492 struct mlme_ext_priv *mlme_ext;
493 struct sta_info *sta_real;
494 struct beamformer_entry *bfer = NULL;
495 struct beamformee_entry *bfee = NULL;
496 u8 *ra;
497 u8 wireless_mode;
498 u8 sta_bf_cap;
499 u8 sounding_dim = 0; /* number of sounding dimensions */
500 u8 comp_steering_num = 0; /* compressed steering number */
501
502
503 mlme = &adapter->mlmepriv;
504 htpriv = &mlme->htpriv;
505 #ifdef CONFIG_80211AC_VHT
506 vhtpriv = &mlme->vhtpriv;
507 #endif
508 mlme_ext = &adapter->mlmeextpriv;
509 ra = sta->hwaddr;
510 wireless_mode = sta->wireless_mode;
511 sta_real = rtw_get_stainfo(&adapter->stapriv, ra);
512
513 /* The current setting does not support Beaforming */
514 if ((IsSupportedHT(wireless_mode) == _FALSE)
515 && (IsSupportedVHT(wireless_mode) == _FALSE))
516 return _FALSE;
517
518 if ((0 == htpriv->beamform_cap)
519 #ifdef CONFIG_80211AC_VHT
520 && (0 == vhtpriv->beamform_cap)
521 #endif
522 ) {
523 RTW_INFO("The configuration disabled Beamforming! Skip...\n");
524 return _FALSE;
525 }
526
527 _get_sta_beamform_cap(adapter, sta,
528 &sta_bf_cap, &sounding_dim, &comp_steering_num);
529 RTW_INFO("STA Beamforming Capability=0x%02X\n", sta_bf_cap);
530
531 if (sta_bf_cap == BEAMFORMING_CAP_NONE)
532 return _FALSE;
533
534 if ((sta_bf_cap & BEAMFORMEE_CAP_HT_EXPLICIT)
535 || (sta_bf_cap & BEAMFORMEE_CAP_VHT_SU)
536 || (sta_bf_cap & BEAMFORMEE_CAP_VHT_MU))
537 sta_bf_cap |= BEAMFORMEE_CAP;
538 else
539 sta_bf_cap |= BEAMFORMER_CAP;
540
541 if (sta_bf_cap & BEAMFORMER_CAP) {
542 /* The other side is beamformer */
543 bfer = _add_bfer_entry(adapter, sta, sta_bf_cap, sounding_dim, comp_steering_num);
544 if (bfer == NULL) {
545 RTW_ERR("%s: Fail to allocate bfer entry!\n", __FUNCTION__);
546 return _FALSE;
547 }
548
549 sta_real->txbf_paid = bfer->p_aid;
550 sta_real->txbf_gid = bfer->g_id;
551 } else {
552 /* The other side is beamformee */
553 bfee = _add_bfee_entry(adapter, sta, sta_bf_cap, sounding_dim, comp_steering_num);
554 if (bfee == NULL) {
555 RTW_ERR("%s: Fail to allocate bfee entry!\n", __FUNCTION__);
556 return _FALSE;
557 }
558
559 sta_real->txbf_paid = bfee->p_aid;
560 sta_real->txbf_gid = bfee->g_id;
561 }
562
563 return _TRUE;
564 }
565
_deinit_entry(PADAPTER adapter,u8 * ra)566 static void _deinit_entry(PADAPTER adapter, u8 *ra)
567 {
568 struct beamforming_info *bf_info;
569 struct beamformer_entry *bfer = NULL;
570 struct beamformee_entry *bfee = NULL;
571 u8 bHwStateAddInit = _FALSE;
572
573
574 RTW_INFO("+%s\n", __FUNCTION__);
575
576 bf_info = GET_BEAMFORM_INFO(adapter);
577 bfer = beamforming_get_bfer_entry_by_addr(adapter, ra);
578 bfee = beamforming_get_bfee_entry_by_addr(adapter, ra);
579
580 if (!bfer && !bfee) {
581 RTW_WARN("%s: " MAC_FMT " is neither beamforming ee or er!!\n",
582 __FUNCTION__, MAC_ARG(ra));
583 return;
584 }
585
586 if (bfer && bfee)
587 RTW_ERR("%s: " MAC_FMT " is both beamforming ee & er!!\n",
588 __FUNCTION__, MAC_ARG(ra));
589
590 if (bfer)
591 _remove_bfer_entry(adapter, bfer);
592
593 if (bfee)
594 _remove_bfee_entry(adapter, bfee);
595
596 rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, ra);
597
598 RTW_DBG("-%s\n", __FUNCTION__);
599 }
600
_beamforming_reset(PADAPTER adapter)601 void _beamforming_reset(PADAPTER adapter)
602 {
603 RTW_ERR("%s: Not ready!!\n", __FUNCTION__);
604 }
605
beamforming_enter(PADAPTER adapter,void * sta)606 void beamforming_enter(PADAPTER adapter, void *sta)
607 {
608 u8 ret;
609
610 ret = _init_entry(adapter, (struct sta_info *)sta);
611 if (ret == _FALSE)
612 return;
613
614 rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_ENTER, sta);
615 }
616
beamforming_leave(PADAPTER adapter,u8 * ra)617 void beamforming_leave(PADAPTER adapter, u8 *ra)
618 {
619 if (ra == NULL)
620 _beamforming_reset(adapter);
621 else
622 _deinit_entry(adapter, ra);
623 }
624
beamforming_sounding_fail(PADAPTER adapter)625 void beamforming_sounding_fail(PADAPTER adapter)
626 {
627 RTW_ERR("+%s: not implemented yet!\n", __FUNCTION__);
628 }
629
beamforming_send_vht_gid_mgnt_packet(PADAPTER adapter,struct beamformee_entry * entry)630 u8 beamforming_send_vht_gid_mgnt_packet(PADAPTER adapter, struct beamformee_entry *entry)
631 {
632 struct xmit_priv *xmitpriv;
633 struct mlme_priv *mlmepriv;
634 struct xmit_frame *pmgntframe;
635 struct pkt_attrib *attrib;
636 struct rtw_ieee80211_hdr *wlanhdr;
637 u8 *pframe;
638
639
640 xmitpriv = &adapter->xmitpriv;
641 mlmepriv = &adapter->mlmepriv;
642
643 pmgntframe = alloc_mgtxmitframe(xmitpriv);
644 if (!pmgntframe)
645 return _FALSE;
646
647 /* update attribute */
648 attrib = &pmgntframe->attrib;
649 update_mgntframe_attrib(adapter, attrib);
650 attrib->rate = MGN_6M;
651 attrib->bwmode = CHANNEL_WIDTH_20;
652 attrib->subtype = WIFI_ACTION;
653
654 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
655
656 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
657 wlanhdr = (struct rtw_ieee80211_hdr *)pframe;
658
659 wlanhdr->frame_ctl = 0;
660 SetFrameSubType(pframe, attrib->subtype);
661 SetDuration(pframe, 0);
662 SetFragNum(pframe, 0);
663 SetSeqNum(pframe, 0);
664
665 _rtw_memcpy(wlanhdr->addr1, entry->mac_addr, ETH_ALEN);
666 _rtw_memcpy(wlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
667 _rtw_memcpy(wlanhdr->addr3, get_bssid(mlmepriv), ETH_ALEN);
668
669 pframe[24] = RTW_WLAN_CATEGORY_VHT;
670 pframe[25] = RTW_WLAN_ACTION_VHT_GROUPID_MANAGEMENT;
671 _rtw_memcpy(&pframe[26], entry->gid_valid, 8);
672 _rtw_memcpy(&pframe[34], entry->user_position, 16);
673
674 attrib->pktlen = 54;
675 attrib->last_txcmdsz = attrib->pktlen;
676
677 dump_mgntframe(adapter, pmgntframe);
678
679 return _TRUE;
680 }
681
beamforming_watchdog(PADAPTER adapter)682 void beamforming_watchdog(PADAPTER adapter)
683 {
684 }
685 #else /* !RTW_BEAMFORMING_VERSION_2 */
686
beamforming_get_entry_by_addr(struct mlme_priv * pmlmepriv,u8 * ra,u8 * idx)687 struct beamforming_entry *beamforming_get_entry_by_addr(struct mlme_priv *pmlmepriv, u8 *ra, u8 *idx)
688 {
689 u8 i = 0;
690 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
691
692 for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
693 if (pBeamInfo->beamforming_entry[i].bUsed &&
694 (_rtw_memcmp(ra, pBeamInfo->beamforming_entry[i].mac_addr, ETH_ALEN))) {
695 *idx = i;
696 return &(pBeamInfo->beamforming_entry[i]);
697 }
698 }
699
700 return NULL;
701 }
702
beamforming_get_entry_beam_cap_by_mac_id(PVOID pmlmepriv,u8 mac_id)703 BEAMFORMING_CAP beamforming_get_entry_beam_cap_by_mac_id(PVOID pmlmepriv , u8 mac_id)
704 {
705 u8 i = 0;
706 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO((struct mlme_priv *)pmlmepriv);
707 BEAMFORMING_CAP BeamformEntryCap = BEAMFORMING_CAP_NONE;
708
709 for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
710 if (pBeamInfo->beamforming_entry[i].bUsed &&
711 (mac_id == pBeamInfo->beamforming_entry[i].mac_id)) {
712 BeamformEntryCap = pBeamInfo->beamforming_entry[i].beamforming_entry_cap;
713 i = BEAMFORMING_ENTRY_NUM;
714 }
715 }
716
717 return BeamformEntryCap;
718 }
719
beamforming_get_free_entry(struct mlme_priv * pmlmepriv,u8 * idx)720 struct beamforming_entry *beamforming_get_free_entry(struct mlme_priv *pmlmepriv, u8 *idx)
721 {
722 u8 i = 0;
723 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
724
725 for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
726 if (pBeamInfo->beamforming_entry[i].bUsed == _FALSE) {
727 *idx = i;
728 return &(pBeamInfo->beamforming_entry[i]);
729 }
730 }
731 return NULL;
732 }
733
734
beamforming_add_entry(PADAPTER adapter,u8 * ra,u16 aid,u16 mac_id,CHANNEL_WIDTH bw,BEAMFORMING_CAP beamfrom_cap,u8 * idx)735 struct beamforming_entry *beamforming_add_entry(PADAPTER adapter, u8 *ra, u16 aid,
736 u16 mac_id, CHANNEL_WIDTH bw, BEAMFORMING_CAP beamfrom_cap, u8 *idx)
737 {
738 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
739 struct beamforming_entry *pEntry = beamforming_get_free_entry(pmlmepriv, idx);
740
741 if (pEntry != NULL) {
742 pEntry->bUsed = _TRUE;
743 pEntry->aid = aid;
744 pEntry->mac_id = mac_id;
745 pEntry->sound_bw = bw;
746 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
747 u16 BSSID = ((*(adapter_mac_addr(adapter) + 5) & 0xf0) >> 4) ^
748 (*(adapter_mac_addr(adapter) + 5) & 0xf); /* BSSID[44:47] xor BSSID[40:43] */
749 pEntry->p_aid = (aid + BSSID * 32) & 0x1ff; /* (dec(A) + dec(B)*32) mod 512 */
750 pEntry->g_id = 63;
751 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
752 pEntry->p_aid = 0;
753 pEntry->g_id = 63;
754 } else {
755 pEntry->p_aid = ra[5]; /* BSSID[39:47] */
756 pEntry->p_aid = (pEntry->p_aid << 1) | (ra[4] >> 7);
757 pEntry->g_id = 0;
758 }
759 _rtw_memcpy(pEntry->mac_addr, ra, ETH_ALEN);
760 pEntry->bSound = _FALSE;
761
762 /* 3 TODO SW/FW sound period */
763 pEntry->sound_period = 200;
764 pEntry->beamforming_entry_cap = beamfrom_cap;
765 pEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
766
767
768 pEntry->PreLogSeq = 0; /*Modified by Jeffery @2015-04-13*/
769 pEntry->LogSeq = 0; /*Modified by Jeffery @2014-10-29*/
770 pEntry->LogRetryCnt = 0; /*Modified by Jeffery @2014-10-29*/
771 pEntry->LogSuccess = 0; /*LogSuccess is NOT needed to be accumulated, so LogSuccessCnt->LogSuccess, 2015-04-13, Jeffery*/
772 pEntry->ClockResetTimes = 0; /*Modified by Jeffery @2015-04-13*/
773 pEntry->LogStatusFailCnt = 0;
774
775 return pEntry;
776 } else
777 return NULL;
778 }
779
beamforming_remove_entry(struct mlme_priv * pmlmepriv,u8 * ra,u8 * idx)780 BOOLEAN beamforming_remove_entry(struct mlme_priv *pmlmepriv, u8 *ra, u8 *idx)
781 {
782 struct beamforming_entry *pEntry = beamforming_get_entry_by_addr(pmlmepriv, ra, idx);
783
784 if (pEntry != NULL) {
785 pEntry->bUsed = _FALSE;
786 pEntry->beamforming_entry_cap = BEAMFORMING_CAP_NONE;
787 pEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
788 return _TRUE;
789 } else
790 return _FALSE;
791 }
792
793 /* Used for BeamformingStart_V1 */
beamforming_dym_ndpa_rate(PADAPTER adapter)794 void beamforming_dym_ndpa_rate(PADAPTER adapter)
795 {
796 u16 NDPARate = MGN_6M;
797 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter);
798
799 if (pHalData->MinUndecoratedPWDBForDM > 30) /* link RSSI > 30% */
800 NDPARate = MGN_24M;
801 else
802 NDPARate = MGN_6M;
803
804 /* BW = CHANNEL_WIDTH_20; */
805 NDPARate = NDPARate << 8;
806 rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_RATE, (u8 *)&NDPARate);
807 }
808
beamforming_dym_period(PADAPTER Adapter)809 void beamforming_dym_period(PADAPTER Adapter)
810 {
811 u8 Idx;
812 BOOLEAN bChangePeriod = _FALSE;
813 u16 SoundPeriod_SW, SoundPeriod_FW;
814 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
815 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
816 struct beamforming_entry *pBeamformEntry;
817 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO((&Adapter->mlmepriv));
818 struct sounding_info *pSoundInfo = &(pBeamInfo->sounding_info);
819
820 /* 3 TODO per-client throughput caculation. */
821
822 if (pdvobjpriv->traffic_stat.cur_tx_tp + pdvobjpriv->traffic_stat.cur_rx_tp > 2) {
823 SoundPeriod_SW = 32 * 20;
824 SoundPeriod_FW = 2;
825 } else {
826 SoundPeriod_SW = 32 * 2000;
827 SoundPeriod_FW = 200;
828 }
829
830 for (Idx = 0; Idx < BEAMFORMING_ENTRY_NUM; Idx++) {
831 pBeamformEntry = pBeamInfo->beamforming_entry + Idx;
832 if (pBeamformEntry->bDefaultCSI) {
833 SoundPeriod_SW = 32 * 2000;
834 SoundPeriod_FW = 200;
835 }
836
837 if (pBeamformEntry->beamforming_entry_cap & (BEAMFORMER_CAP_HT_EXPLICIT | BEAMFORMER_CAP_VHT_SU)) {
838 if (pSoundInfo->sound_mode == SOUNDING_FW_VHT_TIMER || pSoundInfo->sound_mode == SOUNDING_FW_HT_TIMER) {
839 if (pBeamformEntry->sound_period != SoundPeriod_FW) {
840 pBeamformEntry->sound_period = SoundPeriod_FW;
841 bChangePeriod = _TRUE; /* Only FW sounding need to send H2C packet to change sound period. */
842 }
843 } else if (pBeamformEntry->sound_period != SoundPeriod_SW)
844 pBeamformEntry->sound_period = SoundPeriod_SW;
845 }
846 }
847
848 if (bChangePeriod)
849 rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&Idx);
850 }
851
issue_ht_sw_ndpa_packet(PADAPTER Adapter,u8 * ra,CHANNEL_WIDTH bw,u8 qidx)852 BOOLEAN issue_ht_sw_ndpa_packet(PADAPTER Adapter, u8 *ra, CHANNEL_WIDTH bw, u8 qidx)
853 {
854 struct xmit_frame *pmgntframe;
855 struct pkt_attrib *pattrib;
856 struct rtw_ieee80211_hdr *pwlanhdr;
857 struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);
858 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
859 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
860 u8 ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};
861 u8 *pframe;
862 u16 *fctrl;
863 u16 duration = 0;
864 u8 aSifsTime = 0;
865 u8 NDPTxRate = 0;
866
867 RTW_INFO("%s: issue_ht_sw_ndpa_packet!\n", __func__);
868
869 NDPTxRate = MGN_MCS8;
870 RTW_INFO("%s: NDPTxRate =%d\n", __func__, NDPTxRate);
871 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
872
873 if (pmgntframe == NULL)
874 return _FALSE;
875
876 /*update attribute*/
877 pattrib = &pmgntframe->attrib;
878 update_mgntframe_attrib(Adapter, pattrib);
879 pattrib->qsel = QSLT_MGNT;
880 pattrib->rate = NDPTxRate;
881 pattrib->bwmode = bw;
882 pattrib->order = 1;
883 pattrib->subtype = WIFI_ACTION_NOACK;
884
885 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
886
887 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
888
889 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
890
891 fctrl = &pwlanhdr->frame_ctl;
892 *(fctrl) = 0;
893
894 SetOrderBit(pframe);
895 SetFrameSubType(pframe, WIFI_ACTION_NOACK);
896
897 _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
898 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
899 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
900
901 if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
902 aSifsTime = 10;
903 else
904 aSifsTime = 16;
905
906 duration = 2 * aSifsTime + 40;
907
908 if (bw == CHANNEL_WIDTH_40)
909 duration += 87;
910 else
911 duration += 180;
912
913 SetDuration(pframe, duration);
914
915 /*HT control field*/
916 SET_HT_CTRL_CSI_STEERING(pframe + 24, 3);
917 SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe + 24, 1);
918
919 _rtw_memcpy(pframe + 28, ActionHdr, 4);
920
921 pattrib->pktlen = 32;
922
923 pattrib->last_txcmdsz = pattrib->pktlen;
924
925 dump_mgntframe(Adapter, pmgntframe);
926
927 return _TRUE;
928
929
930 }
issue_ht_ndpa_packet(PADAPTER Adapter,u8 * ra,CHANNEL_WIDTH bw,u8 qidx)931 BOOLEAN issue_ht_ndpa_packet(PADAPTER Adapter, u8 *ra, CHANNEL_WIDTH bw, u8 qidx)
932 {
933 struct xmit_frame *pmgntframe;
934 struct pkt_attrib *pattrib;
935 struct rtw_ieee80211_hdr *pwlanhdr;
936 struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);
937 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
938 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
939 u8 ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};
940 u8 *pframe;
941 u16 *fctrl;
942 u16 duration = 0;
943 u8 aSifsTime = 0;
944
945 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
946
947 if (pmgntframe == NULL)
948 return _FALSE;
949
950 /*update attribute*/
951 pattrib = &pmgntframe->attrib;
952 update_mgntframe_attrib(Adapter, pattrib);
953
954 if (qidx == BCN_QUEUE_INX)
955 pattrib->qsel = QSLT_BEACON;
956 pattrib->rate = MGN_MCS8;
957 pattrib->bwmode = bw;
958 pattrib->order = 1;
959 pattrib->subtype = WIFI_ACTION_NOACK;
960
961 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
962
963 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
964
965 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
966
967 fctrl = &pwlanhdr->frame_ctl;
968 *(fctrl) = 0;
969
970 SetOrderBit(pframe);
971 SetFrameSubType(pframe, WIFI_ACTION_NOACK);
972
973 _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
974 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
975 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
976
977 if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
978 aSifsTime = 10;
979 else
980 aSifsTime = 16;
981
982 duration = 2 * aSifsTime + 40;
983
984 if (bw == CHANNEL_WIDTH_40)
985 duration += 87;
986 else
987 duration += 180;
988
989 SetDuration(pframe, duration);
990
991 /* HT control field */
992 SET_HT_CTRL_CSI_STEERING(pframe + 24, 3);
993 SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe + 24, 1);
994
995 _rtw_memcpy(pframe + 28, ActionHdr, 4);
996
997 pattrib->pktlen = 32;
998
999 pattrib->last_txcmdsz = pattrib->pktlen;
1000
1001 dump_mgntframe(Adapter, pmgntframe);
1002
1003 return _TRUE;
1004 }
1005
beamforming_send_ht_ndpa_packet(PADAPTER Adapter,u8 * ra,CHANNEL_WIDTH bw,u8 qidx)1006 BOOLEAN beamforming_send_ht_ndpa_packet(PADAPTER Adapter, u8 *ra, CHANNEL_WIDTH bw, u8 qidx)
1007 {
1008 return issue_ht_ndpa_packet(Adapter, ra, bw, qidx);
1009 }
issue_vht_sw_ndpa_packet(PADAPTER Adapter,u8 * ra,u16 aid,CHANNEL_WIDTH bw,u8 qidx)1010 BOOLEAN issue_vht_sw_ndpa_packet(PADAPTER Adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw, u8 qidx)
1011 {
1012 struct xmit_frame *pmgntframe;
1013 struct pkt_attrib *pattrib;
1014 struct rtw_ieee80211_hdr *pwlanhdr;
1015 struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);
1016 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
1017 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1018 struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
1019 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
1020 struct rtw_ndpa_sta_info sta_info;
1021 u8 NDPTxRate = 0;
1022
1023 u8 *pframe;
1024 u16 *fctrl;
1025 u16 duration = 0;
1026 u8 sequence = 0, aSifsTime = 0;
1027
1028 RTW_INFO("%s: issue_vht_sw_ndpa_packet!\n", __func__);
1029
1030
1031 NDPTxRate = MGN_VHT2SS_MCS0;
1032 RTW_INFO("%s: NDPTxRate =%d\n", __func__, NDPTxRate);
1033 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1034
1035 if (pmgntframe == NULL) {
1036 RTW_INFO("%s, alloc mgnt frame fail\n", __func__);
1037 return _FALSE;
1038 }
1039
1040 /*update attribute*/
1041 pattrib = &pmgntframe->attrib;
1042 update_mgntframe_attrib(Adapter, pattrib);
1043 pattrib->qsel = QSLT_MGNT;
1044 pattrib->rate = NDPTxRate;
1045 pattrib->bwmode = bw;
1046 pattrib->subtype = WIFI_NDPA;
1047
1048 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1049
1050 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1051
1052 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1053
1054 fctrl = &pwlanhdr->frame_ctl;
1055 *(fctrl) = 0;
1056
1057 SetFrameSubType(pframe, WIFI_NDPA);
1058
1059 _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
1060 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
1061
1062 if (IsSupported5G(pmlmeext->cur_wireless_mode) || IsSupportedHT(pmlmeext->cur_wireless_mode))
1063 aSifsTime = 16;
1064 else
1065 aSifsTime = 10;
1066
1067 duration = 2 * aSifsTime + 44;
1068
1069 if (bw == CHANNEL_WIDTH_80)
1070 duration += 40;
1071 else if (bw == CHANNEL_WIDTH_40)
1072 duration += 87;
1073 else
1074 duration += 180;
1075
1076 SetDuration(pframe, duration);
1077
1078 sequence = pBeamInfo->sounding_sequence << 2;
1079 if (pBeamInfo->sounding_sequence >= 0x3f)
1080 pBeamInfo->sounding_sequence = 0;
1081 else
1082 pBeamInfo->sounding_sequence++;
1083
1084 _rtw_memcpy(pframe + 16, &sequence, 1);
1085 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
1086 aid = 0;
1087
1088 sta_info.aid = aid;
1089 sta_info.feedback_type = 0;
1090 sta_info.nc_index = 0;
1091
1092 _rtw_memcpy(pframe + 17, (u8 *)&sta_info, 2);
1093
1094 pattrib->pktlen = 19;
1095
1096 pattrib->last_txcmdsz = pattrib->pktlen;
1097
1098 dump_mgntframe(Adapter, pmgntframe);
1099
1100
1101 return _TRUE;
1102
1103 }
issue_vht_ndpa_packet(PADAPTER Adapter,u8 * ra,u16 aid,CHANNEL_WIDTH bw,u8 qidx)1104 BOOLEAN issue_vht_ndpa_packet(PADAPTER Adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw, u8 qidx)
1105 {
1106 struct xmit_frame *pmgntframe;
1107 struct pkt_attrib *pattrib;
1108 struct rtw_ieee80211_hdr *pwlanhdr;
1109 struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);
1110 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
1111 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1112 struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
1113 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
1114 struct rtw_ndpa_sta_info sta_info;
1115 u8 *pframe;
1116 u16 *fctrl;
1117 u16 duration = 0;
1118 u8 sequence = 0, aSifsTime = 0;
1119
1120 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1121 if (pmgntframe == NULL)
1122 return _FALSE;
1123
1124 /*update attribute*/
1125 pattrib = &pmgntframe->attrib;
1126 update_mgntframe_attrib(Adapter, pattrib);
1127
1128 if (qidx == BCN_QUEUE_INX)
1129 pattrib->qsel = QSLT_BEACON;
1130 pattrib->rate = MGN_VHT2SS_MCS0;
1131 pattrib->bwmode = bw;
1132 pattrib->subtype = WIFI_NDPA;
1133
1134 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1135
1136 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1137
1138 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1139
1140 fctrl = &pwlanhdr->frame_ctl;
1141 *(fctrl) = 0;
1142
1143 SetFrameSubType(pframe, WIFI_NDPA);
1144
1145 _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
1146 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
1147
1148 if (IsSupported5G(pmlmeext->cur_wireless_mode) || IsSupportedHT(pmlmeext->cur_wireless_mode))
1149 aSifsTime = 16;
1150 else
1151 aSifsTime = 10;
1152
1153 duration = 2 * aSifsTime + 44;
1154
1155 if (bw == CHANNEL_WIDTH_80)
1156 duration += 40;
1157 else if (bw == CHANNEL_WIDTH_40)
1158 duration += 87;
1159 else
1160 duration += 180;
1161
1162 SetDuration(pframe, duration);
1163
1164 sequence = pBeamInfo->sounding_sequence << 2;
1165 if (pBeamInfo->sounding_sequence >= 0x3f)
1166 pBeamInfo->sounding_sequence = 0;
1167 else
1168 pBeamInfo->sounding_sequence++;
1169
1170 _rtw_memcpy(pframe + 16, &sequence, 1);
1171
1172 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
1173 aid = 0;
1174
1175 sta_info.aid = aid;
1176 sta_info.feedback_type = 0;
1177 sta_info.nc_index = 0;
1178
1179 _rtw_memcpy(pframe + 17, (u8 *)&sta_info, 2);
1180
1181 pattrib->pktlen = 19;
1182
1183 pattrib->last_txcmdsz = pattrib->pktlen;
1184
1185 dump_mgntframe(Adapter, pmgntframe);
1186
1187 return _TRUE;
1188 }
1189
beamforming_send_vht_ndpa_packet(PADAPTER Adapter,u8 * ra,u16 aid,CHANNEL_WIDTH bw,u8 qidx)1190 BOOLEAN beamforming_send_vht_ndpa_packet(PADAPTER Adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw, u8 qidx)
1191 {
1192 return issue_vht_ndpa_packet(Adapter, ra, aid, bw, qidx);
1193 }
1194
beamfomring_bSounding(struct beamforming_info * pBeamInfo)1195 BOOLEAN beamfomring_bSounding(struct beamforming_info *pBeamInfo)
1196 {
1197 BOOLEAN bSounding = _FALSE;
1198
1199 if ((beamforming_get_beamform_cap(pBeamInfo) & BEAMFORMER_CAP) == 0)
1200 bSounding = _FALSE;
1201 else
1202 bSounding = _TRUE;
1203
1204 return bSounding;
1205 }
1206
beamforming_sounding_idx(struct beamforming_info * pBeamInfo)1207 u8 beamforming_sounding_idx(struct beamforming_info *pBeamInfo)
1208 {
1209 u8 idx = 0;
1210 u8 i;
1211
1212 for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
1213 if (pBeamInfo->beamforming_entry[i].bUsed &&
1214 (_FALSE == pBeamInfo->beamforming_entry[i].bSound)) {
1215 idx = i;
1216 break;
1217 }
1218 }
1219
1220 return idx;
1221 }
1222
beamforming_sounding_mode(struct beamforming_info * pBeamInfo,u8 idx)1223 SOUNDING_MODE beamforming_sounding_mode(struct beamforming_info *pBeamInfo, u8 idx)
1224 {
1225 struct beamforming_entry BeamEntry = pBeamInfo->beamforming_entry[idx];
1226 SOUNDING_MODE mode;
1227
1228 if (BeamEntry.beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU)
1229 mode = SOUNDING_FW_VHT_TIMER;
1230 else if (BeamEntry.beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)
1231 mode = SOUNDING_FW_HT_TIMER;
1232 else
1233 mode = SOUNDING_STOP_All_TIMER;
1234
1235 return mode;
1236 }
1237
beamforming_sounding_time(struct beamforming_info * pBeamInfo,SOUNDING_MODE mode,u8 idx)1238 u16 beamforming_sounding_time(struct beamforming_info *pBeamInfo, SOUNDING_MODE mode, u8 idx)
1239 {
1240 u16 sounding_time = 0xffff;
1241 struct beamforming_entry BeamEntry = pBeamInfo->beamforming_entry[idx];
1242
1243 sounding_time = BeamEntry.sound_period;
1244
1245 return sounding_time;
1246 }
1247
beamforming_sounding_bw(struct beamforming_info * pBeamInfo,SOUNDING_MODE mode,u8 idx)1248 CHANNEL_WIDTH beamforming_sounding_bw(struct beamforming_info *pBeamInfo, SOUNDING_MODE mode, u8 idx)
1249 {
1250 CHANNEL_WIDTH sounding_bw = CHANNEL_WIDTH_20;
1251 struct beamforming_entry BeamEntry = pBeamInfo->beamforming_entry[idx];
1252
1253 sounding_bw = BeamEntry.sound_bw;
1254
1255 return sounding_bw;
1256 }
1257
beamforming_select_beam_entry(struct beamforming_info * pBeamInfo)1258 BOOLEAN beamforming_select_beam_entry(struct beamforming_info *pBeamInfo)
1259 {
1260 struct sounding_info *pSoundInfo = &(pBeamInfo->sounding_info);
1261
1262 pSoundInfo->sound_idx = beamforming_sounding_idx(pBeamInfo);
1263
1264 if (pSoundInfo->sound_idx < BEAMFORMING_ENTRY_NUM)
1265 pSoundInfo->sound_mode = beamforming_sounding_mode(pBeamInfo, pSoundInfo->sound_idx);
1266 else
1267 pSoundInfo->sound_mode = SOUNDING_STOP_All_TIMER;
1268
1269 if (SOUNDING_STOP_All_TIMER == pSoundInfo->sound_mode)
1270 return _FALSE;
1271 else {
1272 pSoundInfo->sound_bw = beamforming_sounding_bw(pBeamInfo, pSoundInfo->sound_mode, pSoundInfo->sound_idx);
1273 pSoundInfo->sound_period = beamforming_sounding_time(pBeamInfo, pSoundInfo->sound_mode, pSoundInfo->sound_idx);
1274 return _TRUE;
1275 }
1276 }
1277
beamforming_start_fw(PADAPTER adapter,u8 idx)1278 BOOLEAN beamforming_start_fw(PADAPTER adapter, u8 idx)
1279 {
1280 u8 *RA = NULL;
1281 struct beamforming_entry *pEntry;
1282 BOOLEAN ret = _TRUE;
1283 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1284 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
1285
1286 pEntry = &(pBeamInfo->beamforming_entry[idx]);
1287 if (pEntry->bUsed == _FALSE) {
1288 RTW_INFO("Skip Beamforming, no entry for Idx =%d\n", idx);
1289 return _FALSE;
1290 }
1291
1292 pEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSING;
1293 pEntry->bSound = _TRUE;
1294 rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&idx);
1295
1296 return _TRUE;
1297 }
1298
beamforming_end_fw(PADAPTER adapter)1299 void beamforming_end_fw(PADAPTER adapter)
1300 {
1301 u8 idx = 0;
1302
1303 rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&idx);
1304
1305 RTW_INFO("%s\n", __FUNCTION__);
1306 }
1307
beamforming_start_period(PADAPTER adapter)1308 BOOLEAN beamforming_start_period(PADAPTER adapter)
1309 {
1310 BOOLEAN ret = _TRUE;
1311 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1312 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
1313 struct sounding_info *pSoundInfo = &(pBeamInfo->sounding_info);
1314
1315 beamforming_dym_ndpa_rate(adapter);
1316
1317 beamforming_select_beam_entry(pBeamInfo);
1318
1319 if (pSoundInfo->sound_mode == SOUNDING_FW_VHT_TIMER || pSoundInfo->sound_mode == SOUNDING_FW_HT_TIMER)
1320 ret = beamforming_start_fw(adapter, pSoundInfo->sound_idx);
1321 else
1322 ret = _FALSE;
1323
1324 RTW_INFO("%s Idx %d Mode %d BW %d Period %d\n", __FUNCTION__,
1325 pSoundInfo->sound_idx, pSoundInfo->sound_mode, pSoundInfo->sound_bw, pSoundInfo->sound_period);
1326
1327 return ret;
1328 }
1329
beamforming_end_period(PADAPTER adapter)1330 void beamforming_end_period(PADAPTER adapter)
1331 {
1332 u8 idx = 0;
1333 struct beamforming_entry *pBeamformEntry;
1334 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1335 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
1336 struct sounding_info *pSoundInfo = &(pBeamInfo->sounding_info);
1337
1338
1339 if (pSoundInfo->sound_mode == SOUNDING_FW_VHT_TIMER || pSoundInfo->sound_mode == SOUNDING_FW_HT_TIMER)
1340 beamforming_end_fw(adapter);
1341 }
1342
beamforming_notify(PADAPTER adapter)1343 void beamforming_notify(PADAPTER adapter)
1344 {
1345 BOOLEAN bSounding = _FALSE;
1346 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(&(adapter->mlmepriv));
1347
1348 bSounding = beamfomring_bSounding(pBeamInfo);
1349
1350 if (pBeamInfo->beamforming_state == BEAMFORMING_STATE_IDLE) {
1351 if (bSounding) {
1352 if (beamforming_start_period(adapter) == _TRUE)
1353 pBeamInfo->beamforming_state = BEAMFORMING_STATE_START;
1354 }
1355 } else if (pBeamInfo->beamforming_state == BEAMFORMING_STATE_START) {
1356 if (bSounding) {
1357 if (beamforming_start_period(adapter) == _FALSE)
1358 pBeamInfo->beamforming_state = BEAMFORMING_STATE_END;
1359 } else {
1360 beamforming_end_period(adapter);
1361 pBeamInfo->beamforming_state = BEAMFORMING_STATE_END;
1362 }
1363 } else if (pBeamInfo->beamforming_state == BEAMFORMING_STATE_END) {
1364 if (bSounding) {
1365 if (beamforming_start_period(adapter) == _TRUE)
1366 pBeamInfo->beamforming_state = BEAMFORMING_STATE_START;
1367 }
1368 } else
1369 RTW_INFO("%s BeamformState %d\n", __FUNCTION__, pBeamInfo->beamforming_state);
1370
1371 RTW_INFO("%s BeamformState %d bSounding %d\n", __FUNCTION__, pBeamInfo->beamforming_state, bSounding);
1372 }
1373
beamforming_init_entry(PADAPTER adapter,struct sta_info * psta,u8 * idx)1374 BOOLEAN beamforming_init_entry(PADAPTER adapter, struct sta_info *psta, u8 *idx)
1375 {
1376 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1377 struct ht_priv *phtpriv = &(pmlmepriv->htpriv);
1378 #ifdef CONFIG_80211AC_VHT
1379 struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1380 #endif
1381 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
1382 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1383 struct beamforming_entry *pBeamformEntry = NULL;
1384 u8 *ra;
1385 u16 aid, mac_id;
1386 u8 wireless_mode;
1387 CHANNEL_WIDTH bw = CHANNEL_WIDTH_20;
1388 BEAMFORMING_CAP beamform_cap = BEAMFORMING_CAP_NONE;
1389
1390 /* The current setting does not support Beaforming */
1391 if (0 == phtpriv->beamform_cap
1392 #ifdef CONFIG_80211AC_VHT
1393 && 0 == pvhtpriv->beamform_cap
1394 #endif
1395 ) {
1396 RTW_INFO("The configuration disabled Beamforming! Skip...\n");
1397 return _FALSE;
1398 }
1399
1400 aid = psta->aid;
1401 ra = psta->hwaddr;
1402 mac_id = psta->mac_id;
1403 wireless_mode = psta->wireless_mode;
1404 bw = psta->bw_mode;
1405
1406 if (IsSupportedHT(wireless_mode) || IsSupportedVHT(wireless_mode)) {
1407 /* 3 */ /* HT */
1408 u8 cur_beamform;
1409
1410 cur_beamform = psta->htpriv.beamform_cap;
1411
1412 /* We are Beamformee because the STA is Beamformer */
1413 if (TEST_FLAG(cur_beamform, BEAMFORMING_HT_BEAMFORMER_ENABLE))
1414 beamform_cap = (BEAMFORMING_CAP)(beamform_cap | BEAMFORMEE_CAP_HT_EXPLICIT);
1415
1416 /* We are Beamformer because the STA is Beamformee */
1417 if (TEST_FLAG(cur_beamform, BEAMFORMING_HT_BEAMFORMEE_ENABLE))
1418 beamform_cap = (BEAMFORMING_CAP)(beamform_cap | BEAMFORMER_CAP_HT_EXPLICIT);
1419 #ifdef CONFIG_80211AC_VHT
1420 if (IsSupportedVHT(wireless_mode)) {
1421 /* 3 */ /* VHT */
1422 cur_beamform = psta->vhtpriv.beamform_cap;
1423
1424 /* We are Beamformee because the STA is Beamformer */
1425 if (TEST_FLAG(cur_beamform, BEAMFORMING_VHT_BEAMFORMER_ENABLE))
1426 beamform_cap = (BEAMFORMING_CAP)(beamform_cap | BEAMFORMEE_CAP_VHT_SU);
1427 /* We are Beamformer because the STA is Beamformee */
1428 if (TEST_FLAG(cur_beamform, BEAMFORMING_VHT_BEAMFORMEE_ENABLE))
1429 beamform_cap = (BEAMFORMING_CAP)(beamform_cap | BEAMFORMER_CAP_VHT_SU);
1430 }
1431 #endif /* CONFIG_80211AC_VHT */
1432
1433 if (beamform_cap == BEAMFORMING_CAP_NONE)
1434 return _FALSE;
1435
1436 RTW_INFO("Beamforming Config Capability = 0x%02X\n", beamform_cap);
1437
1438 pBeamformEntry = beamforming_get_entry_by_addr(pmlmepriv, ra, idx);
1439 if (pBeamformEntry == NULL) {
1440 pBeamformEntry = beamforming_add_entry(adapter, ra, aid, mac_id, bw, beamform_cap, idx);
1441 if (pBeamformEntry == NULL)
1442 return _FALSE;
1443 else
1444 pBeamformEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
1445 } else {
1446 /* Entry has been created. If entry is initialing or progressing then errors occur. */
1447 if (pBeamformEntry->beamforming_entry_state != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
1448 pBeamformEntry->beamforming_entry_state != BEAMFORMING_ENTRY_STATE_PROGRESSED) {
1449 RTW_INFO("Error State of Beamforming");
1450 return _FALSE;
1451 } else
1452 pBeamformEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
1453 }
1454
1455 pBeamformEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZED;
1456 psta->txbf_paid = pBeamformEntry->p_aid;
1457 psta->txbf_gid = pBeamformEntry->g_id;
1458
1459 RTW_INFO("%s Idx %d\n", __FUNCTION__, *idx);
1460 } else
1461 return _FALSE;
1462
1463 return _SUCCESS;
1464 }
1465
beamforming_deinit_entry(PADAPTER adapter,u8 * ra)1466 void beamforming_deinit_entry(PADAPTER adapter, u8 *ra)
1467 {
1468 u8 idx = 0;
1469 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1470
1471 if (beamforming_remove_entry(pmlmepriv, ra, &idx) == _TRUE)
1472 rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, (u8 *)&idx);
1473
1474 RTW_INFO("%s Idx %d\n", __FUNCTION__, idx);
1475 }
1476
beamforming_reset(PADAPTER adapter)1477 void beamforming_reset(PADAPTER adapter)
1478 {
1479 u8 idx = 0;
1480 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1481 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
1482
1483 for (idx = 0; idx < BEAMFORMING_ENTRY_NUM; idx++) {
1484 if (pBeamInfo->beamforming_entry[idx].bUsed == _TRUE) {
1485 pBeamInfo->beamforming_entry[idx].bUsed = _FALSE;
1486 pBeamInfo->beamforming_entry[idx].beamforming_entry_cap = BEAMFORMING_CAP_NONE;
1487 pBeamInfo->beamforming_entry[idx].beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
1488 rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, (u8 *)&idx);
1489 }
1490 }
1491
1492 RTW_INFO("%s\n", __FUNCTION__);
1493 }
1494
beamforming_sounding_fail(PADAPTER Adapter)1495 void beamforming_sounding_fail(PADAPTER Adapter)
1496 {
1497 struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
1498 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
1499 struct beamforming_entry *pEntry = &(pBeamInfo->beamforming_entry[pBeamInfo->beamforming_cur_idx]);
1500
1501 pEntry->bSound = _FALSE;
1502 rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&pBeamInfo->beamforming_cur_idx);
1503 beamforming_deinit_entry(Adapter, pEntry->mac_addr);
1504 }
1505
beamforming_check_sounding_success(PADAPTER Adapter,BOOLEAN status)1506 void beamforming_check_sounding_success(PADAPTER Adapter, BOOLEAN status)
1507 {
1508 struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
1509 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
1510 struct beamforming_entry *pEntry = &(pBeamInfo->beamforming_entry[pBeamInfo->beamforming_cur_idx]);
1511
1512 if (status == 1)
1513 pEntry->LogStatusFailCnt = 0;
1514 else {
1515 pEntry->LogStatusFailCnt++;
1516 RTW_INFO("%s LogStatusFailCnt %d\n", __FUNCTION__, pEntry->LogStatusFailCnt);
1517 }
1518 if (pEntry->LogStatusFailCnt > 20) {
1519 RTW_INFO("%s LogStatusFailCnt > 20, Stop SOUNDING\n", __FUNCTION__);
1520 /* pEntry->bSound = _FALSE; */
1521 /* rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&pBeamInfo->beamforming_cur_idx); */
1522 /* beamforming_deinit_entry(Adapter, pEntry->mac_addr); */
1523 beamforming_wk_cmd(Adapter, BEAMFORMING_CTRL_SOUNDING_FAIL, NULL, 0, 1);
1524 }
1525 }
1526
beamforming_enter(PADAPTER adapter,PVOID psta)1527 void beamforming_enter(PADAPTER adapter, PVOID psta)
1528 {
1529 u8 idx = 0xff;
1530
1531 if (beamforming_init_entry(adapter, (struct sta_info *)psta, &idx))
1532 rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_ENTER, (u8 *)&idx);
1533
1534 /* RTW_INFO("%s Idx %d\n", __FUNCTION__, idx); */
1535 }
1536
beamforming_leave(PADAPTER adapter,u8 * ra)1537 void beamforming_leave(PADAPTER adapter, u8 *ra)
1538 {
1539 if (ra == NULL)
1540 beamforming_reset(adapter);
1541 else
1542 beamforming_deinit_entry(adapter, ra);
1543
1544 beamforming_notify(adapter);
1545 }
1546
beamforming_get_beamform_cap(struct beamforming_info * pBeamInfo)1547 BEAMFORMING_CAP beamforming_get_beamform_cap(struct beamforming_info *pBeamInfo)
1548 {
1549 u8 i;
1550 BOOLEAN bSelfBeamformer = _FALSE;
1551 BOOLEAN bSelfBeamformee = _FALSE;
1552 struct beamforming_entry beamforming_entry;
1553 BEAMFORMING_CAP beamform_cap = BEAMFORMING_CAP_NONE;
1554
1555 for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
1556 beamforming_entry = pBeamInfo->beamforming_entry[i];
1557
1558 if (beamforming_entry.bUsed) {
1559 if ((beamforming_entry.beamforming_entry_cap & BEAMFORMEE_CAP_VHT_SU) ||
1560 (beamforming_entry.beamforming_entry_cap & BEAMFORMEE_CAP_HT_EXPLICIT))
1561 bSelfBeamformee = _TRUE;
1562 if ((beamforming_entry.beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU) ||
1563 (beamforming_entry.beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT))
1564 bSelfBeamformer = _TRUE;
1565 }
1566
1567 if (bSelfBeamformer && bSelfBeamformee)
1568 i = BEAMFORMING_ENTRY_NUM;
1569 }
1570
1571 if (bSelfBeamformer)
1572 beamform_cap |= BEAMFORMER_CAP;
1573 if (bSelfBeamformee)
1574 beamform_cap |= BEAMFORMEE_CAP;
1575
1576 return beamform_cap;
1577 }
1578
beamforming_watchdog(PADAPTER Adapter)1579 void beamforming_watchdog(PADAPTER Adapter)
1580 {
1581 struct beamforming_info *pBeamInfo = GET_BEAMFORM_INFO((&(Adapter->mlmepriv)));
1582
1583 if (pBeamInfo->beamforming_state != BEAMFORMING_STATE_START)
1584 return;
1585
1586 beamforming_dym_period(Adapter);
1587 beamforming_dym_ndpa_rate(Adapter);
1588 }
1589 #endif /* !RTW_BEAMFORMING_VERSION_2 */
1590 #endif/* #if (BEAMFORMING_SUPPORT ==0) - for diver defined beamforming*/
1591
beamforming_get_report_frame(PADAPTER Adapter,union recv_frame * precv_frame)1592 u32 beamforming_get_report_frame(PADAPTER Adapter, union recv_frame *precv_frame)
1593 {
1594 u32 ret = _SUCCESS;
1595 #if (BEAMFORMING_SUPPORT == 1)
1596 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
1597 PDM_ODM_T pDM_Odm = &(pHalData->odmpriv);
1598
1599 ret = Beamforming_GetReportFrame(pDM_Odm, precv_frame);
1600
1601 #else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
1602 #ifdef RTW_BEAMFORMING_VERSION_2
1603 struct beamformee_entry *pBeamformEntry = NULL;
1604 struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
1605 u8 *pframe = precv_frame->u.hdr.rx_data;
1606 u32 frame_len = precv_frame->u.hdr.len;
1607 u8 *ta;
1608 u8 *frame_body;
1609 u8 category, action;
1610 u8 *pMIMOCtrlField, *pCSIMatrix;
1611 u8 Nc = 0, Nr = 0, CH_W = 0;
1612 u16 CSIMatrixLen = 0;
1613
1614
1615 RTW_DBG("+%s\n", __FUNCTION__);
1616
1617 /* Memory comparison to see if CSI report is the same with previous one */
1618 ta = GetAddr2Ptr(pframe);
1619 pBeamformEntry = beamforming_get_bfee_entry_by_addr(Adapter, ta);
1620 if (!pBeamformEntry)
1621 return _FAIL;
1622
1623 frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
1624 category = frame_body[0];
1625 action = frame_body[1];
1626
1627 if ((category == RTW_WLAN_CATEGORY_VHT)
1628 && (action == RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING)) {
1629 pMIMOCtrlField = pframe + 26;
1630 Nc = ((*pMIMOCtrlField) & 0x7) + 1;
1631 Nr = (((*pMIMOCtrlField) & 0x38) >> 3) + 1;
1632 CH_W = (((*pMIMOCtrlField) & 0xC0) >> 6);
1633 /*
1634 * 24+(1+1+3)+2
1635 * ==> MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)
1636 */
1637 pCSIMatrix = pMIMOCtrlField + 3 + Nc;
1638 CSIMatrixLen = frame_len - 26 - 3 - Nc;
1639 } else if ((category == RTW_WLAN_CATEGORY_HT)
1640 && (action == RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING)) {
1641 pMIMOCtrlField = pframe + 26;
1642 Nc = ((*pMIMOCtrlField) & 0x3) + 1;
1643 Nr = (((*pMIMOCtrlField) & 0xC) >> 2) + 1;
1644 CH_W = ((*pMIMOCtrlField) & 0x10) >> 4;
1645 /*
1646 * 24+(1+1+6)+2
1647 * ==> MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)
1648 */
1649 pCSIMatrix = pMIMOCtrlField + 6 + Nr;
1650 CSIMatrixLen = frame_len - 26 - 6 - Nr;
1651 }
1652
1653 RTW_INFO("%s: pkt type=%d-%d, Nc=%d, Nr=%d, CH_W=%d\n",
1654 __FUNCTION__, category, action, Nc, Nr, CH_W);
1655 #else /* !RTW_BEAMFORMING_VERSION_2 */
1656 struct beamforming_entry *pBeamformEntry = NULL;
1657 struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
1658 u8 *pframe = precv_frame->u.hdr.rx_data;
1659 u32 frame_len = precv_frame->u.hdr.len;
1660 u8 *ta;
1661 u8 idx, offset;
1662
1663 /*RTW_INFO("beamforming_get_report_frame\n");*/
1664
1665 /*Memory comparison to see if CSI report is the same with previous one*/
1666 ta = GetAddr2Ptr(pframe);
1667 pBeamformEntry = beamforming_get_entry_by_addr(pmlmepriv, ta, &idx);
1668 if (pBeamformEntry->beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU)
1669 offset = 31; /*24+(1+1+3)+2 MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/
1670 else if (pBeamformEntry->beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)
1671 offset = 34; /*24+(1+1+6)+2 MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/
1672 else
1673 return ret;
1674
1675 /*RTW_INFO("%s MacId %d offset=%d\n", __FUNCTION__, pBeamformEntry->mac_id, offset);*/
1676
1677 if (_rtw_memcmp(pBeamformEntry->PreCsiReport + offset, pframe + offset, frame_len - offset) == _FALSE)
1678 pBeamformEntry->DefaultCsiCnt = 0;
1679 else
1680 pBeamformEntry->DefaultCsiCnt++;
1681
1682 _rtw_memcpy(&pBeamformEntry->PreCsiReport, pframe, frame_len);
1683
1684 pBeamformEntry->bDefaultCSI = _FALSE;
1685
1686 if (pBeamformEntry->DefaultCsiCnt > 20)
1687 pBeamformEntry->bDefaultCSI = _TRUE;
1688 else
1689 pBeamformEntry->bDefaultCSI = _FALSE;
1690 #endif /* !RTW_BEAMFORMING_VERSION_2 */
1691 #endif
1692 return ret;
1693 }
1694
beamforming_get_ndpa_frame(PADAPTER Adapter,union recv_frame * precv_frame)1695 void beamforming_get_ndpa_frame(PADAPTER Adapter, union recv_frame *precv_frame)
1696 {
1697 #if (BEAMFORMING_SUPPORT == 1)
1698 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
1699 PDM_ODM_T pDM_Odm = &(pHalData->odmpriv);
1700
1701 Beamforming_GetNDPAFrame(pDM_Odm, precv_frame);
1702
1703 #else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
1704 #ifdef RTW_BEAMFORMING_VERSION_2
1705 RTW_DBG("+%s\n", __FUNCTION__);
1706 #else /* !RTW_BEAMFORMING_VERSION_2 */
1707 u8 *ta;
1708 u8 idx, Sequence;
1709 u8 *pframe = precv_frame->u.hdr.rx_data;
1710 struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
1711 struct beamforming_entry *pBeamformEntry = NULL;
1712
1713 /*RTW_INFO("beamforming_get_ndpa_frame\n");*/
1714
1715 if (IS_HARDWARE_TYPE_8812(Adapter) == _FALSE)
1716 return;
1717 else if (GetFrameSubType(pframe) != WIFI_NDPA)
1718 return;
1719
1720 ta = GetAddr2Ptr(pframe);
1721 /*Remove signaling TA. */
1722 ta[0] = ta[0] & 0xFE;
1723
1724 pBeamformEntry = beamforming_get_entry_by_addr(pmlmepriv, ta, &idx);
1725
1726 if (pBeamformEntry == NULL)
1727 return;
1728 else if (!(pBeamformEntry->beamforming_entry_cap & BEAMFORMEE_CAP_VHT_SU))
1729 return;
1730 /*LogSuccess: As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is NO LONGER needed !2015-04-10, Jeffery*/
1731 /*ClockResetTimes: While BFer entry always doesn't receive our CSI, clock will reset again and again.So ClockResetTimes is limited to 5 times.2015-04-13, Jeffery*/
1732 else if ((pBeamformEntry->LogSuccess == 1) || (pBeamformEntry->ClockResetTimes == 5)) {
1733 RTW_INFO("[%s] LogSeq=%d, PreLogSeq=%d\n", __func__, pBeamformEntry->LogSeq, pBeamformEntry->PreLogSeq);
1734 return;
1735 }
1736
1737 Sequence = (pframe[16]) >> 2;
1738 RTW_INFO("[%s] Start, Sequence=%d, LogSeq=%d, PreLogSeq=%d, LogRetryCnt=%d, ClockResetTimes=%d, LogSuccess=%d\n",
1739 __func__, Sequence, pBeamformEntry->LogSeq, pBeamformEntry->PreLogSeq, pBeamformEntry->LogRetryCnt, pBeamformEntry->ClockResetTimes, pBeamformEntry->LogSuccess);
1740
1741 if ((pBeamformEntry->LogSeq != 0) && (pBeamformEntry->PreLogSeq != 0)) {
1742 /*Success condition*/
1743 if ((pBeamformEntry->LogSeq != Sequence) && (pBeamformEntry->PreLogSeq != pBeamformEntry->LogSeq)) {
1744 /* break option for clcok reset, 2015-03-30, Jeffery */
1745 pBeamformEntry->LogRetryCnt = 0;
1746 /*As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is no longer needed.*/
1747 /*That is, LogSuccess is NOT needed to be reset to zero, 2015-04-13, Jeffery*/
1748 pBeamformEntry->LogSuccess = 1;
1749
1750 } else {/*Fail condition*/
1751
1752 if (pBeamformEntry->LogRetryCnt == 5) {
1753 pBeamformEntry->ClockResetTimes++;
1754 pBeamformEntry->LogRetryCnt = 0;
1755
1756 RTW_INFO("[%s] Clock Reset!!! ClockResetTimes=%d\n", __func__, pBeamformEntry->ClockResetTimes);
1757 beamforming_wk_cmd(Adapter, BEAMFORMING_CTRL_SOUNDING_CLK, NULL, 0, 1);
1758
1759 } else
1760 pBeamformEntry->LogRetryCnt++;
1761 }
1762 }
1763
1764 /*Update LogSeq & PreLogSeq*/
1765 pBeamformEntry->PreLogSeq = pBeamformEntry->LogSeq;
1766 pBeamformEntry->LogSeq = Sequence;
1767 #endif /* !RTW_BEAMFORMING_VERSION_2 */
1768 #endif
1769
1770 }
1771
1772 /* octets in data header, no WEP */
1773 #define sMacHdrLng 24
1774 /* VHT Group ID (GID) Management Frame */
1775 #define FRAME_OFFSET_VHT_GID_MGNT_MEMBERSHIP_STATUS_ARRAY (sMacHdrLng + 2)
1776 #define FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY (sMacHdrLng + 10)
1777 /* VHT GID Management Frame Info */
1778 #define GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS(_pStart) LE_BITS_TO_1BYTE((_pStart), 0, 8)
1779 #define GET_VHT_GID_MGNT_INFO_USER_POSITION(_pStart) LE_BITS_TO_1BYTE((_pStart), 0, 8)
1780 /*
1781 * Description:
1782 * On VHT GID management frame by an MU beamformee.
1783 *
1784 * 2015.05.20. Created by tynli.
1785 */
beamforming_get_vht_gid_mgnt_frame(PADAPTER adapter,union recv_frame * precv_frame)1786 u32 beamforming_get_vht_gid_mgnt_frame(PADAPTER adapter, union recv_frame *precv_frame)
1787 {
1788 #ifdef RTW_BEAMFORMING_VERSION_2
1789 u8 *ta;
1790 u8 idx;
1791 u8 *pframe;
1792 u8 *pBuffer = NULL;
1793 struct beamformer_entry *bfer = NULL;
1794
1795
1796 RTW_DBG("+%s\n", __FUNCTION__);
1797
1798 pframe = precv_frame->u.hdr.rx_data;
1799 /* Get BFer entry by Addr2 */
1800 ta = GetAddr2Ptr(pframe);
1801 /* Remove signaling TA */
1802 ta[0] &= 0xFE;
1803
1804 bfer = beamforming_get_bfer_entry_by_addr(adapter, ta);
1805 if (!bfer) {
1806 RTW_INFO("%s: Cannot find BFer entry!!\n", __FUNCTION__);
1807 return _FAIL;
1808 }
1809
1810 /* Parsing Membership Status Array */
1811 pBuffer = pframe + FRAME_OFFSET_VHT_GID_MGNT_MEMBERSHIP_STATUS_ARRAY;
1812 for (idx = 0; idx < 8; idx++)
1813 bfer->gid_valid[idx] = GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS(pBuffer+idx);
1814
1815 /* Parsing User Position Array */
1816 pBuffer = pframe + FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY;
1817 for (idx = 0; idx < 16; idx++)
1818 bfer->user_position[idx] = GET_VHT_GID_MGNT_INFO_USER_POSITION(pBuffer+idx);
1819
1820 /* Config HW GID table */
1821 beamforming_wk_cmd(adapter, BEAMFORMING_CTRL_SET_GID_TABLE, (u8*)&bfer, sizeof(struct beamformer_entry *), 1);
1822
1823 return _SUCCESS;
1824 #else /* !RTW_BEAMFORMING_VERSION_2 */
1825 return _FAIL;
1826 #endif /* !RTW_BEAMFORMING_VERSION_2 */
1827 }
1828
beamforming_wk_hdl(_adapter * padapter,u8 type,u8 * pbuf)1829 void beamforming_wk_hdl(_adapter *padapter, u8 type, u8 *pbuf)
1830 {
1831 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
1832 PDM_ODM_T pDM_Odm = &(pHalData->odmpriv);
1833 _func_enter_;
1834
1835 #if (BEAMFORMING_SUPPORT == 1) /*(BEAMFORMING_SUPPORT == 1)- for PHYDM beamfoming*/
1836 switch (type) {
1837 case BEAMFORMING_CTRL_ENTER: {
1838 struct sta_info *psta = (PVOID)pbuf;
1839 u16 staIdx = psta->mac_id;
1840
1841 Beamforming_Enter(pDM_Odm, staIdx);
1842 break;
1843 }
1844 case BEAMFORMING_CTRL_LEAVE:
1845 Beamforming_Leave(pDM_Odm, pbuf);
1846 break;
1847 default:
1848 break;
1849
1850 }
1851 #else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
1852 switch (type) {
1853 case BEAMFORMING_CTRL_ENTER:
1854 beamforming_enter(padapter, (PVOID)pbuf);
1855 break;
1856
1857 case BEAMFORMING_CTRL_LEAVE:
1858 beamforming_leave(padapter, pbuf);
1859 break;
1860
1861 case BEAMFORMING_CTRL_SOUNDING_FAIL:
1862 beamforming_sounding_fail(padapter);
1863 break;
1864
1865 case BEAMFORMING_CTRL_SOUNDING_CLK:
1866 rtw_hal_set_hwreg(padapter, HW_VAR_SOUNDING_CLK, NULL);
1867 break;
1868
1869 case BEAMFORMING_CTRL_SET_GID_TABLE:
1870 rtw_hal_set_hwreg(padapter, HW_VAR_SOUNDING_SET_GID_TABLE, *(void**)pbuf);
1871 break;
1872
1873 default:
1874 break;
1875 }
1876 #endif
1877 _func_exit_;
1878 }
1879
beamforming_wk_cmd(_adapter * padapter,s32 type,u8 * pbuf,s32 size,u8 enqueue)1880 u8 beamforming_wk_cmd(_adapter *padapter, s32 type, u8 *pbuf, s32 size, u8 enqueue)
1881 {
1882 struct cmd_obj *ph2c;
1883 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1884 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1885 u8 res = _SUCCESS;
1886
1887 _func_enter_;
1888
1889 if (enqueue) {
1890 u8 *wk_buf;
1891
1892 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1893 if (ph2c == NULL) {
1894 res = _FAIL;
1895 goto exit;
1896 }
1897
1898 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1899 if (pdrvextra_cmd_parm == NULL) {
1900 rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1901 res = _FAIL;
1902 goto exit;
1903 }
1904
1905 if (pbuf != NULL) {
1906 wk_buf = rtw_zmalloc(size);
1907 if (wk_buf == NULL) {
1908 rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
1909 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
1910 res = _FAIL;
1911 goto exit;
1912 }
1913
1914 _rtw_memcpy(wk_buf, pbuf, size);
1915 } else {
1916 wk_buf = NULL;
1917 size = 0;
1918 }
1919
1920 pdrvextra_cmd_parm->ec_id = BEAMFORMING_WK_CID;
1921 pdrvextra_cmd_parm->type = type;
1922 pdrvextra_cmd_parm->size = size;
1923 pdrvextra_cmd_parm->pbuf = wk_buf;
1924
1925 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1926
1927 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1928 } else
1929 beamforming_wk_hdl(padapter, type, pbuf);
1930
1931 exit:
1932
1933 _func_exit_;
1934
1935 return res;
1936 }
1937
update_attrib_txbf_info(_adapter * padapter,struct pkt_attrib * pattrib,struct sta_info * psta)1938 void update_attrib_txbf_info(_adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)
1939 {
1940 if (psta) {
1941 pattrib->txbf_g_id = psta->txbf_gid;
1942 pattrib->txbf_p_aid = psta->txbf_paid;
1943 }
1944 }
1945
1946 #endif
1947