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