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