Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nu11secur1ty
GitHub Repository: nu11secur1ty/Kali-Linux
Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_beamforming.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_BEAMFORMING_C_
16
17
#include <drv_types.h>
18
#include <hal_data.h>
19
20
#ifdef CONFIG_BEAMFORMING
21
22
#ifdef RTW_BEAMFORMING_VERSION_2
23
24
struct ndpa_sta_info {
25
u16 aid:12;
26
u16 feedback_type:1;
27
u16 nc_index:3;
28
};
29
30
static void _get_txvector_parameter(PADAPTER adapter, struct sta_info *sta, u8 *g_id, u16 *p_aid)
31
{
32
struct mlme_priv *mlme;
33
u16 aid;
34
u8 *bssid;
35
u16 val16;
36
u8 i;
37
38
39
mlme = &adapter->mlmepriv;
40
41
if (check_fwstate(mlme, WIFI_AP_STATE)) {
42
/*
43
* Sent by an AP and addressed to a STA associated with that AP
44
* or sent by a DLS or TDLS STA in a direct path to
45
* a DLS or TDLS peer STA
46
*/
47
48
aid = sta->cmn.aid;
49
bssid = adapter_mac_addr(adapter);
50
RTW_INFO("%s: AID=0x%x BSSID=" MAC_FMT "\n",
51
__FUNCTION__, sta->cmn.aid, MAC_ARG(bssid));
52
53
/* AID[0:8] */
54
aid &= 0x1FF;
55
/* BSSID[44:47] xor BSSID[40:43] */
56
val16 = ((bssid[5] & 0xF0) >> 4) ^ (bssid[5] & 0xF);
57
/* (dec(AID[0:8]) + dec(BSSID)*2^5) mod 2^9 */
58
*p_aid = (aid + (val16 << 5)) & 0x1FF;
59
*g_id = 63;
60
} else if ((check_fwstate(mlme, WIFI_ADHOC_STATE) == _TRUE)
61
|| (check_fwstate(mlme, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {
62
/*
63
* Otherwise, includes
64
* 1. Sent to an IBSS STA
65
* 2. Sent by an AP to a non associated STA
66
* 3. Sent to a STA for which it is not known
67
* which condition is applicable
68
*/
69
*p_aid = 0;
70
*g_id = 63;
71
} else {
72
/* Addressed to AP */
73
bssid = sta->cmn.mac_addr;
74
RTW_INFO("%s: BSSID=" MAC_FMT "\n", __FUNCTION__, MAC_ARG(bssid));
75
76
/* BSSID[39:47] */
77
*p_aid = (bssid[5] << 1) | (bssid[4] >> 7);
78
*g_id = 0;
79
}
80
81
RTW_INFO("%s: GROUP_ID=0x%02x PARTIAL_AID=0x%04x\n",
82
__FUNCTION__, *g_id, *p_aid);
83
}
84
85
/*
86
* Parameters
87
* adapter struct _adapter*
88
* sta struct sta_info*
89
* sta_bf_cap beamforming capabe of sta
90
* sounding_dim Number of Sounding Dimensions
91
* comp_steering Compressed Steering Number of Beamformer Antennas Supported
92
*/
93
static void _get_sta_beamform_cap(PADAPTER adapter, struct sta_info *sta,
94
u8 *sta_bf_cap, u8 *sounding_dim, u8 *comp_steering)
95
{
96
struct beamforming_info *info;
97
struct ht_priv *ht;
98
#ifdef CONFIG_80211AC_VHT
99
struct vht_priv *vht;
100
#endif /* CONFIG_80211AC_VHT */
101
u16 bf_cap;
102
103
104
*sta_bf_cap = 0;
105
*sounding_dim = 0;
106
*comp_steering = 0;
107
108
info = GET_BEAMFORM_INFO(adapter);
109
ht = &adapter->mlmepriv.htpriv;
110
#ifdef CONFIG_80211AC_VHT
111
vht = &adapter->mlmepriv.vhtpriv;
112
#endif /* CONFIG_80211AC_VHT */
113
114
if (is_supported_ht(sta->wireless_mode) == _TRUE) {
115
/* HT */
116
bf_cap = ht->beamform_cap;
117
118
if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {
119
info->beamforming_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
120
*sta_bf_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
121
*sounding_dim = (bf_cap & BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP) >> 6;
122
}
123
if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {
124
info->beamforming_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
125
*sta_bf_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
126
*comp_steering = (bf_cap & BEAMFORMING_HT_BEAMFORMER_STEER_NUM) >> 4;
127
}
128
}
129
130
#ifdef CONFIG_80211AC_VHT
131
if (is_supported_vht(sta->wireless_mode) == _TRUE) {
132
/* VHT */
133
bf_cap = vht->beamform_cap;
134
135
/* We are SU Beamformee because the STA is SU Beamformer */
136
if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
137
info->beamforming_cap |= BEAMFORMEE_CAP_VHT_SU;
138
*sta_bf_cap |= BEAMFORMER_CAP_VHT_SU;
139
140
/* We are MU Beamformee because the STA is MU Beamformer */
141
if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) {
142
info->beamforming_cap |= BEAMFORMEE_CAP_VHT_MU;
143
*sta_bf_cap |= BEAMFORMER_CAP_VHT_MU;
144
}
145
146
*sounding_dim = (bf_cap & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM) >> 12;
147
}
148
/* We are SU Beamformer because the STA is SU Beamformee */
149
if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
150
info->beamforming_cap |= BEAMFORMER_CAP_VHT_SU;
151
*sta_bf_cap |= BEAMFORMEE_CAP_VHT_SU;
152
153
/* We are MU Beamformer because the STA is MU Beamformee */
154
if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
155
info->beamforming_cap |= BEAMFORMER_CAP_VHT_MU;
156
*sta_bf_cap |= BEAMFORMEE_CAP_VHT_MU;
157
}
158
159
*comp_steering = (bf_cap & BEAMFORMING_VHT_BEAMFORMER_STS_CAP) >> 8;
160
}
161
}
162
#endif /* CONFIG_80211AC_VHT */
163
}
164
165
static u8 _send_ht_ndpa_packet(PADAPTER adapter, u8 *ra, enum channel_width bw)
166
{
167
/* General */
168
struct xmit_priv *pxmitpriv;
169
struct mlme_ext_priv *pmlmeext;
170
struct mlme_ext_info *pmlmeinfo;
171
struct xmit_frame *pmgntframe;
172
/* Beamforming */
173
struct beamforming_info *info;
174
struct beamformee_entry *bfee;
175
struct ndpa_sta_info sta_info;
176
u8 ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xE0, 0x4C};
177
/* MISC */
178
struct pkt_attrib *attrib;
179
struct rtw_ieee80211_hdr *pwlanhdr;
180
enum MGN_RATE txrate;
181
u8 *pframe;
182
u16 duration = 0;
183
u8 aSifsTime = 0;
184
185
186
RTW_INFO("+%s: Send to " MAC_FMT "\n", __FUNCTION__, MAC_ARG(ra));
187
188
pxmitpriv = &adapter->xmitpriv;
189
pmlmeext = &adapter->mlmeextpriv;
190
pmlmeinfo = &pmlmeext->mlmext_info;
191
bfee = rtw_bf_bfee_get_entry_by_addr(adapter, ra);
192
if (!bfee) {
193
RTW_ERR("%s: Cann't find beamformee entry!\n", __FUNCTION__);
194
return _FALSE;
195
}
196
197
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
198
if (!pmgntframe) {
199
RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__);
200
return _FALSE;
201
}
202
203
txrate = beamforming_get_htndp_tx_rate(GET_PDM_ODM(adapter), bfee->comp_steering_num_of_bfer);
204
205
/* update attribute */
206
attrib = &pmgntframe->attrib;
207
update_mgntframe_attrib(adapter, attrib);
208
/*attrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */
209
attrib->subtype = WIFI_ACTION_NOACK;
210
attrib->bwmode = bw;
211
/*attrib->qsel = QSLT_MGNT;*/ /* set in update_mgntframe_attrib() */
212
attrib->order = 1;
213
attrib->rate = (u8)txrate;
214
attrib->bf_pkt_type = 0;
215
216
_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
217
pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
218
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
219
220
/* Frame control */
221
pwlanhdr->frame_ctl = 0;
222
set_frame_sub_type(pframe, attrib->subtype);
223
set_order_bit(pframe);
224
225
/* Duration */
226
if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
227
aSifsTime = 10;
228
else
229
aSifsTime = 16;
230
duration = 2 * aSifsTime + 40;
231
if (bw == CHANNEL_WIDTH_40)
232
duration += 87;
233
else
234
duration += 180;
235
set_duration(pframe, duration);
236
237
/* DA */
238
_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
239
/* SA */
240
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
241
/* BSSID */
242
_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
243
244
/* HT control field */
245
SET_HT_CTRL_CSI_STEERING(pframe + 24, 3);
246
SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe + 24, 1);
247
248
/*
249
* Frame Body
250
* Category field: vender-specific value, 0x7F
251
* OUI: 0x00E04C
252
*/
253
_rtw_memcpy(pframe + 28, ActionHdr, 4);
254
255
attrib->pktlen = 32;
256
attrib->last_txcmdsz = attrib->pktlen;
257
258
dump_mgntframe(adapter, pmgntframe);
259
260
return _TRUE;
261
}
262
263
static u8 _send_vht_ndpa_packet(PADAPTER adapter, u8 *ra, u16 aid, enum channel_width bw)
264
{
265
/* General */
266
struct xmit_priv *pxmitpriv;
267
struct mlme_ext_priv *pmlmeext;
268
struct xmit_frame *pmgntframe;
269
/* Beamforming */
270
struct beamforming_info *info;
271
struct beamformee_entry *bfee;
272
struct ndpa_sta_info sta_info;
273
/* MISC */
274
struct pkt_attrib *attrib;
275
struct rtw_ieee80211_hdr *pwlanhdr;
276
u8 *pframe;
277
enum MGN_RATE txrate;
278
u16 duration = 0;
279
u8 sequence = 0, aSifsTime = 0;
280
281
282
RTW_INFO("+%s: Send to " MAC_FMT "\n", __FUNCTION__, MAC_ARG(ra));
283
284
pxmitpriv = &adapter->xmitpriv;
285
pmlmeext = &adapter->mlmeextpriv;
286
info = GET_BEAMFORM_INFO(adapter);
287
bfee = rtw_bf_bfee_get_entry_by_addr(adapter, ra);
288
if (!bfee) {
289
RTW_ERR("%s: Cann't find beamformee entry!\n", __FUNCTION__);
290
return _FALSE;
291
}
292
293
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
294
if (!pmgntframe) {
295
RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__);
296
return _FALSE;
297
}
298
299
txrate = beamforming_get_vht_ndp_tx_rate(GET_PDM_ODM(adapter), bfee->comp_steering_num_of_bfer);
300
301
/* update attribute */
302
attrib = &pmgntframe->attrib;
303
update_mgntframe_attrib(adapter, attrib);
304
/*pattrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */
305
attrib->subtype = WIFI_NDPA;
306
attrib->bwmode = bw;
307
/*attrib->qsel = QSLT_MGNT;*/ /* set in update_mgntframe_attrib() */
308
attrib->rate = (u8)txrate;
309
attrib->bf_pkt_type = 0;
310
311
_rtw_memset(pmgntframe->buf_addr, 0, TXDESC_OFFSET + WLANHDR_OFFSET);
312
pframe = pmgntframe->buf_addr + TXDESC_OFFSET;
313
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
314
315
/* Frame control */
316
pwlanhdr->frame_ctl = 0;
317
set_frame_sub_type(pframe, attrib->subtype);
318
319
/* Duration */
320
if (is_supported_5g(pmlmeext->cur_wireless_mode) || is_supported_ht(pmlmeext->cur_wireless_mode))
321
aSifsTime = 16;
322
else
323
aSifsTime = 10;
324
duration = 2 * aSifsTime + 44;
325
if (bw == CHANNEL_WIDTH_80)
326
duration += 40;
327
else if (bw == CHANNEL_WIDTH_40)
328
duration += 87;
329
else
330
duration += 180;
331
set_duration(pframe, duration);
332
333
/* RA */
334
_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
335
336
/* TA */
337
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
338
339
/* Sounding Sequence, bit0~1 is reserved */
340
sequence = info->sounding_sequence << 2;
341
if (info->sounding_sequence >= 0x3f)
342
info->sounding_sequence = 0;
343
else
344
info->sounding_sequence++;
345
_rtw_memcpy(pframe + 16, &sequence, 1);
346
347
/* STA Info */
348
/*
349
* "AID12" Equal to 0 if the STA is an AP, mesh STA or
350
* STA that is a member of an IBSS
351
*/
352
if (check_fwstate(&adapter->mlmepriv, WIFI_AP_STATE) == _FALSE)
353
aid = 0;
354
sta_info.aid = aid;
355
/* "Feedback Type" set to 0 for SU */
356
sta_info.feedback_type = 0;
357
/* "Nc Index" reserved if the Feedback Type field indicates SU */
358
sta_info.nc_index = 0;
359
_rtw_memcpy(pframe + 17, (u8 *)&sta_info, 2);
360
361
attrib->pktlen = 19;
362
attrib->last_txcmdsz = attrib->pktlen;
363
364
dump_mgntframe(adapter, pmgntframe);
365
366
return _TRUE;
367
}
368
369
static u8 _send_vht_mu_ndpa_packet(PADAPTER adapter, enum channel_width bw)
370
{
371
/* General */
372
struct xmit_priv *pxmitpriv;
373
struct mlme_ext_priv *pmlmeext;
374
struct xmit_frame *pmgntframe;
375
/* Beamforming */
376
struct beamforming_info *info;
377
struct sounding_info *sounding;
378
struct beamformee_entry *bfee;
379
struct ndpa_sta_info sta_info;
380
/* MISC */
381
struct pkt_attrib *attrib;
382
struct rtw_ieee80211_hdr *pwlanhdr;
383
enum MGN_RATE txrate;
384
u8 *pframe;
385
u8 *ra = NULL;
386
u16 duration = 0;
387
u8 sequence = 0, aSifsTime = 0;
388
u8 i;
389
390
391
RTW_INFO("+%s\n", __FUNCTION__);
392
393
pxmitpriv = &adapter->xmitpriv;
394
pmlmeext = &adapter->mlmeextpriv;
395
info = GET_BEAMFORM_INFO(adapter);
396
sounding = &info->sounding_info;
397
398
txrate = MGN_VHT2SS_MCS0;
399
400
/*
401
* Fill the first MU BFee entry (STA1) MAC addr to destination address then
402
* HW will change A1 to broadcast addr.
403
* 2015.05.28. Suggested by SD1 Chunchu.
404
*/
405
bfee = &info->bfee_entry[sounding->mu_sounding_list[0]];
406
ra = bfee->mac_addr;
407
408
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
409
if (!pmgntframe) {
410
RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__);
411
return _FALSE;
412
}
413
414
/* update attribute */
415
attrib = &pmgntframe->attrib;
416
update_mgntframe_attrib(adapter, attrib);
417
/*attrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */
418
attrib->subtype = WIFI_NDPA;
419
attrib->bwmode = bw;
420
/*attrib->qsel = QSLT_MGNT;*/ /* set in update_mgntframe_attrib() */
421
attrib->rate = (u8)txrate;
422
/* Set TxBFPktType of Tx desc to unicast type if there is only one MU STA for HW design */
423
if (info->sounding_info.candidate_mu_bfee_cnt > 1)
424
attrib->bf_pkt_type = 1;
425
else
426
attrib->bf_pkt_type = 0;
427
428
_rtw_memset(pmgntframe->buf_addr, 0, TXDESC_OFFSET + WLANHDR_OFFSET);
429
pframe = pmgntframe->buf_addr + TXDESC_OFFSET;
430
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
431
432
/* Frame control */
433
pwlanhdr->frame_ctl = 0;
434
set_frame_sub_type(pframe, attrib->subtype);
435
436
/* Duration */
437
if (is_supported_5g(pmlmeext->cur_wireless_mode) || is_supported_ht(pmlmeext->cur_wireless_mode))
438
aSifsTime = 16;
439
else
440
aSifsTime = 10;
441
duration = 2 * aSifsTime + 44;
442
if (bw == CHANNEL_WIDTH_80)
443
duration += 40;
444
else if (bw == CHANNEL_WIDTH_40)
445
duration += 87;
446
else
447
duration += 180;
448
set_duration(pframe, duration);
449
450
/* RA */
451
_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
452
453
/* TA */
454
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
455
456
/* Sounding Sequence, bit0~1 is reserved */
457
sequence = info->sounding_sequence << 2;
458
if (info->sounding_sequence >= 0x3f)
459
info->sounding_sequence = 0;
460
else
461
info->sounding_sequence++;
462
_rtw_memcpy(pframe + 16, &sequence, 1);
463
464
attrib->pktlen = 17;
465
466
/*
467
* Construct STA info. for multiple STAs
468
* STA Info1, ..., STA Info n
469
*/
470
for (i = 0; i < sounding->candidate_mu_bfee_cnt; i++) {
471
bfee = &info->bfee_entry[sounding->mu_sounding_list[i]];
472
sta_info.aid = bfee->aid;
473
sta_info.feedback_type = 1; /* 1'b1: MU */
474
sta_info.nc_index = 0;
475
_rtw_memcpy(pframe + attrib->pktlen, (u8 *)&sta_info, 2);
476
attrib->pktlen += 2;
477
}
478
479
attrib->last_txcmdsz = attrib->pktlen;
480
481
dump_mgntframe(adapter, pmgntframe);
482
483
return _TRUE;
484
}
485
486
static u8 _send_bf_report_poll(PADAPTER adapter, u8 *ra, u8 bFinalPoll)
487
{
488
/* General */
489
struct xmit_priv *pxmitpriv;
490
struct xmit_frame *pmgntframe;
491
/* MISC */
492
struct pkt_attrib *attrib;
493
struct rtw_ieee80211_hdr *pwlanhdr;
494
u8 *pframe;
495
496
497
RTW_INFO("+%s: Send to " MAC_FMT "\n", __FUNCTION__, MAC_ARG(ra));
498
499
pxmitpriv = &adapter->xmitpriv;
500
501
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
502
if (!pmgntframe) {
503
RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__);
504
return _FALSE;
505
}
506
507
/* update attribute */
508
attrib = &pmgntframe->attrib;
509
update_mgntframe_attrib(adapter, attrib);
510
/*attrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */
511
attrib->subtype = WIFI_BF_REPORT_POLL;
512
attrib->bwmode = CHANNEL_WIDTH_20;
513
/*attrib->qsel = QSLT_MGNT;*/ /* set in update_mgntframe_attrib() */
514
attrib->rate = MGN_6M;
515
if (bFinalPoll)
516
attrib->bf_pkt_type = 3;
517
else
518
attrib->bf_pkt_type = 2;
519
520
_rtw_memset(pmgntframe->buf_addr, 0, TXDESC_OFFSET + WLANHDR_OFFSET);
521
pframe = pmgntframe->buf_addr + TXDESC_OFFSET;
522
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
523
524
/* Frame control */
525
pwlanhdr->frame_ctl = 0;
526
set_frame_sub_type(pframe, attrib->subtype);
527
528
/* Duration */
529
set_duration(pframe, 100);
530
531
/* RA */
532
_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
533
534
/* TA */
535
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
536
537
/* Feedback Segment Retransmission Bitmap */
538
pframe[16] = 0xFF;
539
540
attrib->pktlen = 17;
541
attrib->last_txcmdsz = attrib->pktlen;
542
543
dump_mgntframe(adapter, pmgntframe);
544
545
return _TRUE;
546
}
547
548
static void _sounding_update_min_period(PADAPTER adapter, u16 period, u8 leave)
549
{
550
struct beamforming_info *info;
551
struct beamformee_entry *bfee;
552
u8 i = 0;
553
u16 min_val = 0xFFFF;
554
555
556
info = GET_BEAMFORM_INFO(adapter);
557
558
if (_TRUE == leave) {
559
/*
560
* When a BFee left,
561
* we need to find the latest min sounding period
562
* from the remaining BFees
563
*/
564
for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
565
bfee = &info->bfee_entry[i];
566
if ((bfee->used == _TRUE)
567
&& (bfee->sound_period < min_val))
568
min_val = bfee->sound_period;
569
}
570
571
if (min_val == 0xFFFF)
572
info->sounding_info.min_sounding_period = 0;
573
else
574
info->sounding_info.min_sounding_period = min_val;
575
} else {
576
if ((info->sounding_info.min_sounding_period == 0)
577
|| (period < info->sounding_info.min_sounding_period))
578
info->sounding_info.min_sounding_period = period;
579
}
580
}
581
582
static void _sounding_init(struct sounding_info *sounding)
583
{
584
_rtw_memset(sounding->su_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_SU);
585
_rtw_memset(sounding->mu_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_MU);
586
sounding->state = SOUNDING_STATE_NONE;
587
sounding->su_bfee_curidx = 0xFF;
588
sounding->candidate_mu_bfee_cnt = 0;
589
sounding->min_sounding_period = 0;
590
sounding->sound_remain_cnt_per_period = 0;
591
}
592
593
static void _sounding_reset_vars(PADAPTER adapter)
594
{
595
struct beamforming_info *info;
596
struct sounding_info *sounding;
597
u8 idx;
598
599
600
info = GET_BEAMFORM_INFO(adapter);
601
sounding = &info->sounding_info;
602
603
_rtw_memset(sounding->su_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_SU);
604
_rtw_memset(sounding->mu_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_MU);
605
sounding->su_bfee_curidx = 0xFF;
606
sounding->candidate_mu_bfee_cnt = 0;
607
608
/* Clear bSound flag for the new period */
609
for (idx = 0; idx < MAX_BEAMFORMEE_ENTRY_NUM; idx++) {
610
if ((info->bfee_entry[idx].used == _TRUE)
611
&& (info->bfee_entry[idx].sounding == _TRUE)) {
612
info->bfee_entry[idx].sounding = _FALSE;
613
info->bfee_entry[idx].bCandidateSoundingPeer = _FALSE;
614
}
615
}
616
}
617
618
/*
619
* Return
620
* 0 Prepare sounding list OK
621
* -1 Fail to prepare sounding list, because no beamformee need to souding
622
* -2 Fail to prepare sounding list, because beamformee state not ready
623
*
624
*/
625
static int _sounding_get_list(PADAPTER adapter)
626
{
627
struct beamforming_info *info;
628
struct sounding_info *sounding;
629
struct beamformee_entry *bfee;
630
u8 i, mu_idx = 0, su_idx = 0, not_ready = 0;
631
int ret = 0;
632
633
634
info = GET_BEAMFORM_INFO(adapter);
635
sounding = &info->sounding_info;
636
637
/* Add MU BFee list first because MU priority is higher than SU */
638
for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
639
bfee = &info->bfee_entry[i];
640
if (bfee->used == _FALSE)
641
continue;
642
643
if (bfee->state != BEAMFORM_ENTRY_HW_STATE_ADDED) {
644
RTW_ERR("%s: Invalid BFee idx(%d) Hw state=%d\n", __FUNCTION__, i, bfee->state);
645
not_ready++;
646
continue;
647
}
648
649
/*
650
* Decrease BFee's SoundCnt per period
651
* If the remain count is 0,
652
* then it can be sounded at this time
653
*/
654
if (bfee->SoundCnt) {
655
bfee->SoundCnt--;
656
if (bfee->SoundCnt)
657
continue;
658
}
659
660
/*
661
* <tynli_Note>
662
* If the STA supports MU BFee capability then we add it to MUSoundingList directly
663
* because we can only sound one STA by unicast NDPA with MU cap enabled to get correct channel info.
664
* Suggested by BB team Luke Lee. 2015.11.25.
665
*/
666
if (bfee->cap & BEAMFORMEE_CAP_VHT_MU) {
667
/* MU BFee */
668
if (mu_idx >= MAX_NUM_BEAMFORMEE_MU) {
669
RTW_ERR("%s: Too much MU bfee entry(Limit:%d)\n", __FUNCTION__, MAX_NUM_BEAMFORMEE_MU);
670
continue;
671
}
672
673
if (bfee->bApplySounding == _TRUE) {
674
bfee->bCandidateSoundingPeer = _TRUE;
675
bfee->SoundCnt = GetInitSoundCnt(bfee->sound_period, sounding->min_sounding_period);
676
sounding->mu_sounding_list[mu_idx] = i;
677
mu_idx++;
678
}
679
} else if (bfee->cap & (BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) {
680
/* SU BFee (HT/VHT) */
681
if (su_idx >= MAX_NUM_BEAMFORMEE_SU) {
682
RTW_ERR("%s: Too much SU bfee entry(Limit:%d)\n", __FUNCTION__, MAX_NUM_BEAMFORMEE_SU);
683
continue;
684
}
685
686
if (bfee->bDeleteSounding == _TRUE) {
687
sounding->su_sounding_list[su_idx] = i;
688
su_idx++;
689
} else if ((bfee->bApplySounding == _TRUE)
690
&& (bfee->bSuspendSUCap == _FALSE)) {
691
bfee->bCandidateSoundingPeer = _TRUE;
692
bfee->SoundCnt = GetInitSoundCnt(bfee->sound_period, sounding->min_sounding_period);
693
sounding->su_sounding_list[su_idx] = i;
694
su_idx++;
695
}
696
}
697
}
698
699
sounding->candidate_mu_bfee_cnt = mu_idx;
700
701
if (su_idx + mu_idx == 0) {
702
ret = -1;
703
if (not_ready)
704
ret = -2;
705
}
706
707
RTW_INFO("-%s: There are %d SU and %d MU BFees in this sounding period\n", __FUNCTION__, su_idx, mu_idx);
708
709
return ret;
710
}
711
712
static void _sounding_handler(PADAPTER adapter)
713
{
714
struct beamforming_info *info;
715
struct sounding_info *sounding;
716
struct beamformee_entry *bfee;
717
u8 su_idx, i;
718
u32 timeout_period = 0;
719
u8 set_timer = _FALSE;
720
int ret = 0;
721
static u16 wait_cnt = 0;
722
723
724
info = GET_BEAMFORM_INFO(adapter);
725
sounding = &info->sounding_info;
726
727
RTW_DBG("+%s: state=%d\n", __FUNCTION__, sounding->state);
728
if ((sounding->state != SOUNDING_STATE_INIT)
729
&& (sounding->state != SOUNDING_STATE_SU_SOUNDDOWN)
730
&& (sounding->state != SOUNDING_STATE_MU_SOUNDDOWN)
731
&& (sounding->state != SOUNDING_STATE_SOUNDING_TIMEOUT)) {
732
RTW_WARN("%s: Invalid State(%d) and return!\n", __FUNCTION__, sounding->state);
733
return;
734
}
735
736
if (sounding->state == SOUNDING_STATE_INIT) {
737
RTW_INFO("%s: Sounding start\n", __FUNCTION__);
738
739
/* Init Var */
740
_sounding_reset_vars(adapter);
741
742
/* Get the sounding list of this sounding period */
743
ret = _sounding_get_list(adapter);
744
if (ret == -1) {
745
wait_cnt = 0;
746
sounding->state = SOUNDING_STATE_NONE;
747
RTW_ERR("%s: No BFees found, set to SOUNDING_STATE_NONE\n", __FUNCTION__);
748
info->sounding_running--;
749
return;
750
}
751
if (ret == -2) {
752
RTW_WARN("%s: Temporarily cann't find BFee to sounding\n", __FUNCTION__);
753
if (wait_cnt < 5) {
754
wait_cnt++;
755
} else {
756
wait_cnt = 0;
757
sounding->state = SOUNDING_STATE_NONE;
758
RTW_ERR("%s: Wait changing state timeout!! Set to SOUNDING_STATE_NONE\n", __FUNCTION__);
759
}
760
info->sounding_running--;
761
return;
762
}
763
if (ret != 0) {
764
wait_cnt = 0;
765
RTW_ERR("%s: Unkown state(%d)!\n", __FUNCTION__, ret);
766
info->sounding_running--;
767
return;
768
769
}
770
771
wait_cnt = 0;
772
773
if (check_fwstate(&adapter->mlmepriv, WIFI_SITE_MONITOR) == _TRUE) {
774
RTW_INFO("%s: Sounding abort! scanning APs...\n", __FUNCTION__);
775
info->sounding_running--;
776
return;
777
}
778
779
rtw_ps_deny(adapter, PS_DENY_BEAMFORMING);
780
LeaveAllPowerSaveModeDirect(adapter);
781
}
782
783
/* Get non-sound SU BFee index */
784
for (i = 0; i < MAX_NUM_BEAMFORMEE_SU; i++) {
785
su_idx = sounding->su_sounding_list[i];
786
if (su_idx >= MAX_BEAMFORMEE_ENTRY_NUM)
787
continue;
788
bfee = &info->bfee_entry[su_idx];
789
if (_FALSE == bfee->sounding)
790
break;
791
}
792
if (i < MAX_NUM_BEAMFORMEE_SU) {
793
sounding->su_bfee_curidx = su_idx;
794
/* Set to sounding start state */
795
sounding->state = SOUNDING_STATE_SU_START;
796
RTW_DBG("%s: Set to SOUNDING_STATE_SU_START\n", __FUNCTION__);
797
798
bfee->sounding = _TRUE;
799
/* Reset sounding timeout flag for the new sounding */
800
bfee->bSoundingTimeout = _FALSE;
801
802
if (_TRUE == bfee->bDeleteSounding) {
803
u8 res = _FALSE;
804
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_END_PERIOD, &res, 1, 0);
805
return;
806
}
807
808
/* Start SU sounding */
809
if (bfee->cap & BEAMFORMEE_CAP_VHT_SU)
810
_send_vht_ndpa_packet(adapter, bfee->mac_addr, bfee->aid, bfee->sound_bw);
811
else if (bfee->cap & BEAMFORMEE_CAP_HT_EXPLICIT)
812
_send_ht_ndpa_packet(adapter, bfee->mac_addr, bfee->sound_bw);
813
814
/* Set sounding timeout timer */
815
_set_timer(&info->sounding_timeout_timer, SU_SOUNDING_TIMEOUT);
816
return;
817
}
818
819
if (sounding->candidate_mu_bfee_cnt > 0) {
820
/*
821
* If there is no SU BFee then find MU BFee and perform MU sounding
822
*
823
* <tynli_note> Need to check the MU starting condition. 2015.12.15.
824
*/
825
sounding->state = SOUNDING_STATE_MU_START;
826
RTW_DBG("%s: Set to SOUNDING_STATE_MU_START\n", __FUNCTION__);
827
828
/* Update MU BFee info */
829
for (i = 0; i < sounding->candidate_mu_bfee_cnt; i++) {
830
bfee = &info->bfee_entry[sounding->mu_sounding_list[i]];
831
bfee->sounding = _TRUE;
832
}
833
834
/* Send MU NDPA */
835
bfee = &info->bfee_entry[sounding->mu_sounding_list[0]];
836
_send_vht_mu_ndpa_packet(adapter, bfee->sound_bw);
837
838
/* Send BF report poll if more than 1 MU STA */
839
for (i = 1; i < sounding->candidate_mu_bfee_cnt; i++) {
840
bfee = &info->bfee_entry[sounding->mu_sounding_list[i]];
841
842
if (i == (sounding->candidate_mu_bfee_cnt - 1))/* The last STA*/
843
_send_bf_report_poll(adapter, bfee->mac_addr, _TRUE);
844
else
845
_send_bf_report_poll(adapter, bfee->mac_addr, _FALSE);
846
}
847
848
sounding->candidate_mu_bfee_cnt = 0;
849
850
/* Set sounding timeout timer */
851
_set_timer(&info->sounding_timeout_timer, MU_SOUNDING_TIMEOUT);
852
return;
853
}
854
855
info->sounding_running--;
856
sounding->state = SOUNDING_STATE_INIT;
857
RTW_INFO("%s: Sounding finished!\n", __FUNCTION__);
858
rtw_ps_deny_cancel(adapter, PS_DENY_BEAMFORMING);
859
}
860
861
static void _sounding_force_stop(PADAPTER adapter)
862
{
863
struct beamforming_info *info;
864
struct sounding_info *sounding;
865
866
info = GET_BEAMFORM_INFO(adapter);
867
sounding = &info->sounding_info;
868
869
if ((sounding->state == SOUNDING_STATE_SU_START)
870
|| (sounding->state == SOUNDING_STATE_MU_START)) {
871
u8 res = _FALSE;
872
_cancel_timer_ex(&info->sounding_timeout_timer);
873
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_END_PERIOD, &res, 1, 1);
874
return;
875
}
876
877
info->sounding_running--;
878
sounding->state = SOUNDING_STATE_INIT;
879
RTW_INFO("%s: Sounding finished!\n", __FUNCTION__);
880
rtw_ps_deny_cancel(adapter, PS_DENY_BEAMFORMING);
881
}
882
883
static void _sounding_timer_handler(void *FunctionContext)
884
{
885
PADAPTER adapter;
886
struct beamforming_info *info;
887
struct sounding_info *sounding;
888
static u8 delay = 0;
889
890
891
RTW_DBG("+%s\n", __FUNCTION__);
892
893
adapter = (PADAPTER)FunctionContext;
894
info = GET_BEAMFORM_INFO(adapter);
895
sounding = &info->sounding_info;
896
897
if (SOUNDING_STATE_NONE == sounding->state) {
898
RTW_INFO("%s: Stop!\n", __FUNCTION__);
899
if (info->sounding_running)
900
RTW_WARN("%s: souding_running=%d when thread stop!\n",
901
__FUNCTION__, info->sounding_running);
902
return;
903
}
904
905
_set_timer(&info->sounding_timer, sounding->min_sounding_period);
906
907
if (!info->sounding_running) {
908
if (SOUNDING_STATE_INIT != sounding->state) {
909
RTW_WARN("%s: state(%d) != SOUNDING_STATE_INIT!!\n", __FUNCTION__, sounding->state);
910
sounding->state = SOUNDING_STATE_INIT;
911
}
912
delay = 0;
913
info->sounding_running++;
914
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_START_PERIOD, NULL, 0, 1);
915
} else {
916
if (delay != 0xFF)
917
delay++;
918
RTW_WARN("%s: souding is still processing...(state:%d, running:%d, delay:%d)\n",
919
__FUNCTION__, sounding->state, info->sounding_running, delay);
920
if (delay > 3) {
921
RTW_WARN("%s: Stop sounding!!\n", __FUNCTION__);
922
_sounding_force_stop(adapter);
923
}
924
}
925
}
926
927
static void _sounding_timeout_timer_handler(void *FunctionContext)
928
{
929
PADAPTER adapter;
930
struct beamforming_info *info;
931
struct sounding_info *sounding;
932
struct beamformee_entry *bfee;
933
934
935
RTW_WARN("+%s\n", __FUNCTION__);
936
937
adapter = (PADAPTER)FunctionContext;
938
info = GET_BEAMFORM_INFO(adapter);
939
sounding = &info->sounding_info;
940
941
if (SOUNDING_STATE_SU_START == sounding->state) {
942
sounding->state = SOUNDING_STATE_SOUNDING_TIMEOUT;
943
RTW_ERR("%s: Set to SU SOUNDING_STATE_SOUNDING_TIMEOUT\n", __FUNCTION__);
944
/* SU BFee */
945
bfee = &info->bfee_entry[sounding->su_bfee_curidx];
946
bfee->bSoundingTimeout = _TRUE;
947
RTW_WARN("%s: The BFee entry[%d] is Sounding Timeout!\n", __FUNCTION__, sounding->su_bfee_curidx);
948
} else if (SOUNDING_STATE_MU_START == sounding->state) {
949
sounding->state = SOUNDING_STATE_SOUNDING_TIMEOUT;
950
RTW_ERR("%s: Set to MU SOUNDING_STATE_SOUNDING_TIMEOUT\n", __FUNCTION__);
951
} else {
952
RTW_WARN("%s: unexpected sounding state:0x%02x\n", __FUNCTION__, sounding->state);
953
return;
954
}
955
956
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_START_PERIOD, NULL, 0, 1);
957
}
958
959
static struct beamformer_entry *_bfer_get_free_entry(PADAPTER adapter)
960
{
961
u8 i = 0;
962
struct beamforming_info *info;
963
struct beamformer_entry *bfer;
964
965
966
info = GET_BEAMFORM_INFO(adapter);
967
968
for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) {
969
bfer = &info->bfer_entry[i];
970
if (bfer->used == _FALSE)
971
return bfer;
972
}
973
974
return NULL;
975
}
976
977
static struct beamformer_entry *_bfer_get_entry_by_addr(PADAPTER adapter, u8 *ra)
978
{
979
u8 i = 0;
980
struct beamforming_info *info;
981
struct beamformer_entry *bfer;
982
983
984
info = GET_BEAMFORM_INFO(adapter);
985
986
for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) {
987
bfer = &info->bfer_entry[i];
988
if (bfer->used == _FALSE)
989
continue;
990
if (_rtw_memcmp(ra, bfer->mac_addr, ETH_ALEN) == _TRUE)
991
return bfer;
992
}
993
994
return NULL;
995
}
996
997
static struct beamformer_entry *_bfer_add_entry(PADAPTER adapter,
998
struct sta_info *sta, u8 bf_cap, u8 sounding_dim, u8 comp_steering)
999
{
1000
struct mlme_priv *mlme;
1001
struct beamforming_info *info;
1002
struct beamformer_entry *bfer;
1003
u8 *bssid;
1004
u16 val16;
1005
u8 i;
1006
1007
1008
mlme = &adapter->mlmepriv;
1009
info = GET_BEAMFORM_INFO(adapter);
1010
1011
bfer = _bfer_get_entry_by_addr(adapter, sta->cmn.mac_addr);
1012
if (!bfer) {
1013
bfer = _bfer_get_free_entry(adapter);
1014
if (!bfer)
1015
return NULL;
1016
}
1017
1018
bfer->used = _TRUE;
1019
_get_txvector_parameter(adapter, sta, &bfer->g_id, &bfer->p_aid);
1020
_rtw_memcpy(bfer->mac_addr, sta->cmn.mac_addr, ETH_ALEN);
1021
bfer->cap = bf_cap;
1022
bfer->state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT;
1023
bfer->NumofSoundingDim = sounding_dim;
1024
1025
if (TEST_FLAG(bf_cap, BEAMFORMER_CAP_VHT_MU)) {
1026
info->beamformer_mu_cnt += 1;
1027
bfer->aid = sta->cmn.aid;
1028
} else if (TEST_FLAG(bf_cap, BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT)) {
1029
info->beamformer_su_cnt += 1;
1030
1031
/* Record HW idx info */
1032
for (i = 0; i < MAX_NUM_BEAMFORMER_SU; i++) {
1033
if ((info->beamformer_su_reg_maping & BIT(i)) == 0) {
1034
info->beamformer_su_reg_maping |= BIT(i);
1035
bfer->su_reg_index = i;
1036
break;
1037
}
1038
}
1039
RTW_INFO("%s: Add BFer entry beamformer_su_reg_maping=%#x, su_reg_index=%d\n",
1040
__FUNCTION__, info->beamformer_su_reg_maping, bfer->su_reg_index);
1041
}
1042
1043
return bfer;
1044
}
1045
1046
static void _bfer_remove_entry(PADAPTER adapter, struct beamformer_entry *entry)
1047
{
1048
struct beamforming_info *info;
1049
1050
1051
info = GET_BEAMFORM_INFO(adapter);
1052
1053
entry->state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT;
1054
1055
if (TEST_FLAG(entry->cap, BEAMFORMER_CAP_VHT_MU)) {
1056
info->beamformer_mu_cnt -= 1;
1057
_rtw_memset(entry->gid_valid, 0, 8);
1058
_rtw_memset(entry->user_position, 0, 16);
1059
} else if (TEST_FLAG(entry->cap, BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT)) {
1060
info->beamformer_su_cnt -= 1;
1061
}
1062
1063
if (info->beamformer_mu_cnt == 0)
1064
info->beamforming_cap &= ~BEAMFORMEE_CAP_VHT_MU;
1065
if (info->beamformer_su_cnt == 0)
1066
info->beamforming_cap &= ~(BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT);
1067
}
1068
1069
static u8 _bfer_set_entry_gid(PADAPTER adapter, u8 *addr, u8 *gid, u8 *position)
1070
{
1071
struct beamformer_entry bfer;
1072
1073
memset(&bfer, 0, sizeof(bfer));
1074
memcpy(bfer.mac_addr, addr, ETH_ALEN);
1075
1076
/* Parsing Membership Status Array */
1077
memcpy(bfer.gid_valid, gid, 8);
1078
1079
/* Parsing User Position Array */
1080
memcpy(bfer.user_position, position, 16);
1081
1082
/* Config HW GID table */
1083
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_GID_TABLE, (u8 *) &bfer,
1084
sizeof(bfer), 1);
1085
1086
return _SUCCESS;
1087
}
1088
1089
static struct beamformee_entry *_bfee_get_free_entry(PADAPTER adapter)
1090
{
1091
u8 i = 0;
1092
struct beamforming_info *info;
1093
struct beamformee_entry *bfee;
1094
1095
1096
info = GET_BEAMFORM_INFO(adapter);
1097
1098
for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
1099
bfee = &info->bfee_entry[i];
1100
if (bfee->used == _FALSE)
1101
return bfee;
1102
}
1103
1104
return NULL;
1105
}
1106
1107
static struct beamformee_entry *_bfee_get_entry_by_addr(PADAPTER adapter, u8 *ra)
1108
{
1109
u8 i = 0;
1110
struct beamforming_info *info;
1111
struct beamformee_entry *bfee;
1112
1113
1114
info = GET_BEAMFORM_INFO(adapter);
1115
1116
for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
1117
bfee = &info->bfee_entry[i];
1118
if (bfee->used == _FALSE)
1119
continue;
1120
if (_rtw_memcmp(ra, bfee->mac_addr, ETH_ALEN) == _TRUE)
1121
return bfee;
1122
}
1123
1124
return NULL;
1125
}
1126
1127
static u8 _bfee_get_first_su_entry_idx(PADAPTER adapter, struct beamformee_entry *ignore)
1128
{
1129
struct beamforming_info *info;
1130
struct beamformee_entry *bfee;
1131
u8 i;
1132
1133
1134
info = GET_BEAMFORM_INFO(adapter);
1135
1136
for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
1137
bfee = &info->bfee_entry[i];
1138
if (ignore && (bfee == ignore))
1139
continue;
1140
if (bfee->used == _FALSE)
1141
continue;
1142
if ((!TEST_FLAG(bfee->cap, BEAMFORMEE_CAP_VHT_MU))
1143
&& TEST_FLAG(bfee->cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT))
1144
return i;
1145
}
1146
1147
return 0xFF;
1148
}
1149
1150
/*
1151
* Description:
1152
* Get the first entry index of MU Beamformee.
1153
*
1154
* Return Value:
1155
* Index of the first MU sta, or 0xFF for invalid index.
1156
*
1157
* 2015.05.25. Created by tynli.
1158
*
1159
*/
1160
static u8 _bfee_get_first_mu_entry_idx(PADAPTER adapter, struct beamformee_entry *ignore)
1161
{
1162
struct beamforming_info *info;
1163
struct beamformee_entry *bfee;
1164
u8 i;
1165
1166
1167
info = GET_BEAMFORM_INFO(adapter);
1168
1169
for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
1170
bfee = &info->bfee_entry[i];
1171
if (ignore && (bfee == ignore))
1172
continue;
1173
if (bfee->used == _FALSE)
1174
continue;
1175
if (TEST_FLAG(bfee->cap, BEAMFORMEE_CAP_VHT_MU))
1176
return i;
1177
}
1178
1179
return 0xFF;
1180
}
1181
1182
static struct beamformee_entry *_bfee_add_entry(PADAPTER adapter,
1183
struct sta_info *sta, u8 bf_cap, u8 sounding_dim, u8 comp_steering)
1184
{
1185
struct mlme_priv *mlme;
1186
struct beamforming_info *info;
1187
struct beamformee_entry *bfee;
1188
u8 *bssid;
1189
u16 val16;
1190
u8 i;
1191
1192
1193
mlme = &adapter->mlmepriv;
1194
info = GET_BEAMFORM_INFO(adapter);
1195
1196
bfee = _bfee_get_entry_by_addr(adapter, sta->cmn.mac_addr);
1197
if (!bfee) {
1198
bfee = _bfee_get_free_entry(adapter);
1199
if (!bfee)
1200
return NULL;
1201
}
1202
1203
bfee->used = _TRUE;
1204
bfee->aid = sta->cmn.aid;
1205
bfee->mac_id = sta->cmn.mac_id;
1206
bfee->sound_bw = sta->cmn.bw_mode;
1207
1208
_get_txvector_parameter(adapter, sta, &bfee->g_id, &bfee->p_aid);
1209
sta->cmn.bf_info.g_id = bfee->g_id;
1210
sta->cmn.bf_info.p_aid = bfee->p_aid;
1211
1212
_rtw_memcpy(bfee->mac_addr, sta->cmn.mac_addr, ETH_ALEN);
1213
bfee->txbf = _FALSE;
1214
bfee->sounding = _FALSE;
1215
bfee->sound_period = 40;
1216
_sounding_update_min_period(adapter, bfee->sound_period, _FALSE);
1217
bfee->SoundCnt = GetInitSoundCnt(bfee->sound_period, info->sounding_info.min_sounding_period);
1218
bfee->cap = bf_cap;
1219
bfee->state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT;
1220
1221
bfee->bCandidateSoundingPeer = _FALSE;
1222
bfee->bSoundingTimeout = _FALSE;
1223
bfee->bDeleteSounding = _FALSE;
1224
bfee->bApplySounding = _TRUE;
1225
1226
bfee->tx_timestamp = 0;
1227
bfee->tx_bytes = 0;
1228
1229
bfee->LogStatusFailCnt = 0;
1230
bfee->NumofSoundingDim = sounding_dim;
1231
bfee->comp_steering_num_of_bfer = comp_steering;
1232
bfee->bSuspendSUCap = _FALSE;
1233
1234
if (TEST_FLAG(bf_cap, BEAMFORMEE_CAP_VHT_MU)) {
1235
info->beamformee_mu_cnt += 1;
1236
info->first_mu_bfee_index = _bfee_get_first_mu_entry_idx(adapter, NULL);
1237
1238
if (_TRUE == info->bEnableSUTxBFWorkAround) {
1239
/* When the first MU BFee added, discard SU BFee bfee's capability */
1240
if ((info->beamformee_mu_cnt == 1) && (info->beamformee_su_cnt > 0)) {
1241
if (info->TargetSUBFee) {
1242
info->TargetSUBFee->bSuspendSUCap = _TRUE;
1243
info->TargetSUBFee->bDeleteSounding = _TRUE;
1244
} else {
1245
RTW_ERR("%s: UNEXPECTED!! info->TargetSUBFee is NULL!", __FUNCTION__);
1246
}
1247
info->TargetSUBFee = NULL;
1248
_rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO));
1249
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_CSI_REPORT, (u8*)&info->TargetCSIInfo, sizeof(struct _RT_CSI_INFO), 0);
1250
}
1251
}
1252
1253
/* Record HW idx info */
1254
for (i = 0; i < MAX_NUM_BEAMFORMEE_MU; i++) {
1255
if ((info->beamformee_mu_reg_maping & BIT(i)) == 0) {
1256
info->beamformee_mu_reg_maping |= BIT(i);
1257
bfee->mu_reg_index = i;
1258
break;
1259
}
1260
}
1261
RTW_INFO("%s: Add BFee entry beamformee_mu_reg_maping=%#x, mu_reg_index=%d\n",
1262
__FUNCTION__, info->beamformee_mu_reg_maping, bfee->mu_reg_index);
1263
1264
} else if (TEST_FLAG(bf_cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) {
1265
info->beamformee_su_cnt += 1;
1266
1267
if (_TRUE == info->bEnableSUTxBFWorkAround) {
1268
/* Record the first SU BFee index. We only allow the first SU BFee to be sound */
1269
if ((info->beamformee_su_cnt == 1) && (info->beamformee_mu_cnt == 0)) {
1270
info->TargetSUBFee = bfee;
1271
_rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO));
1272
bfee->bSuspendSUCap = _FALSE;
1273
} else {
1274
bfee->bSuspendSUCap = _TRUE;
1275
}
1276
}
1277
1278
/* Record HW idx info */
1279
for (i = 0; i < MAX_NUM_BEAMFORMEE_SU; i++) {
1280
if ((info->beamformee_su_reg_maping & BIT(i)) == 0) {
1281
info->beamformee_su_reg_maping |= BIT(i);
1282
bfee->su_reg_index = i;
1283
break;
1284
}
1285
}
1286
RTW_INFO("%s: Add BFee entry beamformee_su_reg_maping=%#x, su_reg_index=%d\n",
1287
__FUNCTION__, info->beamformee_su_reg_maping, bfee->su_reg_index);
1288
}
1289
1290
return bfee;
1291
}
1292
1293
static void _bfee_remove_entry(PADAPTER adapter, struct beamformee_entry *entry)
1294
{
1295
struct beamforming_info *info;
1296
u8 idx;
1297
1298
1299
info = GET_BEAMFORM_INFO(adapter);
1300
1301
entry->state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT;
1302
1303
if (TEST_FLAG(entry->cap, BEAMFORMEE_CAP_VHT_MU)) {
1304
info->beamformee_mu_cnt -= 1;
1305
info->first_mu_bfee_index = _bfee_get_first_mu_entry_idx(adapter, entry);
1306
1307
if (_TRUE == info->bEnableSUTxBFWorkAround) {
1308
if ((info->beamformee_mu_cnt == 0) && (info->beamformee_su_cnt > 0)) {
1309
idx = _bfee_get_first_su_entry_idx(adapter, NULL);
1310
info->TargetSUBFee = &info->bfee_entry[idx];
1311
_rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO));
1312
info->TargetSUBFee->bSuspendSUCap = _FALSE;
1313
}
1314
}
1315
} else if (TEST_FLAG(entry->cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) {
1316
info->beamformee_su_cnt -= 1;
1317
1318
/* When the target SU BFee leaves, disable workaround */
1319
if ((_TRUE == info->bEnableSUTxBFWorkAround)
1320
&& (entry == info->TargetSUBFee)) {
1321
entry->bSuspendSUCap = _TRUE;
1322
info->TargetSUBFee = NULL;
1323
_rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO));
1324
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_CSI_REPORT, (u8*)&info->TargetCSIInfo, sizeof(struct _RT_CSI_INFO), 0);
1325
}
1326
}
1327
1328
if (info->beamformee_mu_cnt == 0)
1329
info->beamforming_cap &= ~BEAMFORMER_CAP_VHT_MU;
1330
if (info->beamformee_su_cnt == 0)
1331
info->beamforming_cap &= ~(BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT);
1332
1333
_sounding_update_min_period(adapter, 0, _TRUE);
1334
}
1335
1336
static enum beamforming_cap _bfee_get_entry_cap_by_macid(PADAPTER adapter, u8 macid)
1337
{
1338
struct beamforming_info *info;
1339
struct beamformee_entry *bfee;
1340
u8 i;
1341
1342
1343
info = GET_BEAMFORM_INFO(adapter);
1344
1345
for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) {
1346
bfee = &info->bfee_entry[i];
1347
if (bfee->used == _FALSE)
1348
continue;
1349
if (bfee->mac_id == macid)
1350
return bfee->cap;
1351
}
1352
1353
return BEAMFORMING_CAP_NONE;
1354
}
1355
1356
static void _beamforming_enter(PADAPTER adapter, void *p)
1357
{
1358
struct mlme_priv *mlme;
1359
struct ht_priv *htpriv;
1360
#ifdef CONFIG_80211AC_VHT
1361
struct vht_priv *vhtpriv;
1362
#endif
1363
struct mlme_ext_priv *mlme_ext;
1364
struct sta_info *sta, *sta_copy;
1365
struct beamforming_info *info;
1366
struct beamformer_entry *bfer = NULL;
1367
struct beamformee_entry *bfee = NULL;
1368
u8 wireless_mode;
1369
u8 sta_bf_cap;
1370
u8 sounding_dim = 0; /* number of sounding dimensions */
1371
u8 comp_steering_num = 0; /* compressed steering number */
1372
1373
1374
mlme = &adapter->mlmepriv;
1375
htpriv = &mlme->htpriv;
1376
#ifdef CONFIG_80211AC_VHT
1377
vhtpriv = &mlme->vhtpriv;
1378
#endif
1379
mlme_ext = &adapter->mlmeextpriv;
1380
info = GET_BEAMFORM_INFO(adapter);
1381
1382
sta_copy = (struct sta_info *)p;
1383
sta = rtw_get_stainfo(&adapter->stapriv, sta_copy->cmn.mac_addr);
1384
if (!sta) {
1385
RTW_ERR("%s: Cann't find STA info for " MAC_FMT "\n",
1386
__FUNCTION__, MAC_ARG(sta_copy->cmn.mac_addr));
1387
return;
1388
}
1389
if (sta != sta_copy) {
1390
RTW_WARN("%s: Origin sta(fake)=%p realsta=%p for " MAC_FMT "\n",
1391
__FUNCTION__, sta_copy, sta, MAC_ARG(sta_copy->cmn.mac_addr));
1392
}
1393
1394
/* The current setting does not support Beaforming */
1395
wireless_mode = sta->wireless_mode;
1396
if ((is_supported_ht(wireless_mode) == _FALSE)
1397
&& (is_supported_vht(wireless_mode) == _FALSE)) {
1398
RTW_WARN("%s: Not support HT or VHT mode\n", __FUNCTION__);
1399
return;
1400
}
1401
1402
if ((0 == htpriv->beamform_cap)
1403
#ifdef CONFIG_80211AC_VHT
1404
&& (0 == vhtpriv->beamform_cap)
1405
#endif
1406
) {
1407
RTW_INFO("The configuration disabled Beamforming! Skip...\n");
1408
return;
1409
}
1410
1411
_get_sta_beamform_cap(adapter, sta,
1412
&sta_bf_cap, &sounding_dim, &comp_steering_num);
1413
RTW_INFO("STA Beamforming Capability=0x%02X\n", sta_bf_cap);
1414
if (sta_bf_cap == BEAMFORMING_CAP_NONE)
1415
return;
1416
if ((sta_bf_cap & BEAMFORMEE_CAP_HT_EXPLICIT)
1417
|| (sta_bf_cap & BEAMFORMEE_CAP_VHT_SU)
1418
|| (sta_bf_cap & BEAMFORMEE_CAP_VHT_MU))
1419
sta_bf_cap |= BEAMFORMEE_CAP;
1420
if ((sta_bf_cap & BEAMFORMER_CAP_HT_EXPLICIT)
1421
|| (sta_bf_cap & BEAMFORMER_CAP_VHT_SU)
1422
|| (sta_bf_cap & BEAMFORMER_CAP_VHT_MU))
1423
sta_bf_cap |= BEAMFORMER_CAP;
1424
1425
if (sta_bf_cap & BEAMFORMER_CAP) {
1426
/* The other side is beamformer */
1427
bfer = _bfer_add_entry(adapter, sta, sta_bf_cap, sounding_dim, comp_steering_num);
1428
if (!bfer)
1429
RTW_ERR("%s: Fail to allocate bfer entry!\n", __FUNCTION__);
1430
}
1431
if (sta_bf_cap & BEAMFORMEE_CAP) {
1432
/* The other side is beamformee */
1433
bfee = _bfee_add_entry(adapter, sta, sta_bf_cap, sounding_dim, comp_steering_num);
1434
if (!bfee)
1435
RTW_ERR("%s: Fail to allocate bfee entry!\n", __FUNCTION__);
1436
}
1437
if (!bfer && !bfee)
1438
return;
1439
1440
rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_ENTER, (u8*)sta);
1441
1442
/* Perform sounding if there is BFee */
1443
if ((info->beamformee_su_cnt != 0)
1444
|| (info->beamformee_mu_cnt != 0)) {
1445
if (SOUNDING_STATE_NONE == info->sounding_info.state) {
1446
info->sounding_info.state = SOUNDING_STATE_INIT;
1447
/* Start sounding after 2 sec */
1448
_set_timer(&info->sounding_timer, 2000);
1449
}
1450
}
1451
}
1452
1453
static void _beamforming_reset(PADAPTER adapter)
1454
{
1455
RTW_ERR("%s: Not ready!!\n", __FUNCTION__);
1456
}
1457
1458
static void _beamforming_leave(PADAPTER adapter, u8 *ra)
1459
{
1460
struct beamforming_info *info;
1461
struct beamformer_entry *bfer = NULL;
1462
struct beamformee_entry *bfee = NULL;
1463
u8 bHwStateAddInit = _FALSE;
1464
1465
1466
RTW_INFO("+%s\n", __FUNCTION__);
1467
1468
info = GET_BEAMFORM_INFO(adapter);
1469
bfer = _bfer_get_entry_by_addr(adapter, ra);
1470
bfee = _bfee_get_entry_by_addr(adapter, ra);
1471
1472
if (!bfer && !bfee) {
1473
RTW_WARN("%s: " MAC_FMT " is neither beamforming ee or er!!\n",
1474
__FUNCTION__, MAC_ARG(ra));
1475
return;
1476
}
1477
1478
if (bfer)
1479
_bfer_remove_entry(adapter, bfer);
1480
1481
if (bfee)
1482
_bfee_remove_entry(adapter, bfee);
1483
1484
rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, ra);
1485
1486
/* Stop sounding if there is no any BFee */
1487
if ((info->beamformee_su_cnt == 0)
1488
&& (info->beamformee_mu_cnt == 0)) {
1489
_cancel_timer_ex(&info->sounding_timer);
1490
_sounding_init(&info->sounding_info);
1491
}
1492
1493
RTW_INFO("-%s\n", __FUNCTION__);
1494
}
1495
1496
static void _beamforming_sounding_down(PADAPTER adapter, u8 status)
1497
{
1498
struct beamforming_info *info;
1499
struct sounding_info *sounding;
1500
struct beamformee_entry *bfee;
1501
1502
1503
info = GET_BEAMFORM_INFO(adapter);
1504
sounding = &info->sounding_info;
1505
1506
RTW_INFO("+%s: sounding=%d, status=0x%02x\n", __FUNCTION__, sounding->state, status);
1507
1508
if (sounding->state == SOUNDING_STATE_MU_START) {
1509
RTW_INFO("%s: MU sounding done\n", __FUNCTION__);
1510
sounding->state = SOUNDING_STATE_MU_SOUNDDOWN;
1511
RTW_INFO("%s: Set to SOUNDING_STATE_MU_SOUNDDOWN\n", __FUNCTION__);
1512
info->SetHalSoundownOnDemandCnt++;
1513
rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_STATUS, &status);
1514
} else if (sounding->state == SOUNDING_STATE_SU_START) {
1515
RTW_INFO("%s: SU entry[%d] sounding down\n", __FUNCTION__, sounding->su_bfee_curidx);
1516
bfee = &info->bfee_entry[sounding->su_bfee_curidx];
1517
sounding->state = SOUNDING_STATE_SU_SOUNDDOWN;
1518
RTW_INFO("%s: Set to SOUNDING_STATE_SU_SOUNDDOWN\n", __FUNCTION__);
1519
1520
/*
1521
* <tynli_note>
1522
* bfee->bSoundingTimeout this flag still cannot avoid
1523
* old sound down event happens in the new sounding period.
1524
* 2015.12.10
1525
*/
1526
if (_TRUE == bfee->bSoundingTimeout) {
1527
RTW_WARN("%s: The entry[%d] is bSoundingTimeout!\n", __FUNCTION__, sounding->su_bfee_curidx);
1528
bfee->bSoundingTimeout = _FALSE;
1529
return;
1530
}
1531
1532
if (_TRUE == status) {
1533
/* success */
1534
bfee->LogStatusFailCnt = 0;
1535
info->SetHalSoundownOnDemandCnt++;
1536
rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_STATUS, &status);
1537
} else if (_TRUE == bfee->bDeleteSounding) {
1538
RTW_WARN("%s: Delete entry[%d] sounding info!\n", __FUNCTION__, sounding->su_bfee_curidx);
1539
rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_STATUS, &status);
1540
bfee->bDeleteSounding = _FALSE;
1541
} else {
1542
bfee->LogStatusFailCnt++;
1543
RTW_WARN("%s: LogStatusFailCnt=%d\n", __FUNCTION__, bfee->LogStatusFailCnt);
1544
if (bfee->LogStatusFailCnt > 30) {
1545
RTW_ERR("%s: LogStatusFailCnt > 30, Stop SOUNDING!!\n", __FUNCTION__);
1546
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_LEAVE, bfee->mac_addr, ETH_ALEN, 1);
1547
}
1548
}
1549
} else {
1550
RTW_WARN("%s: unexpected sounding state:0x%02x\n", __FUNCTION__, sounding->state);
1551
return;
1552
}
1553
1554
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_START_PERIOD, NULL, 0, 0);
1555
}
1556
1557
static void _c2h_snd_txbf(PADAPTER adapter, u8 *buf, u8 buf_len)
1558
{
1559
struct beamforming_info *info;
1560
u8 res;
1561
1562
info = GET_BEAMFORM_INFO(adapter);
1563
1564
_cancel_timer_ex(&info->sounding_timeout_timer);
1565
1566
res = C2H_SND_TXBF_GET_SND_RESULT(buf) ? _TRUE : _FALSE;
1567
RTW_INFO("+%s: %s\n", __FUNCTION__, res==_TRUE?"Success":"Fail!");
1568
1569
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_END_PERIOD, &res, 1, 1);
1570
}
1571
1572
/*
1573
* Description:
1574
* This function is for phydm only
1575
*/
1576
enum beamforming_cap rtw_bf_bfee_get_entry_cap_by_macid(void *mlme, u8 macid)
1577
{
1578
PADAPTER adapter;
1579
enum beamforming_cap cap = BEAMFORMING_CAP_NONE;
1580
1581
1582
adapter = mlme_to_adapter((struct mlme_priv *)mlme);
1583
cap = _bfee_get_entry_cap_by_macid(adapter, macid);
1584
1585
return cap;
1586
}
1587
1588
struct beamformer_entry *rtw_bf_bfer_get_entry_by_addr(PADAPTER adapter, u8 *ra)
1589
{
1590
return _bfer_get_entry_by_addr(adapter, ra);
1591
}
1592
1593
struct beamformee_entry *rtw_bf_bfee_get_entry_by_addr(PADAPTER adapter, u8 *ra)
1594
{
1595
return _bfee_get_entry_by_addr(adapter, ra);
1596
}
1597
1598
void rtw_bf_get_ndpa_packet(PADAPTER adapter, union recv_frame *precv_frame)
1599
{
1600
RTW_DBG("+%s\n", __FUNCTION__);
1601
}
1602
1603
u32 rtw_bf_get_report_packet(PADAPTER adapter, union recv_frame *precv_frame)
1604
{
1605
u32 ret = _SUCCESS;
1606
struct beamforming_info *info;
1607
struct beamformee_entry *bfee = NULL;
1608
u8 *pframe;
1609
u32 frame_len;
1610
u8 *ta;
1611
u8 *frame_body;
1612
u8 category, action;
1613
u8 *pMIMOCtrlField, *pCSIMatrix;
1614
u8 Nc = 0, Nr = 0, CH_W = 0, Ng = 0, CodeBook = 0;
1615
u16 CSIMatrixLen = 0;
1616
1617
1618
RTW_INFO("+%s\n", __FUNCTION__);
1619
1620
info = GET_BEAMFORM_INFO(adapter);
1621
pframe = precv_frame->u.hdr.rx_data;
1622
frame_len = precv_frame->u.hdr.len;
1623
1624
/* Memory comparison to see if CSI report is the same with previous one */
1625
ta = get_addr2_ptr(pframe);
1626
bfee = _bfee_get_entry_by_addr(adapter, ta);
1627
if (!bfee)
1628
return _FAIL;
1629
1630
frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
1631
category = frame_body[0];
1632
action = frame_body[1];
1633
1634
if ((category == RTW_WLAN_CATEGORY_VHT)
1635
&& (action == RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING)) {
1636
pMIMOCtrlField = pframe + 26;
1637
Nc = (*pMIMOCtrlField) & 0x7;
1638
Nr = ((*pMIMOCtrlField) & 0x38) >> 3;
1639
CH_W = (((*pMIMOCtrlField) & 0xC0) >> 6);
1640
Ng = (*(pMIMOCtrlField+1)) & 0x3;
1641
CodeBook = ((*(pMIMOCtrlField+1)) & 0x4) >> 2;
1642
/*
1643
* 24+(1+1+3)+2
1644
* ==> MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)
1645
*/
1646
pCSIMatrix = pMIMOCtrlField + 3 + Nc;
1647
CSIMatrixLen = frame_len - 26 - 3 - Nc;
1648
info->TargetCSIInfo.bVHT = _TRUE;
1649
} else if ((category == RTW_WLAN_CATEGORY_HT)
1650
&& (action == RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING)) {
1651
pMIMOCtrlField = pframe + 26;
1652
Nc = (*pMIMOCtrlField) & 0x3;
1653
Nr = ((*pMIMOCtrlField) & 0xC) >> 2;
1654
CH_W = ((*pMIMOCtrlField) & 0x10) >> 4;
1655
Ng = ((*pMIMOCtrlField) & 0x60) >> 5;
1656
CodeBook = ((*(pMIMOCtrlField+1)) & 0x6) >> 1;
1657
/*
1658
* 24+(1+1+6)+2
1659
* ==> MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)
1660
*/
1661
pCSIMatrix = pMIMOCtrlField + 6 + Nr;
1662
CSIMatrixLen = frame_len - 26 - 6 - Nr;
1663
info->TargetCSIInfo.bVHT = _FALSE;
1664
}
1665
1666
/* Update current CSI report info */
1667
if ((_TRUE == info->bEnableSUTxBFWorkAround)
1668
&& (info->TargetSUBFee == bfee)) {
1669
if ((info->TargetCSIInfo.Nc != Nc) || (info->TargetCSIInfo.Nr != Nr) ||
1670
(info->TargetCSIInfo.ChnlWidth != CH_W) || (info->TargetCSIInfo.Ng != Ng) ||
1671
(info->TargetCSIInfo.CodeBook != CodeBook)) {
1672
info->TargetCSIInfo.Nc = Nc;
1673
info->TargetCSIInfo.Nr = Nr;
1674
info->TargetCSIInfo.ChnlWidth = CH_W;
1675
info->TargetCSIInfo.Ng = Ng;
1676
info->TargetCSIInfo.CodeBook = CodeBook;
1677
1678
rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_CSI_REPORT, (u8*)&info->TargetCSIInfo, sizeof(struct _RT_CSI_INFO), 1);
1679
}
1680
}
1681
1682
RTW_INFO("%s: pkt type=%d-%d, Nc=%d, Nr=%d, CH_W=%d, Ng=%d, CodeBook=%d\n",
1683
__FUNCTION__, category, action, Nc, Nr, CH_W, Ng, CodeBook);
1684
1685
return ret;
1686
}
1687
1688
u8 rtw_bf_send_vht_gid_mgnt_packet(PADAPTER adapter, u8 *ra, u8 *gid, u8 *position)
1689
{
1690
/* General */
1691
struct xmit_priv *xmitpriv;
1692
struct mlme_priv *mlmepriv;
1693
struct xmit_frame *pmgntframe;
1694
/* MISC */
1695
struct pkt_attrib *attrib;
1696
struct rtw_ieee80211_hdr *wlanhdr;
1697
u8 *pframe, *ptr;
1698
1699
1700
xmitpriv = &adapter->xmitpriv;
1701
mlmepriv = &adapter->mlmepriv;
1702
1703
pmgntframe = alloc_mgtxmitframe(xmitpriv);
1704
if (!pmgntframe)
1705
return _FALSE;
1706
1707
/* update attribute */
1708
attrib = &pmgntframe->attrib;
1709
update_mgntframe_attrib(adapter, attrib);
1710
attrib->rate = MGN_6M;
1711
attrib->bwmode = CHANNEL_WIDTH_20;
1712
attrib->subtype = WIFI_ACTION;
1713
1714
_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1715
1716
pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
1717
wlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1718
1719
wlanhdr->frame_ctl = 0;
1720
set_frame_sub_type(pframe, attrib->subtype);
1721
set_duration(pframe, 0);
1722
SetFragNum(pframe, 0);
1723
SetSeqNum(pframe, 0);
1724
1725
_rtw_memcpy(wlanhdr->addr1, ra, ETH_ALEN);
1726
_rtw_memcpy(wlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
1727
_rtw_memcpy(wlanhdr->addr3, get_bssid(mlmepriv), ETH_ALEN);
1728
1729
pframe[24] = RTW_WLAN_CATEGORY_VHT;
1730
pframe[25] = RTW_WLAN_ACTION_VHT_GROUPID_MANAGEMENT;
1731
/* Set Membership Status Array */
1732
ptr = pframe + 26;
1733
_rtw_memcpy(ptr, gid, 8);
1734
/* Set User Position Array */
1735
ptr = pframe + 34;
1736
_rtw_memcpy(ptr, position, 16);
1737
1738
attrib->pktlen = 54;
1739
attrib->last_txcmdsz = attrib->pktlen;
1740
1741
dump_mgntframe(adapter, pmgntframe);
1742
1743
return _TRUE;
1744
}
1745
1746
/*
1747
* Description:
1748
* On VHT GID management frame by an MU beamformee.
1749
*/
1750
void rtw_bf_get_vht_gid_mgnt_packet(PADAPTER adapter, union recv_frame *precv_frame)
1751
{
1752
u8 *pframe;
1753
u8 *ta, *gid, *position;
1754
1755
1756
RTW_DBG("+%s\n", __FUNCTION__);
1757
1758
pframe = precv_frame->u.hdr.rx_data;
1759
1760
/* Get address by Addr2 */
1761
ta = get_addr2_ptr(pframe);
1762
/* Remove signaling TA */
1763
ta[0] &= 0xFE;
1764
1765
/* Membership Status Array */
1766
gid = pframe + 26;
1767
/* User Position Array */
1768
position= pframe + 34;
1769
1770
_bfer_set_entry_gid(adapter, ta, gid, position);
1771
}
1772
1773
void rtw_bf_init(PADAPTER adapter)
1774
{
1775
struct beamforming_info *info;
1776
1777
1778
info = GET_BEAMFORM_INFO(adapter);
1779
info->beamforming_cap = BEAMFORMING_CAP_NONE;
1780
info->beamforming_state = BEAMFORMING_STATE_IDLE;
1781
/*
1782
info->bfee_entry[MAX_BEAMFORMEE_ENTRY_NUM];
1783
info->bfer_entry[MAX_BEAMFORMER_ENTRY_NUM];
1784
*/
1785
info->sounding_sequence = 0;
1786
info->beamformee_su_cnt = 0;
1787
info->beamformer_su_cnt = 0;
1788
info->beamformee_su_reg_maping = 0;
1789
info->beamformer_su_reg_maping = 0;
1790
info->beamformee_mu_cnt = 0;
1791
info->beamformer_mu_cnt = 0;
1792
info->beamformee_mu_reg_maping = 0;
1793
info->first_mu_bfee_index = 0xFF;
1794
info->mu_bfer_curidx = 0xFF;
1795
info->cur_csi_rpt_rate = HALMAC_OFDM24;
1796
1797
_sounding_init(&info->sounding_info);
1798
rtw_init_timer(&info->sounding_timer, adapter, _sounding_timer_handler, adapter);
1799
rtw_init_timer(&info->sounding_timeout_timer, adapter, _sounding_timeout_timer_handler, adapter);
1800
1801
info->SetHalBFEnterOnDemandCnt = 0;
1802
info->SetHalBFLeaveOnDemandCnt = 0;
1803
info->SetHalSoundownOnDemandCnt = 0;
1804
1805
info->bEnableSUTxBFWorkAround = _TRUE;
1806
info->TargetSUBFee = NULL;
1807
1808
info->sounding_running = 0;
1809
}
1810
1811
void rtw_bf_cmd_hdl(PADAPTER adapter, u8 type, u8 *pbuf)
1812
{
1813
switch (type) {
1814
case BEAMFORMING_CTRL_ENTER:
1815
_beamforming_enter(adapter, pbuf);
1816
break;
1817
1818
case BEAMFORMING_CTRL_LEAVE:
1819
if (pbuf == NULL)
1820
_beamforming_reset(adapter);
1821
else
1822
_beamforming_leave(adapter, pbuf);
1823
break;
1824
1825
case BEAMFORMING_CTRL_START_PERIOD:
1826
_sounding_handler(adapter);
1827
break;
1828
1829
case BEAMFORMING_CTRL_END_PERIOD:
1830
_beamforming_sounding_down(adapter, *pbuf);
1831
break;
1832
1833
case BEAMFORMING_CTRL_SET_GID_TABLE:
1834
rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_SET_GID_TABLE, pbuf);
1835
break;
1836
1837
case BEAMFORMING_CTRL_SET_CSI_REPORT:
1838
rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_CSI_REPORT, pbuf);
1839
break;
1840
1841
default:
1842
break;
1843
}
1844
}
1845
1846
u8 rtw_bf_cmd(PADAPTER adapter, s32 type, u8 *pbuf, s32 size, u8 enqueue)
1847
{
1848
struct cmd_obj *ph2c;
1849
struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1850
struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1851
u8 *wk_buf;
1852
u8 res = _SUCCESS;
1853
1854
1855
if (!enqueue) {
1856
rtw_bf_cmd_hdl(adapter, type, pbuf);
1857
goto exit;
1858
}
1859
1860
ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1861
if (ph2c == NULL) {
1862
res = _FAIL;
1863
goto exit;
1864
}
1865
1866
pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
1867
if (pdrvextra_cmd_parm == NULL) {
1868
rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
1869
res = _FAIL;
1870
goto exit;
1871
}
1872
1873
if (pbuf != NULL) {
1874
wk_buf = rtw_zmalloc(size);
1875
if (wk_buf == NULL) {
1876
rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
1877
rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
1878
res = _FAIL;
1879
goto exit;
1880
}
1881
1882
_rtw_memcpy(wk_buf, pbuf, size);
1883
} else {
1884
wk_buf = NULL;
1885
size = 0;
1886
}
1887
1888
pdrvextra_cmd_parm->ec_id = BEAMFORMING_WK_CID;
1889
pdrvextra_cmd_parm->type = type;
1890
pdrvextra_cmd_parm->size = size;
1891
pdrvextra_cmd_parm->pbuf = wk_buf;
1892
1893
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
1894
1895
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
1896
1897
exit:
1898
return res;
1899
}
1900
1901
void rtw_bf_update_attrib(PADAPTER adapter, struct pkt_attrib *attrib, struct sta_info *sta)
1902
{
1903
if (sta) {
1904
attrib->txbf_g_id = sta->cmn.bf_info.g_id;
1905
attrib->txbf_p_aid = sta->cmn.bf_info.p_aid;
1906
}
1907
}
1908
1909
void rtw_bf_c2h_handler(PADAPTER adapter, u8 id, u8 *buf, u8 buf_len)
1910
{
1911
switch (id) {
1912
case CMD_ID_C2H_SND_TXBF:
1913
_c2h_snd_txbf(adapter, buf, buf_len);
1914
break;
1915
}
1916
}
1917
1918
#define toMbps(bytes, secs) (rtw_division64(bytes >> 17, secs))
1919
void rtw_bf_update_traffic(PADAPTER adapter)
1920
{
1921
struct beamforming_info *info;
1922
struct sounding_info *sounding;
1923
struct beamformee_entry *bfee;
1924
struct sta_info *sta;
1925
u8 bfee_cnt, sounding_idx, i;
1926
u16 tp[MAX_BEAMFORMEE_ENTRY_NUM] = {0};
1927
u8 tx_rate[MAX_BEAMFORMEE_ENTRY_NUM] = {0};
1928
u64 tx_bytes, last_bytes;
1929
u32 time;
1930
systime last_timestamp;
1931
u8 set_timer = _FALSE;
1932
1933
1934
info = GET_BEAMFORM_INFO(adapter);
1935
sounding = &info->sounding_info;
1936
1937
/* Check any bfee exist? */
1938
bfee_cnt = info->beamformee_su_cnt + info->beamformee_mu_cnt;
1939
if (bfee_cnt == 0)
1940
return;
1941
1942
for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
1943
bfee = &info->bfee_entry[i];
1944
if (_FALSE == bfee->used)
1945
continue;
1946
1947
sta = rtw_get_stainfo(&adapter->stapriv, bfee->mac_addr);
1948
if (!sta) {
1949
RTW_ERR("%s: Cann't find sta_info for " MAC_FMT "!\n", __FUNCTION__, MAC_ARG(bfee->mac_addr));
1950
continue;
1951
}
1952
1953
last_timestamp = bfee->tx_timestamp;
1954
last_bytes = bfee->tx_bytes;
1955
bfee->tx_timestamp = rtw_get_current_time();
1956
bfee->tx_bytes = sta->sta_stats.tx_bytes;
1957
if (last_timestamp) {
1958
if (bfee->tx_bytes >= last_bytes)
1959
tx_bytes = bfee->tx_bytes - last_bytes;
1960
else
1961
tx_bytes = bfee->tx_bytes + (~last_bytes);
1962
time = rtw_get_time_interval_ms(last_timestamp, bfee->tx_timestamp);
1963
time = (time > 1000) ? time/1000 : 1;
1964
tp[i] = toMbps(tx_bytes, time);
1965
tx_rate[i] = rtw_get_current_tx_rate(adapter, sta);
1966
RTW_INFO("%s: BFee idx(%d), MadId(%d), TxTP=%lld bytes (%d Mbps), txrate=%d\n",
1967
__FUNCTION__, i, bfee->mac_id, tx_bytes, tp[i], tx_rate[i]);
1968
}
1969
}
1970
1971
sounding_idx = phydm_get_beamforming_sounding_info(GET_PDM_ODM(adapter), tp, MAX_BEAMFORMEE_ENTRY_NUM, tx_rate);
1972
1973
for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
1974
bfee = &info->bfee_entry[i];
1975
if (_FALSE == bfee->used) {
1976
if (sounding_idx & BIT(i))
1977
RTW_WARN("%s: bfee(%d) not in used but need sounding?!\n", __FUNCTION__, i);
1978
continue;
1979
}
1980
1981
if (sounding_idx & BIT(i)) {
1982
if (_FALSE == bfee->bApplySounding) {
1983
bfee->bApplySounding = _TRUE;
1984
bfee->SoundCnt = 0;
1985
set_timer = _TRUE;
1986
}
1987
} else {
1988
if (_TRUE == bfee->bApplySounding) {
1989
bfee->bApplySounding = _FALSE;
1990
bfee->bDeleteSounding = _TRUE;
1991
bfee->SoundCnt = 0;
1992
set_timer = _TRUE;
1993
}
1994
}
1995
}
1996
1997
if (_TRUE == set_timer) {
1998
if (SOUNDING_STATE_NONE == info->sounding_info.state) {
1999
info->sounding_info.state = SOUNDING_STATE_INIT;
2000
_set_timer(&info->sounding_timer, 0);
2001
}
2002
}
2003
}
2004
2005
#else /* !RTW_BEAMFORMING_VERSION_2 */
2006
2007
/*PHYDM_BF - (BEAMFORMING_SUPPORT == 1)*/
2008
u32 rtw_beamforming_get_report_frame(PADAPTER Adapter, union recv_frame *precv_frame)
2009
{
2010
u32 ret = _SUCCESS;
2011
2012
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
2013
struct dm_struct *pDM_Odm = &(pHalData->odmpriv);
2014
2015
ret = beamforming_get_report_frame(pDM_Odm, precv_frame);
2016
return ret;
2017
}
2018
2019
void rtw_beamforming_get_ndpa_frame(PADAPTER Adapter, union recv_frame *precv_frame)
2020
{
2021
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
2022
struct dm_struct *pDM_Odm = &(pHalData->odmpriv);
2023
2024
beamforming_get_ndpa_frame(pDM_Odm, precv_frame);
2025
}
2026
2027
void beamforming_wk_hdl(_adapter *padapter, u8 type, u8 *pbuf)
2028
{
2029
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
2030
struct dm_struct *pDM_Odm = &(pHalData->odmpriv);
2031
2032
/*(BEAMFORMING_SUPPORT == 1)- for PHYDM beamfoming*/
2033
switch (type) {
2034
case BEAMFORMING_CTRL_ENTER: {
2035
struct sta_info *psta = (void *)pbuf;
2036
u16 staIdx = psta->cmn.mac_id;
2037
2038
beamforming_enter(pDM_Odm, staIdx, adapter_mac_addr(psta->padapter));
2039
break;
2040
}
2041
case BEAMFORMING_CTRL_LEAVE:
2042
beamforming_leave(pDM_Odm, pbuf);
2043
break;
2044
default:
2045
break;
2046
2047
}
2048
}
2049
2050
u8 beamforming_wk_cmd(_adapter *padapter, s32 type, u8 *pbuf, s32 size, u8 enqueue)
2051
{
2052
struct cmd_obj *ph2c;
2053
struct drvextra_cmd_parm *pdrvextra_cmd_parm;
2054
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
2055
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2056
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2057
u8 res = _SUCCESS;
2058
2059
/*20170214 ad_hoc mode and mp_mode not support BF*/
2060
if ((padapter->registrypriv.mp_mode == 1)
2061
|| (pmlmeinfo->state == WIFI_FW_ADHOC_STATE))
2062
return res;
2063
2064
if (enqueue) {
2065
u8 *wk_buf;
2066
2067
ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2068
if (ph2c == NULL) {
2069
res = _FAIL;
2070
goto exit;
2071
}
2072
2073
pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2074
if (pdrvextra_cmd_parm == NULL) {
2075
rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
2076
res = _FAIL;
2077
goto exit;
2078
}
2079
2080
if (pbuf != NULL) {
2081
wk_buf = rtw_zmalloc(size);
2082
if (wk_buf == NULL) {
2083
rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
2084
rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
2085
res = _FAIL;
2086
goto exit;
2087
}
2088
2089
_rtw_memcpy(wk_buf, pbuf, size);
2090
} else {
2091
wk_buf = NULL;
2092
size = 0;
2093
}
2094
2095
pdrvextra_cmd_parm->ec_id = BEAMFORMING_WK_CID;
2096
pdrvextra_cmd_parm->type = type;
2097
pdrvextra_cmd_parm->size = size;
2098
pdrvextra_cmd_parm->pbuf = wk_buf;
2099
2100
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2101
2102
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
2103
} else
2104
beamforming_wk_hdl(padapter, type, pbuf);
2105
2106
exit:
2107
2108
2109
return res;
2110
}
2111
2112
void update_attrib_txbf_info(_adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)
2113
{
2114
if (psta) {
2115
pattrib->txbf_g_id = psta->cmn.bf_info.g_id;
2116
pattrib->txbf_p_aid = psta->cmn.bf_info.p_aid;
2117
}
2118
}
2119
#endif /* !RTW_BEAMFORMING_VERSION_2 */
2120
2121
#endif /* CONFIG_BEAMFORMING */
2122
2123