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