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