• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2019 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 
16 #include <drv_types.h>
17 #include <hal_data.h>
18 #ifdef CONFIG_RTW_80211K
19 #include "rtw_rm_fsm.h"
20 #include "rtw_rm_util.h"
21 
22 /* 802.11-2012 Table E-1 Operationg classes in United States */
23 static RT_OPERATING_CLASS RTW_OP_CLASS_US[] = {
24 	/* 0, OP_CLASS_NULL */	{  0,  0, {}},
25 	/* 1, OP_CLASS_1 */	{115,  4, {36, 40, 44, 48}},
26 	/* 2, OP_CLASS_2 */	{118,  4, {52, 56, 60, 64}},
27 	/* 3, OP_CLASS_3 */	{124,  4, {149, 153, 157, 161}},
28 	/* 4, OP_CLASS_4 */	{121, 11, {100, 104, 108, 112, 116, 120, 124,
29 						128, 132, 136, 140}},
30 	/* 5, OP_CLASS_5 */	{125,  5, {149, 153, 157, 161, 165}},
31 	/* 6, OP_CLASS_12 */	{ 81, 11, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}
32 };
33 
rm_get_ch_set(struct rtw_ieee80211_channel * pch_set,u8 op_class,u8 ch_num)34 u8 rm_get_ch_set(
35 	struct rtw_ieee80211_channel *pch_set, u8 op_class, u8 ch_num)
36 {
37 	int i,j,sz;
38 	u8 ch_amount = 0;
39 
40 
41 	sz = sizeof(RTW_OP_CLASS_US)/sizeof(struct _RT_OPERATING_CLASS);
42 
43 	if (ch_num != 0) {
44 		pch_set[0].hw_value = ch_num;
45 		ch_amount = 1;
46 		RTW_INFO("RM: meas_ch->hw_value = %u\n", pch_set->hw_value);
47 		goto done;
48 	}
49 
50 	for (i = 0; i < sz; i++) {
51 
52 		if (RTW_OP_CLASS_US[i].global_op_class == op_class) {
53 
54 			for (j = 0; j < RTW_OP_CLASS_US[i].Len; j++) {
55 				pch_set[j].hw_value =
56 					RTW_OP_CLASS_US[i].Channel[j];
57 				RTW_INFO("RM: meas_ch[%d].hw_value = %u\n",
58 					j, pch_set[j].hw_value);
59 			}
60 			ch_amount = RTW_OP_CLASS_US[i].Len;
61 			break;
62 		}
63 	}
64 done:
65 	return ch_amount;
66 }
67 
rm_get_ch_set_from_bcn_req_opt(struct rtw_ieee80211_channel * pch_set,struct bcn_req_opt * opt)68 u8 rm_get_ch_set_from_bcn_req_opt(
69 	struct rtw_ieee80211_channel *pch_set, struct bcn_req_opt *opt)
70 {
71 	int i,j,k,sz;
72 	struct _RT_OPERATING_CLASS *ap_ch_rpt;
73 	u8 ch_amount = 0;
74 
75 	k = 0;
76 	for (i = 0; i < opt->ap_ch_rpt_num; i++) {
77 		if (opt->ap_ch_rpt[i] == NULL)
78 			break;
79 		ap_ch_rpt = opt->ap_ch_rpt[i];
80 		for (j = 0; j < ap_ch_rpt->Len; j++) {
81 			pch_set[k].hw_value =
82 				ap_ch_rpt->Channel[j];
83 			RTW_INFO("RM: meas_ch[%d].hw_value = %u\n",
84 				j, pch_set[k].hw_value);
85 			k++;
86 		}
87 	}
88 	return k;
89 }
90 
rm_get_oper_class_via_ch(u8 ch)91 u8 rm_get_oper_class_via_ch(u8 ch)
92 {
93 	int i,j,sz;
94 
95 
96 	sz = sizeof(RTW_OP_CLASS_US)/sizeof(struct _RT_OPERATING_CLASS);
97 
98 	for (i = 0; i < sz; i++) {
99 		for (j = 0; j < RTW_OP_CLASS_US[i].Len; j++) {
100 			if ( ch == RTW_OP_CLASS_US[i].Channel[j]) {
101 				RTW_INFO("RM: ch %u in oper_calss %u\n",
102 					ch, RTW_OP_CLASS_US[i].global_op_class);
103 				return RTW_OP_CLASS_US[i].global_op_class;
104 				break;
105 			}
106 		}
107 	}
108 	return 0;
109 }
110 
is_wildcard_bssid(u8 * bssid)111 int is_wildcard_bssid(u8 *bssid)
112 {
113 	int i;
114 	u8 val8 = 0xff;
115 
116 
117 	for (i=0;i<6;i++)
118 		val8 &= bssid[i];
119 
120 	if (val8 == 0xff)
121 		return _SUCCESS;
122 	return _FALSE;
123 }
124 
translate_dbm_to_rcpi(s8 SignalPower)125 u8 translate_dbm_to_rcpi(s8 SignalPower)
126 {
127 	/* RCPI = Int{(Power in dBm + 110)*2} for 0dBm > Power > -110dBm
128 	 *    0	: power <= -110.0 dBm
129 	 *    1	: power =  -109.5 dBm
130 	 *    2	: power =  -109.0 dBm
131 	 */
132 	return (SignalPower + 110)*2;
133 }
134 
translate_percentage_to_rcpi(u32 SignalStrengthIndex)135 u8 translate_percentage_to_rcpi(u32 SignalStrengthIndex)
136 {
137 	/* Translate to dBm (x=y-100) */
138 	return translate_dbm_to_rcpi(SignalStrengthIndex - 100);
139 }
140 
rm_get_bcn_rcpi(struct rm_obj * prm,struct wlan_network * pnetwork)141 u8 rm_get_bcn_rcpi(struct rm_obj *prm, struct wlan_network *pnetwork)
142 {
143 	return translate_percentage_to_rcpi(
144 		pnetwork->network.PhyInfo.SignalStrength);
145 }
146 
rm_get_frame_rsni(struct rm_obj * prm,union recv_frame * pframe)147 u8 rm_get_frame_rsni(struct rm_obj *prm, union recv_frame *pframe)
148 {
149 	s8 pwr;
150 	u8 ch;
151 
152 	pwr = pframe->u.hdr.attrib.phy_info.recv_signal_power;
153 	ch = pframe->u.hdr.attrib.phy_info.channel;
154 
155 	return rtw_acs_get_rsni(prm->psta->padapter, pwr, ch);
156 }
157 
rm_get_bcn_rsni(struct rm_obj * prm,struct wlan_network * pnetwork)158 u8 rm_get_bcn_rsni(struct rm_obj *prm, struct wlan_network *pnetwork)
159 {
160 	s8 pwr;
161 	u8 ch;
162 
163 	pwr = (u8)pnetwork->network.Rssi;
164 	ch = pnetwork->network.Configuration.DSConfig;
165 
166 	return rtw_acs_get_rsni(prm->psta->padapter, pwr, ch);
167 }
168 
169 /* output: pwr (unit dBm) */
rm_get_tx_power(PADAPTER adapter,enum rf_path path,enum MGN_RATE rate,s8 * pwr)170 int rm_get_tx_power(PADAPTER adapter, enum rf_path path, enum MGN_RATE rate, s8 *pwr)
171 {
172 	struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
173 	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
174 	int tx_num, band, bw, ch, n, rs;
175 	u8 base;
176 	s8 limt_offset = 127; /* max value of s8 */
177 	s8 rate_offset;
178 	s8 powr_offset;
179 	int rate_pos;
180 
181 
182 	band = hal_data->current_band_type;
183 	bw = hal_data->current_channel_bw;
184 	ch = hal_data->current_channel;
185 
186 	if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path))
187 		return -1;
188 
189 	if (HAL_IsLegalChannel(adapter, ch) == _FALSE) {
190 		RTW_INFO("Illegal channel!!\n");
191 		return -2;
192 	}
193 
194 	*pwr = phy_get_tx_power_final_absolute_value(adapter, path, rate, bw, ch);
195 
196 	return 0;
197 }
198 
rm_get_rx_sensitivity(PADAPTER adapter,enum channel_width bw,enum MGN_RATE rate,s8 * pwr)199 int rm_get_rx_sensitivity(PADAPTER adapter, enum channel_width bw, enum MGN_RATE rate, s8 *pwr)
200 {
201 	s8 rx_sensitivity = -110;
202 
203 	switch(rate) {
204 	case MGN_1M:
205 		rx_sensitivity= -101;
206 		break;
207 	case MGN_2M:
208 		rx_sensitivity= -98;
209 		break;
210 	case MGN_5_5M:
211 		rx_sensitivity= -92;
212 		break;
213 	case MGN_11M:
214 		rx_sensitivity= -89;
215 		break;
216 	case MGN_6M:
217 	case MGN_9M:
218 	case MGN_12M:
219 		rx_sensitivity = -92;
220 		break;
221 	case MGN_18M:
222 		rx_sensitivity = -90;
223 		break;
224 	case MGN_24M:
225 		rx_sensitivity = -88;
226 		break;
227 	case MGN_36M:
228 		rx_sensitivity = -84;
229 		break;
230 	case MGN_48M:
231 		rx_sensitivity = -79;
232 		break;
233 	case MGN_54M:
234 		rx_sensitivity = -78;
235 		break;
236 
237 	case MGN_MCS0:
238 	case MGN_MCS8:
239 	case MGN_MCS16:
240 	case MGN_MCS24:
241 	case MGN_VHT1SS_MCS0:
242 	case MGN_VHT2SS_MCS0:
243 	case MGN_VHT3SS_MCS0:
244 	case MGN_VHT4SS_MCS0:
245 		/* BW20 BPSK 1/2 */
246 		rx_sensitivity = -82;
247 		break;
248 
249 	case MGN_MCS1:
250 	case MGN_MCS9:
251 	case MGN_MCS17:
252 	case MGN_MCS25:
253 	case MGN_VHT1SS_MCS1:
254 	case MGN_VHT2SS_MCS1:
255 	case MGN_VHT3SS_MCS1:
256 	case MGN_VHT4SS_MCS1:
257 		/* BW20 QPSK 1/2 */
258 		rx_sensitivity = -79;
259 		break;
260 
261 	case MGN_MCS2:
262 	case MGN_MCS10:
263 	case MGN_MCS18:
264 	case MGN_MCS26:
265 	case MGN_VHT1SS_MCS2:
266 	case MGN_VHT2SS_MCS2:
267 	case MGN_VHT3SS_MCS2:
268 	case MGN_VHT4SS_MCS2:
269 		/* BW20 QPSK 3/4 */
270 		rx_sensitivity = -77;
271 		break;
272 
273 	case MGN_MCS3:
274 	case MGN_MCS11:
275 	case MGN_MCS19:
276 	case MGN_MCS27:
277 	case MGN_VHT1SS_MCS3:
278 	case MGN_VHT2SS_MCS3:
279 	case MGN_VHT3SS_MCS3:
280 	case MGN_VHT4SS_MCS3:
281 		/* BW20 16-QAM 1/2 */
282 		rx_sensitivity = -74;
283 		break;
284 
285 	case MGN_MCS4:
286 	case MGN_MCS12:
287 	case MGN_MCS20:
288 	case MGN_MCS28:
289 	case MGN_VHT1SS_MCS4:
290 	case MGN_VHT2SS_MCS4:
291 	case MGN_VHT3SS_MCS4:
292 	case MGN_VHT4SS_MCS4:
293 		/* BW20 16-QAM 3/4 */
294 		rx_sensitivity = -70;
295 		break;
296 
297 	case MGN_MCS5:
298 	case MGN_MCS13:
299 	case MGN_MCS21:
300 	case MGN_MCS29:
301 	case MGN_VHT1SS_MCS5:
302 	case MGN_VHT2SS_MCS5:
303 	case MGN_VHT3SS_MCS5:
304 	case MGN_VHT4SS_MCS5:
305 		/* BW20 64-QAM 2/3 */
306 		rx_sensitivity = -66;
307 		break;
308 
309 	case MGN_MCS6:
310 	case MGN_MCS14:
311 	case MGN_MCS22:
312 	case MGN_MCS30:
313 	case MGN_VHT1SS_MCS6:
314 	case MGN_VHT2SS_MCS6:
315 	case MGN_VHT3SS_MCS6:
316 	case MGN_VHT4SS_MCS6:
317 		/* BW20 64-QAM 3/4 */
318 		rx_sensitivity = -65;
319 		break;
320 
321 	case MGN_MCS7:
322 	case MGN_MCS15:
323 	case MGN_MCS23:
324 	case MGN_MCS31:
325 	case MGN_VHT1SS_MCS7:
326 	case MGN_VHT2SS_MCS7:
327 	case MGN_VHT3SS_MCS7:
328 	case MGN_VHT4SS_MCS7:
329 		/* BW20 64-QAM 5/6 */
330 		rx_sensitivity = -64;
331 		break;
332 
333 	case MGN_VHT1SS_MCS8:
334 	case MGN_VHT2SS_MCS8:
335 	case MGN_VHT3SS_MCS8:
336 	case MGN_VHT4SS_MCS8:
337 		/* BW20 256-QAM 3/4 */
338 		rx_sensitivity = -59;
339 		break;
340 
341 	case MGN_VHT1SS_MCS9:
342 	case MGN_VHT2SS_MCS9:
343 	case MGN_VHT3SS_MCS9:
344 	case MGN_VHT4SS_MCS9:
345 		/* BW20 256-QAM 5/6 */
346 		rx_sensitivity = -57;
347 		break;
348 
349 	default:
350 		return -1;
351 		break;
352 
353 	}
354 
355 	switch(bw) {
356 	case CHANNEL_WIDTH_20:
357 		break;
358 	case CHANNEL_WIDTH_40:
359 		rx_sensitivity -= 3;
360 		break;
361 	case CHANNEL_WIDTH_80:
362 		rx_sensitivity -= 6;
363 		break;
364 	case CHANNEL_WIDTH_160:
365 		rx_sensitivity -= 9;
366 		break;
367 	case CHANNEL_WIDTH_5:
368 	case CHANNEL_WIDTH_10:
369 	case CHANNEL_WIDTH_80_80:
370 	default:
371 		return -1;
372 		break;
373 	}
374 	*pwr = rx_sensitivity;
375 
376 	return 0;
377 }
378 
379 /* output: path_a max tx power in dBm */
rm_get_path_a_max_tx_power(_adapter * adapter,s8 * path_a)380 int rm_get_path_a_max_tx_power(_adapter *adapter, s8 *path_a)
381 {
382 	struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
383 	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
384 	int path, tx_num, band, bw, ch, n, rs;
385 	u8 rate_num;
386 	s8 max_pwr[RF_PATH_MAX], pwr;
387 
388 
389 	band = hal_data->current_band_type;
390 	bw = hal_data->current_channel_bw;
391 	ch = hal_data->current_channel;
392 
393 	for (path = 0; path < RF_PATH_MAX; path++) {
394 		if (!HAL_SPEC_CHK_RF_PATH(hal_spec, band, path))
395 			break;
396 
397 		max_pwr[path] = -127; /* min value of s8 */
398 #if (RM_MORE_DBG_MSG)
399 		RTW_INFO("RM: [%s][%c]\n", band_str(band), rf_path_char(path));
400 #endif
401 		for (rs = 0; rs < RATE_SECTION_NUM; rs++) {
402 			tx_num = rate_section_to_tx_num(rs);
403 
404 			if (tx_num >= hal_spec->tx_nss_num)
405 				continue;
406 
407 			if (band == BAND_ON_5G && IS_CCK_RATE_SECTION(rs))
408 				continue;
409 
410 			if (IS_VHT_RATE_SECTION(rs) && !IS_HARDWARE_TYPE_JAGUAR_ALL(adapter))
411 				continue;
412 
413 			rate_num = rate_section_rate_num(rs);
414 
415 			/* get power by rate in db */
416 			for (n = rate_num - 1; n >= 0; n--) {
417 				pwr = phy_get_tx_power_final_absolute_value(adapter, path, rates_by_sections[rs].rates[n], bw, ch);
418 				max_pwr[path] = MAX(max_pwr[path], pwr);
419 #if (RM_MORE_DBG_MSG)
420 				RTW_INFO("RM: %9s = %2d\n",
421 					MGN_RATE_STR(rates_by_sections[rs].rates[n]), pwr);
422 #endif
423 			}
424 		}
425 	}
426 #if (RM_MORE_DBG_MSG)
427 	RTW_INFO("RM: path_a max_pwr=%ddBm\n", max_pwr[0]);
428 #endif
429 	*path_a = max_pwr[0];
430 	return 0;
431 }
432 
rm_gen_dialog_token(_adapter * padapter)433 u8 rm_gen_dialog_token(_adapter *padapter)
434 {
435 	struct rm_priv *prmpriv = &(padapter->rmpriv);
436 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
437 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
438 
439 	do {
440 		pmlmeinfo->dialogToken++;
441 	} while (pmlmeinfo->dialogToken == 0);
442 
443 	return pmlmeinfo->dialogToken;
444 }
445 
rm_gen_meas_token(_adapter * padapter)446 u8 rm_gen_meas_token(_adapter *padapter)
447 {
448 	struct rm_priv *prmpriv = &(padapter->rmpriv);
449 
450 	do {
451 		prmpriv->meas_token++;
452 	} while (prmpriv->meas_token == 0);
453 
454 	return prmpriv->meas_token;
455 }
456 
rm_gen_rmid(_adapter * padapter,struct rm_obj * prm,u8 role)457 u32 rm_gen_rmid(_adapter *padapter, struct rm_obj *prm, u8 role)
458 {
459 	u32 rmid;
460 
461 	if (prm->psta == NULL)
462 		goto err;
463 
464 	if (prm->q.diag_token == 0)
465 		goto err;
466 
467 	rmid = prm->psta->cmn.aid << 16
468 		| prm->q.diag_token << 8
469 		| role;
470 
471 	return rmid;
472 err:
473 	RTW_ERR("RM: unable to gen rmid\n");
474 	return 0;
475 }
476 
477 #endif /* CONFIG_RTW_80211K */
478