xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/core/rtw_vht.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2021 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 
19 #ifdef CONFIG_80211AC_VHT
20 const u16 _vht_max_mpdu_len[] = {
21 	3895,
22 	7991,
23 	11454,
24 	0,
25 };
26 
27 const u8 _vht_sup_ch_width_set_to_bw_cap[] = {
28 	BW_CAP_80M,
29 	BW_CAP_80M | BW_CAP_160M,
30 	BW_CAP_80M | BW_CAP_160M | BW_CAP_80_80M,
31 	0,
32 };
33 
34 const char *const _vht_sup_ch_width_set_str[] = {
35 	"80MHz",
36 	"160MHz",
37 	"160MHz & 80+80MHz",
38 	"BW-RSVD",
39 };
40 
dump_vht_cap_ie_content(void * sel,const u8 * buf,u32 buf_len)41 void dump_vht_cap_ie_content(void *sel, const u8 *buf, u32 buf_len)
42 {
43 	if (buf_len != VHT_CAP_IE_LEN) {
44 		RTW_PRINT_SEL(sel, "Invalid VHT capability IE len:%d != %d\n", buf_len, VHT_CAP_IE_LEN);
45 		return;
46 	}
47 
48 	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"
49 		, *(buf), *(buf + 1), *(buf + 2), *(buf + 3)
50 		, vht_max_mpdu_len(GET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(buf))
51 		, vht_sup_ch_width_set_str(GET_VHT_CAPABILITY_ELE_CHL_WIDTH(buf))
52 		, GET_VHT_CAPABILITY_ELE_RX_LDPC(buf) ? " RX-LDPC" : ""
53 		, GET_VHT_CAPABILITY_ELE_SHORT_GI80M(buf) ? " SGI-80" : ""
54 		, GET_VHT_CAPABILITY_ELE_SHORT_GI160M(buf) ? " SGI-160" : ""
55 		, GET_VHT_CAPABILITY_ELE_TX_STBC(buf) ? " TX-STBC" : ""
56 		, GET_VHT_CAPABILITY_ELE_RX_STBC(buf)
57 		, VHT_MAX_AMPDU_LEN(GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(buf))
58 	);
59 }
60 
dump_vht_cap_ie(void * sel,const u8 * ie,u32 ie_len)61 void dump_vht_cap_ie(void *sel, const u8 *ie, u32 ie_len)
62 {
63 	const u8 *vht_cap_ie;
64 	sint vht_cap_ielen;
65 
66 	vht_cap_ie = rtw_get_ie(ie, WLAN_EID_VHT_CAPABILITY, &vht_cap_ielen, ie_len);
67 	if (!ie || vht_cap_ie != ie)
68 		return;
69 
70 	dump_vht_cap_ie_content(sel, vht_cap_ie + 2, vht_cap_ielen);
71 }
72 
73 const char *const _vht_op_ch_width_str[] = {
74 	"20 or 40MHz",
75 	"80MHz",
76 	"160MHz",
77 	"80+80MHz",
78 	"BW-RSVD",
79 };
80 
dump_vht_op_ie_content(void * sel,const u8 * buf,u32 buf_len)81 void dump_vht_op_ie_content(void *sel, const u8 *buf, u32 buf_len)
82 {
83 	if (buf_len != VHT_OP_IE_LEN) {
84 		RTW_PRINT_SEL(sel, "Invalid VHT operation IE len:%d != %d\n", buf_len, VHT_OP_IE_LEN);
85 		return;
86 	}
87 
88 	RTW_PRINT_SEL(sel, "\tVHT Operation Info:\n");
89 	RTW_PRINT_SEL(sel, "\tChannel Width: %u\n"
90 					, GET_VHT_OPERATION_ELE_CHL_WIDTH(buf));
91 	RTW_PRINT_SEL(sel, "\tCenter Frequency Channel for 80 and 160 MHz Operation: %u\n"
92 					, GET_VHT_OPERATION_ELE_CENTER_FREQ1(buf));
93 	RTW_PRINT_SEL(sel, "\tCenter Frequency Channel for 80+80 MHz Operation: %u\n"
94 					, GET_VHT_OPERATION_ELE_CENTER_FREQ2(buf));
95 	RTW_PRINT_SEL(sel, "\tVHT Basic MCS Set: 0x%04x\n"
96 					, GET_VHT_OPERATION_ELE_BASIC_MCS_SET(buf));
97 }
98 
dump_vht_op_ie(void * sel,const u8 * ie,u32 ie_len)99 void dump_vht_op_ie(void *sel, const u8 *ie, u32 ie_len)
100 {
101 	const u8 *vht_op_ie;
102 	sint vht_op_ielen;
103 
104 	vht_op_ie = rtw_get_ie(ie, WLAN_EID_VHT_OPERATION, &vht_op_ielen, ie_len);
105 	if (!ie || vht_op_ie != ie)
106 		return;
107 
108 	dump_vht_op_ie_content(sel, vht_op_ie + 2, vht_op_ielen);
109 }
110 
111 /*				20/40/80,	ShortGI,	MCS Rate  */
112 const u16 VHT_MCS_DATA_RATE[3][2][30] = {
113 	{	{
114 			13, 26, 39, 52, 78, 104, 117, 130, 156, 156,
115 			26, 52, 78, 104, 156, 208, 234, 260, 312, 312,
116 			39, 78, 117, 156, 234, 312, 351, 390, 468, 520
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 		}
123 	},		/* Short GI, 20MHz */
124 	{	{
125 			27, 54, 81, 108, 162, 216, 243, 270, 324, 360,
126 			54, 108, 162, 216, 324, 432, 486, 540, 648, 720,
127 			81, 162, 243, 324, 486, 648, 729, 810, 972, 1080
128 		}, 		/* Long GI, 40MHz */
129 		{
130 			30, 60, 90, 120, 180, 240, 270, 300, 360, 400,
131 			60, 120, 180, 240, 360, 480, 540, 600, 720, 800,
132 			90, 180, 270, 360, 540, 720, 810, 900, 1080, 1200
133 		}
134 	},		/* Short GI, 40MHz */
135 	{	{
136 			59, 117,  176, 234, 351, 468, 527, 585, 702, 780,
137 			117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560,
138 			176, 351, 527, 702, 1053, 1404, 1580, 1755, 2106, 2340
139 		},	/* Long GI, 80MHz */
140 		{
141 			65, 130, 195, 260, 390, 520, 585, 650, 780, 867,
142 			130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1734,
143 			195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600
144 		}
145 	}	/* Short GI, 80MHz */
146 };
147 
rtw_get_vht_highest_rate(u8 * pvht_mcs_map)148 u8	rtw_get_vht_highest_rate(u8 *pvht_mcs_map)
149 {
150 	u8	i, j;
151 	u8	bit_map;
152 	u8	vht_mcs_rate = 0;
153 
154 	for (i = 0; i < 2; i++) {
155 		if (pvht_mcs_map[i] != 0xff) {
156 			for (j = 0; j < 8; j += 2) {
157 				bit_map = (pvht_mcs_map[i] >> j) & 3;
158 
159 				if (bit_map != 3)
160 					vht_mcs_rate = MGN_VHT1SS_MCS7 + 10 * j / 2 + i * 40 + bit_map; /* VHT rate indications begin from 0x90 */
161 			}
162 		}
163 	}
164 
165 	/* RTW_INFO("HighestVHTMCSRate is %x\n", vht_mcs_rate); */
166 	return vht_mcs_rate;
167 }
168 
rtw_vht_mcsmap_to_nss(u8 * pvht_mcs_map)169 u8	rtw_vht_mcsmap_to_nss(u8 *pvht_mcs_map)
170 {
171 	u8	i, j;
172 	u8	bit_map;
173 	u8	nss = 0;
174 
175 	for (i = 0; i < 2; i++) {
176 		if (pvht_mcs_map[i] != 0xff) {
177 			for (j = 0; j < 8; j += 2) {
178 				bit_map = (pvht_mcs_map[i] >> j) & 3;
179 
180 				if (bit_map != 3)
181 					nss++;
182 			}
183 		}
184 	}
185 
186 	/* RTW_INFO("%s : %dSS\n", __FUNCTION__, nss); */
187 	return nss;
188 }
189 
rtw_vht_nss_to_mcsmap(u8 nss,u8 * target_mcs_map,u8 * cur_mcs_map)190 void rtw_vht_nss_to_mcsmap(u8 nss, u8 *target_mcs_map, u8 *cur_mcs_map)
191 {
192 	u8	i, j;
193 	u8	cur_rate, target_rate;
194 
195 	for (i = 0; i < 2; i++) {
196 		target_mcs_map[i] = 0;
197 		for (j = 0; j < 8; j += 2) {
198 			cur_rate = (cur_mcs_map[i] >> j) & 3;
199 			if (cur_rate == 3) /* 0x3 indicates not supported that num of SS */
200 				target_rate = 3;
201 			else if (nss <= ((j / 2) + i * 4))
202 				target_rate = 3;
203 			else
204 				target_rate = cur_rate;
205 
206 			target_mcs_map[i] |= (target_rate << j);
207 		}
208 	}
209 
210 	/* RTW_INFO("%s : %dSS\n", __FUNCTION__, nss); */
211 }
212 
rtw_vht_mcs_to_data_rate(u8 bw,u8 short_GI,u8 vht_mcs_rate)213 u16	rtw_vht_mcs_to_data_rate(u8 bw, u8 short_GI, u8 vht_mcs_rate)
214 {
215 	if (vht_mcs_rate > MGN_VHT3SS_MCS9)
216 		vht_mcs_rate = MGN_VHT3SS_MCS9;
217 	/* 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)); */
218 	return VHT_MCS_DATA_RATE[bw][short_GI][((vht_mcs_rate - MGN_VHT1SS_MCS0) & 0x3f)];
219 }
220 
221 /* Initialized vhtpriv by PHL default setting */
rtw_vht_get_dft_setting(_adapter * padapter,struct protocol_cap_t * dft_proto_cap,struct role_cap_t * dft_cap)222 void rtw_vht_get_dft_setting(_adapter *padapter,
223 			struct protocol_cap_t *dft_proto_cap, struct role_cap_t *dft_cap)
224 {
225 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
226 	struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
227 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
228 	BOOLEAN bHwLDPCSupport = _FALSE, bHwSTBCSupport = _FALSE;
229 	u8 stbc_rx = 0;
230 #ifdef CONFIG_BEAMFORMING
231 	BOOLEAN	bHwSupportBeamformer = _FALSE, bHwSupportBeamformee = _FALSE;
232 	u8 mu_bfer, mu_bfee;
233 #endif /* CONFIG_BEAMFORMING */
234 	u8 tx_nss, rx_nss;
235 	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
236 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
237 
238 	/* Short GI */
239 	pvhtpriv->sgi_80m = ((dft_proto_cap->sgi_80)
240 		&& rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_80M)
241 		&& TEST_FLAG(pregistrypriv->short_gi, BIT2));
242 
243 	pvhtpriv->sgi_160m = ((dft_proto_cap->sgi_160)
244 		&& rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M)
245 		&& TEST_FLAG(pregistrypriv->short_gi, BIT3));
246 
247 	/* LDPC */
248 	bHwLDPCSupport = (dft_proto_cap->vht_ldpc) ? _TRUE : _FALSE;
249 	if (bHwLDPCSupport) {
250 		if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT0))
251 			SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX);
252 	}
253 
254 	bHwLDPCSupport = (dft_cap->tx_vht_ldpc) ? _TRUE : _FALSE;
255 	if (bHwLDPCSupport) {
256 		if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT1))
257 			SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX);
258 	}
259 
260 	if (pvhtpriv->ldpc_cap)
261 		RTW_INFO("[VHT] Support LDPC = 0x%02X\n", pvhtpriv->ldpc_cap);
262 
263 	/* STBC */
264 	if (dft_proto_cap->stbc_vht_tx)
265 		SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX);
266 
267 	if (dft_proto_cap->stbc_vht_rx)
268 		SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX);
269 
270 	if (pvhtpriv->stbc_cap)
271 		RTW_INFO("[VHT] Support STBC = 0x%02X\n", pvhtpriv->stbc_cap);
272 
273 	/* Beamforming setting */
274 #ifdef CONFIG_BEAMFORMING
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 	{
280 
281 		bHwSupportBeamformer = (dft_proto_cap->vht_su_bfmr) ? _TRUE : _FALSE;
282 		bHwSupportBeamformee = (dft_proto_cap->vht_su_bfme) ? _TRUE : _FALSE;
283 
284 		mu_bfer = (dft_proto_cap->vht_mu_bfmr) ? _TRUE : _FALSE;
285 		mu_bfee = (dft_proto_cap->vht_mu_bfme) ? _TRUE : _FALSE;
286 
287 		if (TEST_FLAG(pregistrypriv->beamform_cap, BIT0) && bHwSupportBeamformer) {
288 #ifdef CONFIG_CONCURRENT_MODE
289 			if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
290 				SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
291 				RTW_INFO("[VHT] CONCURRENT AP Support Beamformer\n");
292 				if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
293 				    && (_TRUE == mu_bfer)) {
294 					SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
295 					RTW_INFO("[VHT] Support MU-MIMO AP\n");
296 				}
297 				pvhtpriv->num_snd_dim = dft_proto_cap->num_snd_dim;
298 			} else
299 				RTW_INFO("[VHT] CONCURRENT not AP ;not allow  Support Beamformer\n");
300 #else
301 			SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
302 			RTW_INFO("[VHT] Support Beamformer\n");
303 			if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
304 			    && (_TRUE == mu_bfer)
305 			    && ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
306 				SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
307 				RTW_INFO("[VHT] Support MU-MIMO AP\n");
308 			}
309 #endif
310 		}
311 		if (TEST_FLAG(pregistrypriv->beamform_cap, BIT1) && bHwSupportBeamformee) {
312 			SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
313 			RTW_INFO("[VHT] Support Beamformee\n");
314 			pvhtpriv->bfme_sts = dft_proto_cap->bfme_sts;
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 	/* We don't support these features, and PHL doesn't define */
326 	pvhtpriv->txop_ps = 0;
327 	pvhtpriv->htc_vht = 1;
328 	pvhtpriv->link_adap_cap = 0;
329 	pvhtpriv->tx_ant_pattern= 0;
330 	pvhtpriv->rx_ant_pattern= 0;
331 	pvhtpriv->ext_nss_bw = 0;
332 
333 	pvhtpriv->ampdu_len = pregistrypriv->ampdu_factor;
334 	pvhtpriv->max_mpdu_len = dft_proto_cap->max_amsdu_len;
335 
336 	tx_nss = GET_PHY_TX_NSS_BY_BAND(padapter, HW_BAND_0);
337 	rx_nss = GET_PHY_RX_NSS_BY_BAND(padapter, HW_BAND_0);
338 
339 	/* for now, vhtpriv.vht_mcs_map comes from RX NSS */
340 	rtw_vht_nss_to_mcsmap(rx_nss, pvhtpriv->vht_mcs_map, pregistrypriv->vht_rx_mcs_map);
341 	pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
342 }
343 
344 /* Initialized vhtpriv by adapter real setting */
rtw_vht_get_real_setting(_adapter * padapter)345 void rtw_vht_get_real_setting(_adapter *padapter)
346 {
347 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
348 	struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
349 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
350 #ifdef CONFIG_BEAMFORMING
351 	BOOLEAN bHwSupportBeamformer = _FALSE, bHwSupportBeamformee = _FALSE;
352 	u8 mu_bfer, mu_bfee;
353 #endif /* CONFIG_BEAMFORMING */
354 	u8 tx_nss, rx_nss;
355 	u8 rf_type = 0;
356 	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
357 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
358 	struct rtw_wifi_role_t *wrole = padapter->phl_role;
359 	struct protocol_cap_t *proto_cap = &(wrole->proto_role_cap);
360 	struct role_cap_t *cap = &(wrole->cap);
361 
362 	/* Short GI */
363 	pvhtpriv->sgi_80m = ((proto_cap->sgi_80)
364 		&& rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_80M)
365 		&& TEST_FLAG(pregistrypriv->short_gi, BIT2));
366 
367 	pvhtpriv->sgi_160m = ((proto_cap->sgi_160)
368 		&& rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M)
369 		&& TEST_FLAG(pregistrypriv->short_gi, BIT3));
370 
371 	/* LDPC support */
372 	if (proto_cap->vht_ldpc)
373 		SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX);
374 
375 	if (cap->tx_vht_ldpc)
376 		SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX);
377 
378 	if (pvhtpriv->ldpc_cap)
379 		RTW_INFO("[VHT] Support LDPC = 0x%02X\n", pvhtpriv->ldpc_cap);
380 
381 	/* STBC */
382 	if (proto_cap->stbc_vht_tx)
383 		SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX);
384 
385 	if (proto_cap->stbc_vht_rx) {
386 		SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX);
387 		pvhtpriv->rx_stbc_nss = proto_cap->stbc_vht_rx;
388 	}
389 
390 	if (pvhtpriv->stbc_cap)
391 		RTW_INFO("[VHT] Support STBC = 0x%02X\n", pvhtpriv->stbc_cap);
392 
393 	/* Beamforming setting */
394 	CLEAR_FLAGS(pvhtpriv->beamform_cap);
395 #ifdef CONFIG_BEAMFORMING
396 	if (proto_cap->vht_su_bfmr) {
397 		SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
398 		RTW_INFO("[VHT] HAL Support Beamformer\n");
399 		if (proto_cap->vht_mu_bfmr) {
400 			SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
401 			RTW_INFO("[VHT] Support MU-MIMO AP\n");
402 		}
403 	}
404 
405 	if (proto_cap->vht_su_bfme) {
406 		u8 bfme_sts = 0;
407 
408 		rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&bfme_sts);
409 		pvhtpriv->bfme_sts = bfme_sts;
410 		SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
411 		RTW_INFO("[VHT] HAL Support Beamformee\n");
412 		if (proto_cap->vht_mu_bfme) {
413 			SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
414 			RTW_INFO("[VHT] Support MU-MIMO STA\n");
415 		}
416 	}
417 #endif
418 
419 /* ToDo: check bfee flow will move change role type and modify wifi_role->proto_role_cap */
420 #if 0
421 #ifdef CONFIG_BEAMFORMING
422 	/* only enable beamforming in STA client mode */
423 	if (MLME_IS_STA(padapter) && !MLME_IS_GC(padapter)
424 				  && !MLME_IS_ADHOC(padapter)
425 				  && !MLME_IS_MESH(padapter))
426 	{
427 		rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMER,
428 			(u8 *)&bHwSupportBeamformer);
429 		rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMEE,
430 			(u8 *)&bHwSupportBeamformee);
431 		mu_bfer = _FALSE;
432 		mu_bfee = _FALSE;
433 		rtw_hal_get_def_var(padapter, HAL_DEF_VHT_MU_BEAMFORMER, &mu_bfer);
434 		rtw_hal_get_def_var(padapter, HAL_DEF_VHT_MU_BEAMFORMEE, &mu_bfee);
435 		if (TEST_FLAG(pregistrypriv->beamform_cap, BIT0) && bHwSupportBeamformer) {
436 #ifdef CONFIG_CONCURRENT_MODE
437 			if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
438 				u8 num_snd_dim = 0;
439 
440 				SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
441 				RTW_INFO("[VHT] CONCURRENT AP Support Beamformer\n");
442 				if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
443 				    && (_TRUE == mu_bfer)) {
444 					SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
445 					RTW_INFO("[VHT] Support MU-MIMO AP\n");
446 				}
447 				rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&num_snd_dim);
448 				pvhtpriv->num_snd_dim = num_snd_dim;
449 			} else
450 				RTW_INFO("[VHT] CONCURRENT not AP ;not allow  Support Beamformer\n");
451 #else
452 			SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
453 			RTW_INFO("[VHT] Support Beamformer\n");
454 			if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
455 			    && (_TRUE == mu_bfer)
456 			    && ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
457 				SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
458 				RTW_INFO("[VHT] Support MU-MIMO AP\n");
459 			}
460 #endif
461 		}
462 		if (TEST_FLAG(pregistrypriv->beamform_cap, BIT1) && bHwSupportBeamformee) {
463 			u8 bfme_sts = 0;
464 
465 			SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
466 			RTW_INFO("[VHT] Support Beamformee\n");
467 			rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&bfme_sts);
468 			pvhtpriv->bfme_sts = bfme_sts;
469 			if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(3))
470 			    && (_TRUE == mu_bfee)
471 			    && ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)) {
472 				SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
473 				RTW_INFO("[VHT] Support MU-MIMO STA\n");
474 			}
475 		}
476 	}
477 #endif /* CONFIG_BEAMFORMING */
478 #endif
479 
480 	/* We don't support these features, and PHL doesn't define */
481 	pvhtpriv->txop_ps = 0;
482 	pvhtpriv->htc_vht = 1;
483 	pvhtpriv->link_adap_cap = 0;
484 	pvhtpriv->tx_ant_pattern= 0;
485 	pvhtpriv->rx_ant_pattern= 0;
486 	pvhtpriv->ext_nss_bw = 0;
487 
488 	pvhtpriv->ampdu_len = pregistrypriv->ampdu_factor;
489 	pvhtpriv->max_mpdu_len = proto_cap->max_amsdu_len;
490 
491 	tx_nss = get_phy_tx_nss(padapter);
492 	rx_nss = get_phy_rx_nss(padapter);
493 
494 	/* for now, vhtpriv.vht_mcs_map comes from RX NSS */
495 	rtw_vht_nss_to_mcsmap(rx_nss, pvhtpriv->vht_mcs_map, pregistrypriv->vht_rx_mcs_map);
496 	pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
497 }
498 
rtw_vht_mcs_map_to_bitmap(u8 * mcs_map,u8 nss)499 u64	rtw_vht_mcs_map_to_bitmap(u8 *mcs_map, u8 nss)
500 {
501 	u8 i, j, tmp;
502 	u64 bitmap = 0;
503 	u8 bits_nss = nss * 2;
504 
505 	for (i = j = 0; i < bits_nss; i += 2, j += 10) {
506 		/* every two bits means single sptial stream */
507 		tmp = (mcs_map[i / 8] >> i) & 3;
508 
509 		switch (tmp) {
510 		case 2:
511 			bitmap = bitmap | (0x03ff << j);
512 			break;
513 		case 1:
514 			bitmap = bitmap | (0x01ff << j);
515 			break;
516 		case 0:
517 			bitmap = bitmap | (0x00ff << j);
518 			break;
519 		default:
520 			break;
521 		}
522 	}
523 
524 	RTW_INFO("vht_mcs_map=%02x %02x, nss=%u => bitmap=%016llx\n"
525 		, mcs_map[0], mcs_map[1], nss, bitmap);
526 
527 	return bitmap;
528 }
529 
530 #ifdef CONFIG_BEAMFORMING
update_sta_vht_info_apmode_bf_cap(_adapter * padapter,struct sta_info * psta)531 void update_sta_vht_info_apmode_bf_cap(_adapter *padapter, struct sta_info *psta)
532 {
533 	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
534 	struct vht_priv	*pvhtpriv_ap = &pmlmepriv->vhtpriv;
535 	struct vht_priv	*pvhtpriv_sta = &psta->vhtpriv;
536 	u16	cur_beamform_cap = 0;
537 
538 	/* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */
539 	if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
540 	    GET_VHT_CAPABILITY_ELE_SU_BFEE(pvhtpriv_sta->vht_cap)) {
541 		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
542 		/*Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP*/
543 		SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pvhtpriv_sta->vht_cap) << 8);
544 	}
545 
546 	/* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */
547 	if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
548 	    GET_VHT_CAPABILITY_ELE_SU_BFER(pvhtpriv_sta->vht_cap)) {
549 		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
550 		/*Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM*/
551 		SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pvhtpriv_sta->vht_cap) << 12);
552 	}
553 
554 	if (cur_beamform_cap)
555 		RTW_INFO("Current STA(%d) VHT Beamforming Setting = %02X\n", psta->phl_sta->aid, cur_beamform_cap);
556 
557 	pvhtpriv_sta->beamform_cap = cur_beamform_cap;
558 
559 	/* ToDo: need to API to inform hal_sta->bf_info.vht_beamform_cap  */
560 	#if 0
561 	psta->phl_sta->bf_info.vht_beamform_cap = cur_beamform_cap;
562 	#endif
563 }
564 #endif
565 
update_sta_vht_info_apmode(_adapter * padapter,void * sta)566 void	update_sta_vht_info_apmode(_adapter *padapter, void *sta)
567 {
568 	struct sta_info	*psta = (struct sta_info *)sta;
569 	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
570 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
571 	struct vht_priv	*pvhtpriv_ap = &pmlmepriv->vhtpriv;
572 	struct vht_priv	*pvhtpriv_sta = &psta->vhtpriv;
573 	struct rtw_phl_stainfo_t *phl_sta = psta->phl_sta;
574 	struct rtw_wifi_role_t *wrole = padapter->phl_role;
575 	struct protocol_cap_t *proto_role_cap = &(wrole->proto_role_cap);
576 	u8	cur_ldpc_cap = 0, cur_stbc_cap = 0;
577 	s8 bw_mode = -1;
578 	u8	*pcap_mcs;
579 
580 	if (pvhtpriv_sta->vht_option == _FALSE)
581 		return;
582 
583 	if (pvhtpriv_sta->op_present) {
584 		switch (GET_VHT_OPERATION_ELE_CHL_WIDTH(pvhtpriv_sta->vht_op)) {
585 		case 1: /* 80MHz */
586 		case 2: /* 160MHz */
587 		case 3: /* 80+80 */
588 			bw_mode = CHANNEL_WIDTH_80; /* only support up to 80MHz for now */
589 			break;
590 		}
591 	}
592 
593 	if (pvhtpriv_sta->notify_present)
594 		bw_mode = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&pvhtpriv_sta->vht_op_mode_notify);
595 	else if (MLME_IS_AP(padapter)) {
596 		/* for VHT client without Operating Mode Notify IE; minimal 80MHz */
597 		if (bw_mode < CHANNEL_WIDTH_80)
598 			bw_mode = CHANNEL_WIDTH_80;
599 	}
600 
601 	if (bw_mode != -1)
602 		psta->phl_sta->chandef.bw = bw_mode; /* update bw_mode only if get value from VHT IEs */
603 
604 	/* ToDo: need to API to inform hal_sta->ra_info.is_vht_enable  */
605 	/* psta->phl_sta->ra_info.is_vht_enable = _TRUE; */
606 
607 	/* B4 Rx LDPC */
608 	if (TEST_FLAG(pvhtpriv_ap->ldpc_cap, LDPC_VHT_ENABLE_TX) &&
609 	    GET_VHT_CAPABILITY_ELE_RX_LDPC(pvhtpriv_sta->vht_cap)) {
610 		SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
611 		RTW_INFO("Current STA(%d) VHT LDPC = %02X\n", psta->phl_sta->aid, cur_ldpc_cap);
612 	}
613 	pvhtpriv_sta->ldpc_cap = cur_ldpc_cap;
614 
615 	if (psta->phl_sta->chandef.bw > pmlmeext->chandef.bw)
616 		psta->phl_sta->chandef.bw = pmlmeext->chandef.bw;
617 
618 	if (psta->phl_sta->chandef.bw == CHANNEL_WIDTH_80) {
619 		/* B5 Short GI for 80 MHz */
620 		pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
621 		/* RTW_INFO("Current STA ShortGI80MHz = %d\n", pvhtpriv_sta->sgi_80m); */
622 	} else if (psta->phl_sta->chandef.bw >= CHANNEL_WIDTH_160) {
623 		/* B5 Short GI for 80 MHz */
624 		pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
625 		/* RTW_INFO("Current STA ShortGI160MHz = %d\n", pvhtpriv_sta->sgi_80m); */
626 	}
627 
628 	/* B8 B9 B10 Rx STBC */
629 	if (TEST_FLAG(pvhtpriv_ap->stbc_cap, STBC_VHT_ENABLE_TX) &&
630 	    GET_VHT_CAPABILITY_ELE_RX_STBC(pvhtpriv_sta->vht_cap)) {
631 		SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
632 		RTW_INFO("Current STA(%d) VHT STBC = %02X\n", psta->phl_sta->aid, cur_stbc_cap);
633 		phl_sta->asoc_cap.stbc_vht_rx =
634 			proto_role_cap->stbc_vht_tx ?
635 			GET_VHT_CAPABILITY_ELE_RX_STBC(pvhtpriv_sta->vht_cap) : 0;
636 	}
637 	pvhtpriv_sta->stbc_cap = cur_stbc_cap;
638 	phl_sta->asoc_cap.stbc_vht_tx =
639 		GET_VHT_CAPABILITY_ELE_TX_STBC(pvhtpriv_sta->vht_cap);
640 
641 #ifdef CONFIG_BEAMFORMING
642 	update_sta_vht_info_apmode_bf_cap(padapter, psta);
643 #endif
644 
645 	/* B23 B24 B25 Maximum A-MPDU Length Exponent */
646 	pvhtpriv_sta->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pvhtpriv_sta->vht_cap);
647 
648 	pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pvhtpriv_sta->vht_cap);
649 	_rtw_memcpy(pvhtpriv_sta->vht_mcs_map, pcap_mcs, 2);
650 	pvhtpriv_sta->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv_sta->vht_mcs_map);
651 }
652 
update_hw_vht_param(_adapter * padapter)653 void	update_hw_vht_param(_adapter *padapter)
654 {
655 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
656 	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
657 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
658 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
659 	u8	ht_AMPDU_len;
660 
661 	ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
662 
663 	if (pvhtpriv->ampdu_len > ht_AMPDU_len)
664 		rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
665 }
666 
667 #ifdef ROKU_PRIVATE
VHT_get_ss_from_map(u8 * vht_mcs_map)668 u8 VHT_get_ss_from_map(u8 *vht_mcs_map)
669 {
670 	u8 i, j;
671 	u8 ss = 0;
672 
673 	for (i = 0; i < 2; i++) {
674 		if (vht_mcs_map[i] != 0xff) {
675 			for (j = 0; j < 8; j += 2) {
676 				if (((vht_mcs_map[i] >> j) & 0x03) == 0x03)
677 					break;
678 				ss++;
679 			}
680 		}
681 
682 	}
683 
684 return ss;
685 }
686 
VHT_caps_handler_infra_ap(_adapter * padapter,PNDIS_802_11_VARIABLE_IEs pIE)687 void VHT_caps_handler_infra_ap(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
688 {
689 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
690 	struct vht_priv_infra_ap	*pvhtpriv = &pmlmepriv->vhtpriv_infra_ap;
691 	u8      cur_stbc_cap_infra_ap = 0;
692 	u16	cur_beamform_cap_infra_ap = 0;
693 	u8	*pcap_mcs;
694 	u8	*pcap_mcs_tx;
695 	u8	Rx_ss = 0, Tx_ss = 0;
696 
697 	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
698 	struct mlme_ext_info		*pmlmeinfo = &(pmlmeext->mlmext_info);
699 
700 	if (pIE == NULL)
701 		return;
702 
703 	pmlmeinfo->ht_vht_received |= BIT(1);
704 
705 	pvhtpriv->ldpc_cap_infra_ap = GET_VHT_CAPABILITY_ELE_RX_LDPC(pIE->data);
706 
707 	if (GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data))
708 		SET_FLAG(cur_stbc_cap_infra_ap, STBC_VHT_ENABLE_RX);
709 	if (GET_VHT_CAPABILITY_ELE_TX_STBC(pIE->data))
710 		SET_FLAG(cur_stbc_cap_infra_ap, STBC_VHT_ENABLE_TX);
711 	pvhtpriv->stbc_cap_infra_ap = cur_stbc_cap_infra_ap;
712 
713 	/*store ap info for channel bandwidth*/
714 	pvhtpriv->channel_width_infra_ap = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(pIE->data);
715 
716 	/*check B11: SU Beamformer Capable and B12: SU Beamformee B19: MU Beamformer B20:MU Beamformee*/
717 	if (GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data))
718 		SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
719 	if (GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data))
720 		SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
721 	if (GET_VHT_CAPABILITY_ELE_MU_BFER(pIE->data))
722 		SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
723 	if (GET_VHT_CAPABILITY_ELE_MU_BFEE(pIE->data))
724 		SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
725 	pvhtpriv->beamform_cap_infra_ap = cur_beamform_cap_infra_ap;
726 
727 	/*store information about vht_mcs_set*/
728 	pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
729 	pcap_mcs_tx = GET_VHT_CAPABILITY_ELE_TX_MCS(pIE->data);
730 	_rtw_memcpy(pvhtpriv->vht_mcs_map_infra_ap, pcap_mcs, 2);
731 	_rtw_memcpy(pvhtpriv->vht_mcs_map_tx_infra_ap, pcap_mcs_tx, 2);
732 
733 	Rx_ss = VHT_get_ss_from_map(pvhtpriv->vht_mcs_map_infra_ap);
734 	Tx_ss = VHT_get_ss_from_map(pvhtpriv->vht_mcs_map_tx_infra_ap);
735 	if (Rx_ss >= Tx_ss) {
736 		pvhtpriv->number_of_streams_infra_ap = Rx_ss;
737 	} else{
738 		pvhtpriv->number_of_streams_infra_ap = Tx_ss;
739 	}
740 
741 }
742 #endif /* ROKU_PRIVATE */
743 
VHT_caps_handler(_adapter * padapter,PNDIS_802_11_VARIABLE_IEs pIE)744 void VHT_caps_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
745 {
746 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
747 	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
748 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
749 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
750 	WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
751 	struct sta_priv 	*pstapriv = &padapter->stapriv;
752 	struct sta_info		*psta = NULL;
753 	struct rtw_phl_stainfo_t *phl_sta = NULL;
754 	struct rtw_wifi_role_t 	*wrole = padapter->phl_role;
755 	struct protocol_cap_t *proto_role_cap = &(wrole->proto_role_cap);
756 	u8	cur_ldpc_cap = 0, cur_stbc_cap = 0, rx_nss = 0;
757 	u16	cur_beamform_cap = 0;
758 	u8	*pcap_mcs;
759 
760 	if (pIE == NULL)
761 		return;
762 
763 	if (pvhtpriv->vht_option == _FALSE)
764 		return;
765 
766 	psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
767 	if (psta == NULL)
768 		return;
769 	phl_sta = psta->phl_sta;
770 
771 	pmlmeinfo->VHT_enable = 1;
772 
773 	/* B4 Rx LDPC */
774 	if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX) &&
775 	    GET_VHT_CAPABILITY_ELE_RX_LDPC(pIE->data)) {
776 		SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
777 		RTW_INFO("Current VHT LDPC Setting = %02X\n", cur_ldpc_cap);
778 		phl_sta->asoc_cap.vht_ldpc = 1;
779 	}
780 	pvhtpriv->ldpc_cap = cur_ldpc_cap;
781 
782 	/* B5 Short GI for 80 MHz */
783 	pvhtpriv->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pIE->data) & pvhtpriv->sgi_80m) ? _TRUE : _FALSE;
784 	/* RTW_INFO("Current ShortGI80MHz = %d\n", pvhtpriv->sgi_80m); */
785 
786 	/* B8 B9 B10 Rx STBC */
787 	if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX) &&
788 	    GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data)) {
789 		SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
790 		RTW_INFO("Current VHT STBC Setting = %02X\n", cur_stbc_cap);
791 		phl_sta->asoc_cap.stbc_vht_rx =
792 			proto_role_cap->stbc_vht_tx ?
793 			GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data) : 0;
794 	}
795 	pvhtpriv->stbc_cap = cur_stbc_cap;
796 	phl_sta->asoc_cap.stbc_vht_tx = GET_VHT_CAPABILITY_ELE_TX_STBC(pIE->data);
797 
798 	phl_sta->asoc_cap.vht_su_bfmr = GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data);
799 	phl_sta->asoc_cap.vht_su_bfme = GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data);
800 	phl_sta->asoc_cap.vht_mu_bfmr = GET_VHT_CAPABILITY_ELE_MU_BFER(pIE->data);
801 	phl_sta->asoc_cap.bfme_sts = GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pIE->data);
802 	phl_sta->asoc_cap.num_snd_dim = GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pIE->data);
803 
804 	RTW_INFO("%s: VHT STA assoc_cap:\n", __func__);
805 	RTW_INFO("- SU BFer: %d\n", phl_sta->asoc_cap.vht_su_bfmr);
806 	RTW_INFO("- SU BFee: %d\n", phl_sta->asoc_cap.vht_su_bfme);
807 	RTW_INFO("- MU BFer: %d\n", phl_sta->asoc_cap.vht_mu_bfmr);
808 	RTW_INFO("- BFee STS: %d\n", phl_sta->asoc_cap.bfme_sts);
809 	RTW_INFO("- BFer SND DIM number: %d\n", phl_sta->asoc_cap.num_snd_dim);
810 
811 #ifdef CONFIG_BEAMFORMING
812 	/*
813 	 * B11 SU Beamformer Capable,
814 	 * the target supports Beamformer and we are Beamformee
815 	 */
816 	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)
817 	    && GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data)) {
818 		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
819 
820 		/* Shift to BEAMFORMING_VHT_BEAMFORMEE_STS_CAP */
821 		SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pIE->data) << 8);
822 
823 		/*
824 		 * B19 MU Beamformer Capable,
825 		 * the target supports Beamformer and we are Beamformee
826 		 */
827 		if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)
828 		    && GET_VHT_CAPABILITY_ELE_MU_BFER(pIE->data))
829 			SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
830 	}
831 
832 	/*
833 	 * B12 SU Beamformee Capable,
834 	 * the target supports Beamformee and we are Beamformer
835 	 */
836 	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)
837 	    && GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data)) {
838 		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
839 
840 		/* Shit to BEAMFORMING_VHT_BEAMFORMER_SOUND_DIM */
841 		SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pIE->data) << 12);
842 
843 		/*
844 		 * B20 MU Beamformee Capable,
845 		 * the target supports Beamformee and we are Beamformer
846 		 */
847 		if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)
848 		    && GET_VHT_CAPABILITY_ELE_MU_BFEE(pIE->data))
849 			SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
850 	}
851 
852 	pvhtpriv->beamform_cap = cur_beamform_cap;
853 	RTW_INFO("Current VHT Beamforming Setting=0x%04X\n", cur_beamform_cap);
854 #endif /* CONFIG_BEAMFORMING */
855 
856 	/* B0 B1 Maximum MPDU Length */
857 	pvhtpriv->max_mpdu_len = GET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pIE->data);
858 	/* B23 B24 B25 Maximum A-MPDU Length Exponent */
859 	pvhtpriv->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pIE->data);
860 
861 	pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
862 	rx_nss = get_phy_rx_nss(padapter);
863 	rtw_vht_nss_to_mcsmap(rx_nss, pvhtpriv->vht_mcs_map, pcap_mcs);
864 	pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
865 }
866 
VHT_operation_handler(_adapter * padapter,PNDIS_802_11_VARIABLE_IEs pIE)867 void VHT_operation_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
868 {
869 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
870 	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
871 
872 	if (pIE == NULL)
873 		return;
874 
875 	if (pvhtpriv->vht_option == _FALSE)
876 		return;
877 
878 	if (pIE->Length != VHT_OP_IE_LEN) {
879 		RTW_WARN("%s: unexpected IE length(%u)!\n",
880 			 __func__, pIE->Length);
881 	}
882 
883 	pvhtpriv->op_present = 1;
884 	_rtw_memcpy(pvhtpriv->vht_op, pIE->data,
885 		    pIE->Length > VHT_OP_IE_LEN ? VHT_OP_IE_LEN : pIE->Length);
886 }
887 
rtw_process_vht_op_mode_notify(_adapter * padapter,u8 * pframe,void * sta)888 void rtw_process_vht_op_mode_notify(_adapter *padapter, u8 *pframe, void *sta)
889 {
890 	struct sta_info		*psta = (struct sta_info *)sta;
891 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
892 	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
893 	struct registry_priv *regsty = adapter_to_regsty(padapter);
894 	u8	target_bw;
895 	u8	target_rxss, current_rxss;
896 	u8	update_ra = _FALSE;
897 	u8 tx_nss = 0;
898 
899 	if (pvhtpriv->vht_option == _FALSE)
900 		return;
901 
902 	target_bw = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(pframe);
903 	tx_nss = get_phy_tx_nss(padapter);
904 	target_rxss = rtw_min(tx_nss, (GET_VHT_OPERATING_MODE_FIELD_RX_NSS(pframe) + 1));
905 
906 	if (target_bw != psta->phl_sta->chandef.bw) {
907 		if (rtw_hw_is_bw_support(adapter_to_dvobj(padapter), target_bw)
908 		    && REGSTY_IS_BW_5G_SUPPORT(regsty, target_bw)
909 		   ) {
910 			update_ra = _TRUE;
911 			psta->phl_sta->chandef.bw = target_bw;
912 		}
913 	}
914 
915 	current_rxss = rtw_vht_mcsmap_to_nss(psta->vhtpriv.vht_mcs_map);
916 	if (target_rxss != current_rxss) {
917 		u8	vht_mcs_map[2] = {};
918 
919 		update_ra = _TRUE;
920 
921 		rtw_vht_nss_to_mcsmap(target_rxss, vht_mcs_map, psta->vhtpriv.vht_mcs_map);
922 		_rtw_memcpy(psta->vhtpriv.vht_mcs_map, vht_mcs_map, 2);
923 
924 		update_sta_ra_info(padapter, psta);
925 	}
926 
927 	if (update_ra) {
928 		rtw_phl_cmd_change_stainfo(adapter_to_dvobj(padapter)->phl,
929 					   psta->phl_sta,
930 					   STA_CHG_RAMASK,
931 					   NULL,
932 					   0,
933 					   PHL_CMD_NO_WAIT,
934 					   0);
935 	}
936 }
937 
rtw_build_vht_operation_ie(_adapter * padapter,u8 * pbuf,u8 channel)938 u32	rtw_build_vht_operation_ie(_adapter *padapter, u8 *pbuf, u8 channel)
939 {
940 	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
941 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
942 	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
943 	/* struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv; */
944 	u8	ChnlWidth, center_freq, bw_mode;
945 	u32	len = 0;
946 	u8	operation[5];
947 
948 	_rtw_memset(operation, 0, 5);
949 
950 	bw_mode = REGSTY_BW_5G(pregistrypriv); /* TODO: control op bw with other info */
951 
952 	if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_80M | BW_CAP_160M)
953 	    && REGSTY_BW_5G(pregistrypriv) >= CHANNEL_WIDTH_80
954 	   ) {
955 		center_freq = rtw_phl_get_center_ch(channel, get_highest_bw_cap(bw_mode), CHAN_OFFSET_UPPER);
956 		ChnlWidth = 1;
957 	} else {
958 		center_freq = 0;
959 		ChnlWidth = 0;
960 	}
961 
962 
963 	SET_VHT_OPERATION_ELE_CHL_WIDTH(operation, ChnlWidth);
964 	/* center frequency */
965 	SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(operation, center_freq);/* Todo: need to set correct center channel */
966 	SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(operation, 0);
967 
968 	_rtw_memcpy(operation + 3, pvhtpriv->vht_mcs_map, 2);
969 
970 	rtw_set_ie(pbuf, EID_VHTOperation, 5, operation, &len);
971 
972 	return len;
973 }
974 
rtw_build_vht_op_mode_notify_ie(_adapter * padapter,u8 * pbuf,u8 bw)975 u32	rtw_build_vht_op_mode_notify_ie(_adapter *padapter, u8 *pbuf, u8 bw)
976 {
977 	/* struct registry_priv *pregistrypriv = &padapter->registrypriv; */
978 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
979 	struct vht_priv	*pvhtpriv = &pmlmepriv->vhtpriv;
980 	u32	len = 0;
981 	u8	opmode = 0;
982 	u8	chnl_width, rx_nss;
983 
984 	chnl_width = bw;
985 	rx_nss = rtw_vht_mcsmap_to_nss(pvhtpriv->vht_mcs_map);
986 
987 	SET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&opmode, chnl_width);
988 	SET_VHT_OPERATING_MODE_FIELD_RX_NSS(&opmode, (rx_nss - 1));
989 	SET_VHT_OPERATING_MODE_FIELD_RX_NSS_TYPE(&opmode, 0); /* Todo */
990 
991 	pvhtpriv->vht_op_mode_notify = opmode;
992 
993 	pbuf = rtw_set_ie(pbuf, EID_OpModeNotification, 1, &opmode, &len);
994 
995 	return len;
996 }
997 
rtw_build_vht_cap_ie(_adapter * padapter,u8 * pbuf)998 u32	rtw_build_vht_cap_ie(_adapter *padapter, u8 *pbuf)
999 {
1000 	u8 bw;
1001 	u16 HighestRate;
1002 	u8 *pcap, *pcap_mcs;
1003 	u32 len = 0;
1004 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
1005 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1006 	struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
1007 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1008 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1009 
1010 	pcap = pvhtpriv->vht_cap;
1011 	_rtw_memset(pcap, 0, 32);
1012 
1013 	/*
1014 	* VHT Capabilities Information field : B0 to B31
1015 	*/
1016 
1017 	/* B0 B1 Maximum MPDU Length */
1018 	SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, pvhtpriv->max_mpdu_len);
1019 
1020 	/* B2 B3 Supported Channel Width Set */
1021 	if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) {
1022 		if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_80_80M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_80_80)) {
1023 			SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 2);
1024 			RTW_INFO("[VHT] Declare supporting 160MHz and 80+80MHz\n");
1025 		} else {
1026 			SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 1);
1027 			RTW_INFO("[VHT] Declare supporting 160MHz\n");
1028 		}
1029 	} else
1030 		SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 0);
1031 
1032 	/* B4 Rx LDPC */
1033 	if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX)) {
1034 		SET_VHT_CAPABILITY_ELE_RX_LDPC(pcap, 1);
1035 		RTW_INFO("[VHT] Declare supporting RX LDPC\n");
1036 	}
1037 
1038 	/* B5 ShortGI for 80MHz */
1039 	SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pcap, pvhtpriv->sgi_80m ? 1 : 0);
1040 	if (pvhtpriv->sgi_80m)
1041 		RTW_INFO("[VHT] Declare supporting SGI 80MHz\n");
1042 
1043 	/* B6 Short GI for 160 and 80+80 MHz */
1044 	SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pcap, pvhtpriv->sgi_160m ? 1 : 0);
1045 	if (pvhtpriv->sgi_160m) {
1046 		RTW_INFO("[VHT] Declare supporting SGI 160MHz and 80+80MHz\n");
1047 	}
1048 
1049 	/* B7 Tx STBC */
1050 	if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX)) {
1051 		SET_VHT_CAPABILITY_ELE_TX_STBC(pcap, 1);
1052 		RTW_INFO("[VHT] Declare supporting TX STBC\n");
1053 	}
1054 
1055 	/* B8 B9 B10 Rx STBC */
1056 	if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX)) {
1057 		SET_VHT_CAPABILITY_ELE_RX_STBC(pcap, pvhtpriv->rx_stbc_nss);
1058 		RTW_INFO("[VHT] Declare supporting RX STBC = %d\n", pvhtpriv->rx_stbc_nss);
1059 	}
1060 
1061 	#ifdef CONFIG_BEAMFORMING
1062 	/* B11 SU Beamformer Capable */
1063 	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
1064 		SET_VHT_CAPABILITY_ELE_SU_BFER(pcap, 1);
1065 		RTW_INFO("[VHT] Declare supporting SU Beamformer\n");
1066 		/* B16 17 18 Number of Sounding Dimensions */
1067 		SET_VHT_CAPABILITY_ELE_SOUNDING_DIMENSIONS(pcap, pvhtpriv->num_snd_dim);
1068 		/* B19 MU Beamformer Capable */
1069 		if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
1070 			SET_VHT_CAPABILITY_ELE_MU_BFER(pcap, 1);
1071 			RTW_INFO("[VHT] Declare supporting MU Beamformer\n");
1072 		}
1073 	}
1074 
1075 	/* B12 SU Beamformee Capable */
1076 	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
1077 		u8 bfme_sts = pvhtpriv->bfme_sts;
1078 
1079 		SET_VHT_CAPABILITY_ELE_SU_BFEE(pcap, 1);
1080 		RTW_INFO("[VHT] Declare supporting SU Beamformee\n");
1081 
1082 		/* IOT action suggested by Yu Chen 2017/3/3 */
1083 		if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM) &&
1084 			!pvhtpriv->ap_bf_cap.is_mu_bfer &&
1085 			pvhtpriv->ap_bf_cap.su_sound_dim == 2)
1086 			bfme_sts = (bfme_sts >= 2 ? 2 : bfme_sts);
1087 
1088 		/* B13 14 15 Beamformee STS Capability */
1089 		SET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pcap, bfme_sts);
1090 
1091 		/* B20 MU Beamformee Capable */
1092 		if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) {
1093 			SET_VHT_CAPABILITY_ELE_MU_BFEE(pcap, 1);
1094 			RTW_INFO("[VHT] Declare supporting MU Beamformee\n");
1095 		}
1096 	}
1097 	#endif/*CONFIG_BEAMFORMING*/
1098 
1099 	/* B21 VHT TXOP PS */
1100 	if (pvhtpriv->txop_ps) {
1101 		SET_VHT_CAPABILITY_ELE_TXOP_PS(pcap, 1);
1102 		RTW_INFO("[VHT] Declare supporting VHT TXOP power save\n");
1103 	}
1104 
1105 	/* B22 +HTC-VHT Capable */
1106 	if (pvhtpriv->htc_vht) {
1107 		SET_VHT_CAPABILITY_ELE_HTC_VHT(pcap, 1);
1108 		RTW_INFO("[VHT] Declare supporting VHT variant HT Control\n");
1109 	}
1110 
1111 	/* B23 24 25 Maximum A-MPDU Length Exponent */
1112 	SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, pvhtpriv->ampdu_len);
1113 	RTW_INFO("[VHT] Declare supporting RX A-MPDU Length Exponent = %u\n", pvhtpriv->ampdu_len);
1114 
1115 	/* B26 27 VHT Link Adaptation Capable */
1116 	if (pvhtpriv->link_adap_cap) {
1117 		SET_VHT_CAPABILITY_ELE_LINK_ADAPTION(pcap, 1);
1118 		RTW_INFO("[VHT] Declare supporting link adaptation using VHT variant HT Control\n");
1119 	}
1120 
1121 	/* B28 Rx Antenna Pattern Consistency */
1122 	if (pvhtpriv->rx_ant_pattern) {
1123 		SET_VHT_CAPABILITY_ELE_RX_ANT_PATTERN(pcap, 1);
1124 		RTW_INFO("[VHT] Declare supporting RX Antenna Pattern Consistency\n");
1125 	}
1126 
1127 	/* B29 Tx Antenna Pattern Consistency */
1128 	if (pvhtpriv->tx_ant_pattern) {
1129 		SET_VHT_CAPABILITY_ELE_TX_ANT_PATTERN(pcap, 1);
1130 		RTW_INFO("[VHT] Declare supporting TX Antenna Pattern Consistency\n");
1131 	}
1132 
1133 	/* B30 B31 Extended NSS BW Support */
1134 	SET_VHT_CAPABILITY_ELE_EXT_NSS_BW(pcap, pvhtpriv->ext_nss_bw);
1135 
1136 	/*
1137 	* Supported VHT-MCS and NSS Set : 8 bytes
1138 	*/
1139 	pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pcap);
1140 	_rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
1141 
1142 	pcap_mcs = GET_VHT_CAPABILITY_ELE_TX_MCS(pcap);
1143 	_rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
1144 
1145 	/* find the largest bw supported by both registry and hal */
1146 	bw = rtw_hw_largest_bw(adapter_to_dvobj(padapter), REGSTY_BW_5G(pregistrypriv));
1147 
1148 	HighestRate = VHT_MCS_DATA_RATE[bw][pvhtpriv->sgi_80m][((pvhtpriv->vht_highest_rate - MGN_VHT1SS_MCS0) & 0x3f)];
1149 	HighestRate = (HighestRate + 1) >> 1;
1150 
1151 	SET_VHT_CAPABILITY_ELE_MCS_RX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest rx rate is 600Mbps. */
1152 	SET_VHT_CAPABILITY_ELE_MCS_TX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest tx rate is 600Mbps. */
1153 
1154 	pbuf = rtw_set_ie(pbuf, EID_VHTCapability, 12, pcap, &len);
1155 
1156 	return len;
1157 }
1158 
rtw_restructure_vht_ie(_adapter * padapter,u8 * in_ie,u8 * out_ie,uint in_len,uint * pout_len,struct country_chplan * req_chplan)1159 u32 rtw_restructure_vht_ie(_adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len, struct country_chplan *req_chplan)
1160 {
1161 	struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1162 	RT_CHANNEL_INFO *chset = rfctl->channel_set;
1163 	u32	ielen;
1164 	u8 max_bw;
1165 	u8 oper_ch, oper_bw = CHANNEL_WIDTH_20, oper_offset = CHAN_OFFSET_NO_EXT;
1166 	u8 *out_vht_op_ie, *ht_op_ie, *vht_cap_ie, *vht_op_ie;
1167 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
1168 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
1169 	struct vht_priv	*pvhtpriv = &pmlmepriv->vhtpriv;
1170 
1171 	rtw_vht_get_real_setting(padapter);
1172 
1173 	ht_op_ie = rtw_get_ie(in_ie + 12, WLAN_EID_HT_OPERATION, &ielen, in_len - 12);
1174 	if (!ht_op_ie || ielen != HT_OP_IE_LEN)
1175 		goto exit;
1176 	vht_cap_ie = rtw_get_ie(in_ie + 12, EID_VHTCapability, &ielen, in_len - 12);
1177 	if (!vht_cap_ie || ielen != VHT_CAP_IE_LEN)
1178 		goto exit;
1179 	vht_op_ie = rtw_get_ie(in_ie + 12, EID_VHTOperation, &ielen, in_len - 12);
1180 	if (!vht_op_ie || ielen != VHT_OP_IE_LEN)
1181 		goto exit;
1182 
1183 	/* VHT Capabilities element */
1184 	*pout_len += rtw_build_vht_cap_ie(padapter, out_ie + *pout_len);
1185 
1186 
1187 	/* VHT Operation element */
1188 	out_vht_op_ie = out_ie + *pout_len;
1189 	rtw_set_ie(out_vht_op_ie, EID_VHTOperation, VHT_OP_IE_LEN, vht_op_ie + 2 , pout_len);
1190 
1191 	/* get primary channel from HT_OP_IE */
1192 	oper_ch = GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2);
1193 
1194 	/* find the largest bw supported by both registry and hal */
1195 	max_bw = rtw_hw_largest_bw(adapter_to_dvobj(padapter), REGSTY_BW_5G(pregistrypriv));
1196 
1197 	if (max_bw >= CHANNEL_WIDTH_40) {
1198 		/* get bw offset form HT_OP_IE */
1199 		if (GET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2)) {
1200 			switch (GET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2)) {
1201 			case IEEE80211_SCA:
1202 				oper_bw = CHANNEL_WIDTH_40;
1203 				oper_offset = CHAN_OFFSET_UPPER;
1204 				break;
1205 			case IEEE80211_SCB:
1206 				oper_bw = CHANNEL_WIDTH_40;
1207 				oper_offset = CHAN_OFFSET_LOWER;
1208 				break;
1209 			}
1210 		}
1211 
1212 		if (oper_bw == CHANNEL_WIDTH_40) {
1213 			switch (GET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2)) {
1214 			case 1: /* 80MHz */
1215 			case 2: /* 160MHz */
1216 			case 3: /* 80+80 */
1217 				oper_bw = CHANNEL_WIDTH_80; /* only support up to 80MHz for now */
1218 				break;
1219 			}
1220 
1221 			oper_bw = rtw_min(oper_bw, max_bw);
1222 
1223 			/* try downgrage bw to fit in channel plan setting */
1224 			while ((req_chplan && !rtw_country_chplan_is_chbw_valid(req_chplan, BAND_ON_5G, oper_ch, oper_bw, oper_offset, 1, 1, pregistrypriv))
1225 				|| (!req_chplan && !rtw_chset_is_chbw_valid(chset, oper_ch, oper_bw, oper_offset, 1, 1))
1226 				|| (IS_DFS_SLAVE_WITH_RD(rfctl)
1227 					&& !rtw_rfctl_dfs_domain_unknown(rfctl)
1228 					&& rtw_chset_is_chbw_non_ocp(chset, oper_ch, oper_bw, oper_offset))
1229 			) {
1230 				oper_bw--;
1231 				if (oper_bw == CHANNEL_WIDTH_20) {
1232 					oper_offset = CHAN_OFFSET_NO_EXT;
1233 					break;
1234 				}
1235 			}
1236 		}
1237 	}
1238 
1239 	rtw_warn_on(req_chplan && !rtw_country_chplan_is_chbw_valid(req_chplan, BAND_ON_5G, oper_ch, oper_bw, oper_offset, 1, 1, pregistrypriv));
1240 	rtw_warn_on(!req_chplan && !rtw_chset_is_chbw_valid(chset, oper_ch, oper_bw, oper_offset, 1, 1));
1241 	if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_rfctl_dfs_domain_unknown(rfctl))
1242 		rtw_warn_on(rtw_chset_is_chbw_non_ocp(chset, oper_ch, oper_bw, oper_offset));
1243 
1244 	/* update VHT_OP_IE */
1245 	if (oper_bw < CHANNEL_WIDTH_80) {
1246 		SET_VHT_OPERATION_ELE_CHL_WIDTH(out_vht_op_ie + 2, 0);
1247 		SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(out_vht_op_ie + 2, 0);
1248 		SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(out_vht_op_ie + 2, 0);
1249 	} else if (oper_bw == CHANNEL_WIDTH_80) {
1250 		u8 cch = rtw_phl_get_center_ch(oper_ch, oper_bw, oper_offset);
1251 
1252 		SET_VHT_OPERATION_ELE_CHL_WIDTH(out_vht_op_ie + 2, 1);
1253 		SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(out_vht_op_ie + 2, cch);
1254 		SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(out_vht_op_ie + 2, 0);
1255 	} else {
1256 		RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(padapter), oper_bw);
1257 		rtw_warn_on(1);
1258 	}
1259 
1260 	/* Operating Mode Notification element */
1261 	*pout_len += rtw_build_vht_op_mode_notify_ie(padapter, out_ie + *pout_len, oper_bw);
1262 
1263 	pvhtpriv->vht_option = _TRUE;
1264 
1265 exit:
1266 	return pvhtpriv->vht_option;
1267 
1268 }
1269 
VHTOnAssocRsp(_adapter * padapter)1270 void VHTOnAssocRsp(_adapter *padapter)
1271 {
1272 	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
1273 	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
1274 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
1275 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
1276 	u8	ht_AMPDU_len;
1277 
1278 	RTW_INFO("%s\n", __FUNCTION__);
1279 
1280 	if (!pmlmeinfo->HT_enable)
1281 		return;
1282 
1283 	if (!pmlmeinfo->VHT_enable)
1284 		return;
1285 
1286 	ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
1287 
1288 	if (pvhtpriv->ampdu_len > ht_AMPDU_len)
1289 		rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
1290 
1291 	rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MAX_TIME, (u8 *)(&pvhtpriv->vht_highest_rate));
1292 }
1293 
rtw_vht_ies_attach(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1294 void rtw_vht_ies_attach(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1295 {
1296 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1297 	u8 cap_len, operation_len;
1298 	uint len = 0;
1299 	sint ie_len = 0;
1300 	u8 *p = NULL;
1301 
1302 	p = rtw_get_ie(pnetwork->IEs + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len,
1303 			(pnetwork->IELength - _BEACON_IE_OFFSET_));
1304 	if (p && ie_len > 0)
1305 		return;
1306 
1307 	rtw_vht_get_real_setting(padapter);
1308 
1309 	/* VHT Operation mode notifiy bit in Extended IE (127) */
1310 	rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1311 	rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1312 		, &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1313 
1314 	/* VHT Capabilities element */
1315 	cap_len = rtw_build_vht_cap_ie(padapter, pnetwork->IEs + pnetwork->IELength);
1316 	pnetwork->IELength += cap_len;
1317 
1318 	/* VHT Operation element */
1319 	operation_len = rtw_build_vht_operation_ie(padapter, pnetwork->IEs + pnetwork->IELength,
1320 										pnetwork->Configuration.DSConfig);
1321 	pnetwork->IELength += operation_len;
1322 
1323 	rtw_check_for_vht20(padapter, pnetwork->IEs + _BEACON_IE_OFFSET_, pnetwork->IELength - _BEACON_IE_OFFSET_);
1324 
1325 	pmlmepriv->vhtpriv.vht_option = _TRUE;
1326 }
1327 
rtw_vht_ies_detach(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1328 void rtw_vht_ies_detach(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1329 {
1330 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1331 
1332 	rtw_remove_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1333 	rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1334 		, &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1335 
1336 	rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTCapability);
1337 	rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTOperation);
1338 	rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTTransmitPower);
1339 
1340 	pmlmepriv->vhtpriv.vht_option = _FALSE;
1341 }
1342 
rtw_check_for_vht20(_adapter * adapter,u8 * ies,int ies_len)1343 void rtw_check_for_vht20(_adapter *adapter, u8 *ies, int ies_len)
1344 {
1345 	u8 ht_ch, ht_bw, ht_offset;
1346 	u8 vht_ch, vht_bw, vht_offset;
1347 
1348 	rtw_ies_get_chbw(ies, ies_len, &ht_ch, &ht_bw, &ht_offset, 1, 0);
1349 	rtw_ies_get_chbw(ies, ies_len, &vht_ch, &vht_bw, &vht_offset, 1, 1);
1350 
1351 	if (ht_bw == CHANNEL_WIDTH_20 && vht_bw >= CHANNEL_WIDTH_80) {
1352 		u8 *vht_op_ie;
1353 		int vht_op_ielen;
1354 
1355 		RTW_INFO(FUNC_ADPT_FMT" vht80 is not allowed without ht40\n", FUNC_ADPT_ARG(adapter));
1356 		vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &vht_op_ielen, ies_len);
1357 		if (vht_op_ie && vht_op_ielen) {
1358 			RTW_INFO(FUNC_ADPT_FMT" switch to vht20\n", FUNC_ADPT_ARG(adapter));
1359 			SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0);
1360 			SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0);
1361 			SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
1362 		}
1363 	}
1364 }
1365 
1366 /* We need to update the (mlmepriv->vhtpriv) */
rtw_update_drv_vht_cap(_adapter * padapter,u8 * vht_cap_ie)1367 void rtw_update_drv_vht_cap(_adapter *padapter, u8 *vht_cap_ie)
1368 {
1369 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1370 	struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1371 	struct registry_priv *pregpriv = &padapter->registrypriv;
1372 	s32 ie_len = 0;
1373 	u32 rx_packet_offset, max_recvbuf_sz, available_mpdu_sz;
1374 	u8 cap_val;
1375 	u8 *pvht_cap;
1376 
1377 	/* Initialize VHT capability element */
1378 	rtw_vht_get_real_setting(padapter);
1379 
1380 	RTW_INFO("Don't setting VHT capability IE from hostap, builded by driver temporarily\n");
1381 	rtw_build_vht_cap_ie(padapter, vht_cap_ie);
1382 }
1383 
rtw_check_vht_ies(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1384 void rtw_check_vht_ies(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1385 {
1386 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1387 	struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1388 	u32 ie_len;
1389 	u32 ies_len = pnetwork->IELength - _BEACON_IE_OFFSET_;
1390 	u8 *ies = pnetwork->IEs + _BEACON_IE_OFFSET_;
1391 	u8 *vht_cap_ie, *vht_op_ie;
1392 
1393 	vht_cap_ie = rtw_get_ie(ies, EID_VHTCapability, &ie_len, ies_len);
1394 
1395 	vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &ie_len, ies_len);
1396 
1397 	rtw_update_drv_vht_cap(padapter, vht_cap_ie);
1398 
1399 	rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1400 	rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1401 		, &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1402 
1403 	/* Backup these two VHT IEs from hostapd/wpa_supplicant for restore usage */
1404 	if (vht_cap_ie != NULL)
1405 		_rtw_memcpy(pvhtpriv->vht_cap_ie_backup, vht_cap_ie + 2, VHT_CAP_IE_LEN);
1406 
1407 	if (vht_op_ie != NULL)
1408 		_rtw_memcpy(pvhtpriv->vht_op_ie_backup, vht_op_ie + 2, VHT_OP_IE_LEN);
1409 
1410 	/* TODO : We don't handle this IE like before, so remove it */
1411 	rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTTransmitPower);
1412 }
1413 
rtw_reattach_vht_ies(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1414 void rtw_reattach_vht_ies(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1415 {
1416 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1417 	struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1418 	u8 *vht_cap_ie = pnetwork->IEs + pnetwork->IELength;
1419 	u8 *vht_op_ie;
1420 
1421 	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1422 
1423 	if (pnetwork->IEs != NULL) {
1424 		vht_op_ie = rtw_set_ie(vht_cap_ie, EID_VHTCapability, VHT_CAP_IE_LEN,
1425 			pvhtpriv->vht_cap_ie_backup, &(pnetwork->IELength));
1426 
1427 		rtw_set_ie(vht_op_ie, EID_VHTOperation, VHT_OP_IE_LEN,
1428 			pvhtpriv->vht_op_ie_backup, &(pnetwork->IELength));
1429 
1430 		rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1431 		rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1432 		, &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1433 	}
1434 
1435 	pmlmepriv->vhtpriv.vht_option = _TRUE;
1436 }
1437 #endif /* CONFIG_80211AC_VHT */
1438