xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8822be/core/rtw_beamforming.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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