1 /******************************************************************************
2 *
3 * Copyright(c) 2015 - 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 #ifdef CONFIG_MCC_MODE
16 #define _HAL_MCC_C_
17
18 #include <drv_types.h> /* PADAPTER */
19 #include <rtw_mcc.h> /* mcc structure */
20 #include <hal_data.h> /* HAL_DATA */
21 #include <rtw_pwrctrl.h> /* power control */
22
23 /* use for AP/GO + STA/GC case */
24 #define MCC_DURATION_IDX 0 /* druration for station side */
25 #define MCC_TSF_SYNC_OFFSET_IDX 1
26 #define MCC_START_TIME_OFFSET_IDX 2
27 #define MCC_INTERVAL_IDX 3
28 #define MCC_GUARD_OFFSET0_IDX 4
29 #define MCC_GUARD_OFFSET1_IDX 5
30 #define MCC_STOP_THRESHOLD 6
31 #define TU 1024 /* 1 TU equals 1024 microseconds */
32 /* druration, TSF sync offset, start time offset, interval (unit:TU (1024 microseconds))*/
33 u8 mcc_switch_channel_policy_table[][7]={
34 {20, 50, 40, 100, 0, 0, 30},
35 {80, 50, 10, 100, 0, 0, 30},
36 {36, 50, 32, 100, 0, 0, 30},
37 {30, 50, 35, 100, 0, 0, 30},
38 };
39
40 const int mcc_max_policy_num = sizeof(mcc_switch_channel_policy_table) /sizeof(u8) /7;
41
dump_iqk_val_table(PADAPTER padapter)42 static void dump_iqk_val_table(PADAPTER padapter)
43 {
44 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
45 struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
46 struct hal_iqk_reg_backup *iqk_reg_backup = pHalData->iqk_reg_backup;
47 u8 total_rf_path = hal_spec->rf_reg_path_num;
48 u8 rf_path_idx = 0;
49 u8 backup_chan_idx = 0;
50 u8 backup_reg_idx = 0;
51
52 #ifdef CONFIG_MCC_MODE_V2
53 #else
54
55 RTW_INFO("=============dump IQK backup table================\n");
56 for (backup_chan_idx = 0; backup_chan_idx < MAX_IQK_INFO_BACKUP_CHNL_NUM; backup_chan_idx++) {
57 for (rf_path_idx = 0; rf_path_idx < total_rf_path; rf_path_idx++) {
58 for(backup_reg_idx = 0; backup_reg_idx < MAX_IQK_INFO_BACKUP_REG_NUM; backup_reg_idx++) {
59 RTW_INFO("ch:%d. bw:%d. rf path:%d. reg[%d] = 0x%02x \n"
60 , iqk_reg_backup[backup_chan_idx].central_chnl
61 , iqk_reg_backup[backup_chan_idx].bw_mode
62 , rf_path_idx
63 , backup_reg_idx
64 , iqk_reg_backup[backup_chan_idx].reg_backup[rf_path_idx][backup_reg_idx]
65 );
66 }
67 }
68 }
69 RTW_INFO("=============================================\n");
70
71 #endif
72 }
73
rtw_hal_mcc_build_p2p_noa_attr(PADAPTER padapter,u8 * ie,u32 * ie_len)74 static void rtw_hal_mcc_build_p2p_noa_attr(PADAPTER padapter, u8 *ie, u32 *ie_len)
75 {
76 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
77 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
78 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
79 u8 p2p_noa_attr_ie[MAX_P2P_IE_LEN] = {0x00};
80 u32 p2p_noa_attr_len = 0;
81 u8 noa_desc_num = 1;
82 u8 opp_ps = 0; /* Disable OppPS */
83 u8 noa_count = 255;
84 u32 noa_duration;
85 u32 noa_interval;
86 u8 noa_index = 0;
87 u8 mcc_policy_idx = 0;
88
89 mcc_policy_idx = pmccobjpriv->policy_index;
90 noa_duration = mcc_switch_channel_policy_table[mcc_policy_idx][MCC_DURATION_IDX] * TU;
91 noa_interval = mcc_switch_channel_policy_table[mcc_policy_idx][MCC_INTERVAL_IDX] * TU;
92
93 /* P2P OUI(4 bytes) */
94 _rtw_memcpy(p2p_noa_attr_ie, P2P_OUI, 4);
95 p2p_noa_attr_len = p2p_noa_attr_len + 4;
96
97 /* attrute ID(1 byte) */
98 p2p_noa_attr_ie[p2p_noa_attr_len] = P2P_ATTR_NOA;
99 p2p_noa_attr_len = p2p_noa_attr_len + 1;
100
101 /* attrute length(2 bytes) length = noa_desc_num*13 + 2 */
102 RTW_PUT_LE16(p2p_noa_attr_ie + p2p_noa_attr_len, (noa_desc_num * 13 + 2));
103 p2p_noa_attr_len = p2p_noa_attr_len + 2;
104
105 /* Index (1 byte) */
106 p2p_noa_attr_ie[p2p_noa_attr_len] = noa_index;
107 p2p_noa_attr_len = p2p_noa_attr_len + 1;
108
109 /* CTWindow and OppPS Parameters (1 byte) */
110 p2p_noa_attr_ie[p2p_noa_attr_len] = opp_ps;
111 p2p_noa_attr_len = p2p_noa_attr_len+ 1;
112
113 /* NoA Count (1 byte) */
114 p2p_noa_attr_ie[p2p_noa_attr_len] = noa_count;
115 p2p_noa_attr_len = p2p_noa_attr_len + 1;
116
117 /* NoA Duration (4 bytes) unit: microseconds */
118 RTW_PUT_LE32(p2p_noa_attr_ie + p2p_noa_attr_len, noa_duration);
119 p2p_noa_attr_len = p2p_noa_attr_len + 4;
120
121 /* NoA Interval (4 bytes) unit: microseconds */
122 RTW_PUT_LE32(p2p_noa_attr_ie + p2p_noa_attr_len, noa_interval);
123 p2p_noa_attr_len = p2p_noa_attr_len + 4;
124
125 /* NoA Start Time (4 bytes) unit: microseconds */
126 RTW_PUT_LE32(p2p_noa_attr_ie + p2p_noa_attr_len, pmccadapriv->noa_start_time);
127 if (0)
128 RTW_INFO("indxe:%d, start_time=0x%02x:0x%02x:0x%02x:0x%02x\n"
129 , noa_index
130 , p2p_noa_attr_ie[p2p_noa_attr_len]
131 , p2p_noa_attr_ie[p2p_noa_attr_len + 1]
132 , p2p_noa_attr_ie[p2p_noa_attr_len + 2]
133 , p2p_noa_attr_ie[p2p_noa_attr_len + 3]);
134
135 p2p_noa_attr_len = p2p_noa_attr_len + 4;
136 rtw_set_ie(ie, _VENDOR_SPECIFIC_IE_, p2p_noa_attr_len, (u8 *)p2p_noa_attr_ie, ie_len);
137 }
138
139
140 /**
141 * rtw_hal_mcc_update_go_p2p_ie - update go p2p ie(add NoA attribute)
142 * @padapter: the adapter to be update go p2p ie
143 */
rtw_hal_mcc_update_go_p2p_ie(PADAPTER padapter)144 static void rtw_hal_mcc_update_go_p2p_ie(PADAPTER padapter)
145 {
146 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
147 struct mcc_obj_priv *mccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
148 u8 *pos = NULL;
149
150
151 /* no noa attribute, build it */
152 if (pmccadapriv->p2p_go_noa_ie_len == 0)
153 rtw_hal_mcc_build_p2p_noa_attr(padapter, pmccadapriv->p2p_go_noa_ie, &pmccadapriv->p2p_go_noa_ie_len);
154 else {
155 /* has noa attribut, modify it */
156 u32 noa_duration = 0;
157
158 /* update index */
159 pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len - 15;
160 /* 0~255 */
161 (*pos) = ((*pos) + 1) % 256;
162 if (0)
163 RTW_INFO("indxe:%d\n", (*pos));
164
165
166 /* update duration */
167 noa_duration = mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_DURATION_IDX] * TU;
168 pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len - 12;
169 RTW_PUT_LE32(pos, noa_duration);
170
171 /* update start time */
172 pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len - 4;
173 RTW_PUT_LE32(pos, pmccadapriv->noa_start_time);
174 if (0)
175 RTW_INFO("start_time=0x%02x:0x%02x:0x%02x:0x%02x\n"
176 , ((u8*)(pos))[0]
177 , ((u8*)(pos))[1]
178 , ((u8*)(pos))[2]
179 , ((u8*)(pos))[3]);
180
181 }
182
183 if (0) {
184 RTW_INFO("p2p_go_noa_ie_len:%d\n", pmccadapriv->p2p_go_noa_ie_len);
185 RTW_INFO_DUMP("\n", pmccadapriv->p2p_go_noa_ie, pmccadapriv->p2p_go_noa_ie_len);
186 }
187 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, P2P_OUI, _TRUE, 0);
188 }
189
190 /**
191 * rtw_hal_mcc_remove_go_p2p_ie - remove go p2p ie(add NoA attribute)
192 * @padapter: the adapter to be update go p2p ie
193 */
rtw_hal_mcc_remove_go_p2p_ie(PADAPTER padapter)194 static void rtw_hal_mcc_remove_go_p2p_ie(PADAPTER padapter)
195 {
196 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
197 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
198
199 /* chech has noa ie or not */
200 if (pmccadapriv->p2p_go_noa_ie_len == 0)
201 return;
202
203 pmccadapriv->p2p_go_noa_ie_len = 0;
204 update_beacon(padapter, _VENDOR_SPECIFIC_IE_, P2P_OUI, _TRUE, 0);
205 }
206
207 /* restore IQK value for all interface */
rtw_hal_mcc_restore_iqk_val(PADAPTER padapter)208 void rtw_hal_mcc_restore_iqk_val(PADAPTER padapter)
209 {
210 u8 take_care_iqk = _FALSE;
211 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
212 _adapter *iface = NULL;
213 struct mcc_adapter_priv *mccadapriv = NULL;
214 u8 i = 0;
215
216 rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);
217 if (take_care_iqk == _TRUE && MCC_EN(padapter)) {
218 for (i = 0; i < dvobj->iface_nums; i++) {
219 iface = dvobj->padapters[i];
220 if (iface == NULL)
221 continue;
222
223 mccadapriv = &iface->mcc_adapterpriv;
224 if (mccadapriv->role == MCC_ROLE_MAX)
225 continue;
226
227 rtw_hal_ch_sw_iqk_info_restore(iface, CH_SW_USE_CASE_MCC);
228 }
229 }
230
231 if (0)
232 dump_iqk_val_table(padapter);
233 }
234
rtw_hal_check_mcc_status(PADAPTER padapter,u8 mcc_status)235 u8 rtw_hal_check_mcc_status(PADAPTER padapter, u8 mcc_status)
236 {
237 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
238
239 if (pmccobjpriv->mcc_status & (mcc_status))
240 return _TRUE;
241 else
242 return _FALSE;
243 }
244
rtw_hal_set_mcc_status(PADAPTER padapter,u8 mcc_status)245 void rtw_hal_set_mcc_status(PADAPTER padapter, u8 mcc_status)
246 {
247 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
248
249 pmccobjpriv->mcc_status |= (mcc_status);
250 }
251
rtw_hal_clear_mcc_status(PADAPTER padapter,u8 mcc_status)252 void rtw_hal_clear_mcc_status(PADAPTER padapter, u8 mcc_status)
253 {
254 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
255
256 pmccobjpriv->mcc_status &= (~mcc_status);
257 }
258
rtw_hal_mcc_update_policy_table(PADAPTER adapter)259 static void rtw_hal_mcc_update_policy_table(PADAPTER adapter)
260 {
261 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
262 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
263 u8 mcc_duration = mccobjpriv->duration;
264 s8 mcc_policy_idx = mccobjpriv->policy_index;
265 u8 interval = mcc_switch_channel_policy_table[mcc_policy_idx][MCC_INTERVAL_IDX];
266 u8 new_mcc_duration_time = 0;
267 u8 new_starttime_offset = 0;
268
269 /* convert % to ms */
270 new_mcc_duration_time = mcc_duration * interval / 100;
271
272 /* start time offset = (interval - duration time)/2 */
273 new_starttime_offset = (interval - new_mcc_duration_time) >> 1;
274
275 /* update modified parameters */
276 mcc_switch_channel_policy_table[mcc_policy_idx][MCC_DURATION_IDX]
277 = new_mcc_duration_time;
278
279 mcc_switch_channel_policy_table[mcc_policy_idx][MCC_START_TIME_OFFSET_IDX]
280 = new_starttime_offset;
281
282
283 }
284
rtw_hal_config_mcc_switch_channel_setting(PADAPTER padapter)285 static void rtw_hal_config_mcc_switch_channel_setting(PADAPTER padapter)
286 {
287 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
288 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
289 struct registry_priv *registry_par = &padapter->registrypriv;
290 u8 mcc_duration = 0;
291 s8 mcc_policy_idx = 0;
292
293 mcc_policy_idx = registry_par->rtw_mcc_policy_table_idx;
294 mcc_duration = mccobjpriv->duration;
295
296 if (mcc_policy_idx < 0 || mcc_policy_idx >= mcc_max_policy_num) {
297 mccobjpriv->policy_index = 0;
298 RTW_INFO("[MCC] can't find table(%d), use default policy(%d)\n",
299 mcc_policy_idx, mccobjpriv->policy_index);
300 } else
301 mccobjpriv->policy_index = mcc_policy_idx;
302
303 /* convert % to time */
304 if (mcc_duration != 0)
305 rtw_hal_mcc_update_policy_table(padapter);
306
307 RTW_INFO("[MCC] policy(%d): %d,%d,%d,%d,%d,%d\n"
308 , mccobjpriv->policy_index
309 , mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_DURATION_IDX]
310 , mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_TSF_SYNC_OFFSET_IDX]
311 , mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_START_TIME_OFFSET_IDX]
312 , mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_INTERVAL_IDX]
313 , mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_GUARD_OFFSET0_IDX]
314 , mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_GUARD_OFFSET1_IDX]);
315
316 }
317
rtw_hal_mcc_assign_tx_threshold(PADAPTER padapter)318 static void rtw_hal_mcc_assign_tx_threshold(PADAPTER padapter)
319 {
320 struct registry_priv *preg = &padapter->registrypriv;
321 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
322 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
323
324 switch (pmccadapriv->role) {
325 case MCC_ROLE_STA:
326 case MCC_ROLE_GC:
327 switch (pmlmeext->cur_bwmode) {
328 case CHANNEL_WIDTH_20:
329 /*
330 * target tx byte(bytes) = target tx tp(Mbits/sec) * 1024 * 1024 / 8 * (duration(ms) / 1024)
331 * = target tx tp(Mbits/sec) * 128 * duration(ms)
332 * note:
333 * target tx tp(Mbits/sec) * 1024 * 1024 / 8 ==> Mbits to bytes
334 * duration(ms) / 1024 ==> msec to sec
335 */
336 pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_sta_bw20_target_tx_tp * 128 * pmccadapriv->mcc_duration;
337 break;
338 case CHANNEL_WIDTH_40:
339 pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_sta_bw40_target_tx_tp * 128 * pmccadapriv->mcc_duration;
340 break;
341 case CHANNEL_WIDTH_80:
342 pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_sta_bw80_target_tx_tp * 128 * pmccadapriv->mcc_duration;
343 break;
344 case CHANNEL_WIDTH_160:
345 case CHANNEL_WIDTH_80_80:
346 RTW_INFO(FUNC_ADPT_FMT": not support bwmode = %d\n"
347 , FUNC_ADPT_ARG(padapter), pmlmeext->cur_bwmode);
348 break;
349 }
350 break;
351 case MCC_ROLE_AP:
352 case MCC_ROLE_GO:
353 switch (pmlmeext->cur_bwmode) {
354 case CHANNEL_WIDTH_20:
355 pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_ap_bw20_target_tx_tp * 128 * pmccadapriv->mcc_duration;
356 break;
357 case CHANNEL_WIDTH_40:
358 pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_ap_bw40_target_tx_tp * 128 * pmccadapriv->mcc_duration;
359 break;
360 case CHANNEL_WIDTH_80:
361 pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_ap_bw80_target_tx_tp * 128 * pmccadapriv->mcc_duration;
362 break;
363 case CHANNEL_WIDTH_160:
364 case CHANNEL_WIDTH_80_80:
365 RTW_INFO(FUNC_ADPT_FMT": not support bwmode = %d\n"
366 , FUNC_ADPT_ARG(padapter), pmlmeext->cur_bwmode);
367 break;
368 }
369 break;
370 default:
371 RTW_INFO(FUNC_ADPT_FMT": unknown role = %d\n"
372 , FUNC_ADPT_ARG(padapter), pmccadapriv->role);
373 break;
374 }
375 }
376
377 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
mcc_cfg_phdym_rf_ch(_adapter * adapter)378 static void mcc_cfg_phdym_rf_ch (_adapter *adapter)
379 {
380 struct mcc_adapter_priv *mccadapriv = &adapter->mcc_adapterpriv;
381 struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
382 HAL_DATA_TYPE *hal = GET_HAL_DATA(adapter);
383 struct dm_struct *dm = &hal->odmpriv;
384 struct _phydm_mcc_dm_ *mcc_dm = &dm->mcc_dm;
385 u8 order = 0;
386
387 set_channel_bwmode(adapter, mlmeext->cur_channel, mlmeext->cur_ch_offset, mlmeext->cur_bwmode);
388 order = mccadapriv->order;
389 mcc_dm->mcc_rf_ch[order] = phy_query_rf_reg(adapter, RF_PATH_A, 0x18, 0x03ff);
390 }
391
mcc_cfg_phdym_update_macid(_adapter * adapter,u8 add,u8 mac_id)392 static void mcc_cfg_phdym_update_macid (_adapter *adapter, u8 add, u8 mac_id)
393 {
394 struct mcc_adapter_priv *mccadapriv = &adapter->mcc_adapterpriv;
395 struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
396 HAL_DATA_TYPE *hal = GET_HAL_DATA(adapter);
397 struct dm_struct *dm = &hal->odmpriv;
398 struct _phydm_mcc_dm_ *mcc_dm = &dm->mcc_dm;
399 u8 order = 0, i = 0;
400
401 order = mccadapriv->order;
402 if (add) {
403 for (i = 0; i < NUM_STA; i++) {
404 if (mcc_dm->sta_macid[order][i] == 0xff) {
405 mcc_dm->sta_macid[order][i] = mac_id;
406 break;
407 }
408 }
409 } else {
410 for (i = 0; i < NUM_STA; i++) {
411 if (mcc_dm->sta_macid[order][i] == mac_id) {
412 mcc_dm->sta_macid[order][i] = 0xff;
413 break;
414 }
415 }
416 }
417
418
419 }
420
mcc_cfg_phdym_start(_adapter * adapter,u8 start)421 static void mcc_cfg_phdym_start(_adapter *adapter, u8 start)
422 {
423 struct dvobj_priv *dvobj;
424 struct mcc_obj_priv *mccobjpriv;
425 HAL_DATA_TYPE *hal;
426 struct dm_struct *dm;
427 struct _phydm_mcc_dm_ *mcc_dm;
428 u8 rfk_forbidden = _TRUE;
429 u8 i = 0, j = 0;
430
431 dvobj = adapter_to_dvobj(adapter);
432 mccobjpriv = adapter_to_mccobjpriv(adapter);
433 hal = GET_HAL_DATA(adapter);
434 dm = &hal->odmpriv;
435 mcc_dm = &dm->mcc_dm;
436
437 if (start) {
438 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
439 mcc_dm->mcc_status = mccobjpriv->mcc_phydm_offload;
440 #endif
441
442 rfk_forbidden = _TRUE;
443 halrf_cmn_info_set(dm, HALRF_CMNINFO_RFK_FORBIDDEN, rfk_forbidden);
444 } else {
445 rfk_forbidden = _FALSE;
446 halrf_cmn_info_set(dm, HALRF_CMNINFO_RFK_FORBIDDEN, rfk_forbidden);
447
448 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
449 for(i = 0; i < MAX_MCC_NUM; i ++) {
450 for(j = 0; j < NUM_STA; j ++) {
451 if (mcc_dm->sta_macid[i][j] != 0xff)
452 /* clear all used value for mcc stop */
453 /* do nothing for mcc start due to phydm will init to 0xff */
454 mcc_dm->sta_macid[i][j] = 0xff;
455 }
456 mcc_dm->mcc_rf_ch[i] = 0xff;
457 }
458 mcc_dm->mcc_status = 0;
459 #endif
460 }
461 }
462
mcc_cfg_phdym_dump(_adapter * adapter,void * sel)463 static void mcc_cfg_phdym_dump(_adapter *adapter, void *sel)
464 {
465 HAL_DATA_TYPE *hal;
466 struct dm_struct *dm;
467 struct _phydm_mcc_dm_ *mcc_dm;
468 u8 rfk_forbidden = _TRUE;
469 u8 i = 0, j = 0;
470
471
472 hal = GET_HAL_DATA(adapter);
473 dm = &hal->odmpriv;
474 mcc_dm = &dm->mcc_dm;
475
476 rfk_forbidden = halrf_cmn_info_get(dm, HALRF_CMNINFO_RFK_FORBIDDEN);
477 RTW_PRINT_SEL(sel, "dump mcc dm info\n");
478 RTW_PRINT_SEL(sel, "mcc_status=%d\n", mcc_dm->mcc_status);
479 RTW_PRINT_SEL(sel, "rfk_forbidden=%d\n", rfk_forbidden);
480 for(i = 0; i < MAX_MCC_NUM; i ++) {
481
482 if (mcc_dm->mcc_rf_ch[i] != 0xff)
483 RTW_PRINT_SEL(sel, "mcc_dm->mcc_rf_ch[%d] = 0x%02x\n", i, mcc_dm->mcc_rf_ch[i]);
484
485 for(j = 0; j < NUM_STA; j ++) {
486 if (mcc_dm->sta_macid[i][j] != 0xff)
487 RTW_PRINT_SEL(sel, "mcc_dm->sta_macid[%d][%d] = %d\n", i, j, mcc_dm->sta_macid[i][j]);
488 }
489 }
490 }
491
mcc_cfg_phdym_offload(_adapter * adapter,u8 enable)492 static void mcc_cfg_phdym_offload(_adapter *adapter, u8 enable)
493 {
494 struct mcc_obj_priv *mccobjpriv = adapter_to_mccobjpriv(adapter);
495 _adapter *iface = NULL;
496 struct mcc_adapter_priv *mccadapriv = NULL;
497 HAL_DATA_TYPE *hal = NULL;
498 struct dm_struct *dm = NULL;
499 struct _phydm_mcc_dm_ *mcc_dm = NULL;
500 struct sta_priv *stapriv = NULL;
501 struct sta_info *sta = NULL;
502 struct wlan_network *cur_network = NULL;
503 _irqL irqL;
504 _list *head = NULL, *list = NULL;
505 u8 i = 0;
506
507
508 hal = GET_HAL_DATA(adapter);
509 dm = &hal->odmpriv;
510 mcc_dm = &dm->mcc_dm;
511
512 /* due to phydm will rst related date, driver must set related data */
513 if (enable) {
514 for (i = 0; i < MAX_MCC_NUM; i++) {
515 iface = mccobjpriv->iface[i];
516 if (!iface)
517 continue;
518 stapriv = &iface->stapriv;
519 mccadapriv = &iface->mcc_adapterpriv;
520 switch (mccadapriv->role) {
521 case MCC_ROLE_STA:
522 case MCC_ROLE_GC:
523 cur_network = &iface->mlmepriv.cur_network;
524 sta = rtw_get_stainfo(stapriv, cur_network->network.MacAddress);
525 if (sta)
526 mcc_cfg_phdym_update_macid(iface, _TRUE, sta->cmn.mac_id);
527 break;
528 case MCC_ROLE_AP:
529 case MCC_ROLE_GO:
530 _enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
531
532 head = &stapriv->asoc_list;
533 list = get_next(head);
534
535 while ((rtw_end_of_queue_search(head, list)) == _FALSE) {
536 sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
537 list = get_next(list);
538 mcc_cfg_phdym_update_macid(iface, _TRUE, sta->cmn.mac_id);
539 }
540
541 _exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
542 break;
543 default:
544 RTW_INFO("Unknown role\n");
545 rtw_warn_on(1);
546 break;
547 }
548
549 }
550 }
551
552 mcc_dm->mcc_status = enable;
553 }
554
rtw_hal_mcc_cfg_phydm(_adapter * adapter,enum mcc_cfg_phydm_ops ops,void * data)555 static void rtw_hal_mcc_cfg_phydm (_adapter *adapter, enum mcc_cfg_phydm_ops ops, void *data)
556 {
557 switch (ops) {
558 case MCC_CFG_PHYDM_OFFLOAD:
559 mcc_cfg_phdym_offload(adapter, *(u8 *)data);
560 break;
561 case MCC_CFG_PHYDM_RF_CH:
562 mcc_cfg_phdym_rf_ch(adapter);
563 break;
564 case MCC_CFG_PHYDM_ADD_CLIENT:
565 mcc_cfg_phdym_update_macid(adapter, _TRUE, *(u8 *)data);
566 break;
567 case MCC_CFG_PHYDM_REMOVE_CLIENT:
568 mcc_cfg_phdym_update_macid(adapter, _FALSE, *(u8 *)data);
569 break;
570 case MCC_CFG_PHYDM_START:
571 mcc_cfg_phdym_start(adapter, _TRUE);
572 break;
573 case MCC_CFG_PHYDM_STOP:
574 mcc_cfg_phdym_start(adapter, _FALSE);
575 break;
576 case MCC_CFG_PHYDM_DUMP:
577 mcc_cfg_phdym_dump(adapter, data);
578 break;
579 case MCC_CFG_PHYDM_MAX:
580 default:
581 RTW_ERR("[MCC] rtw_hal_mcc_cfg_phydm ops error (%d)\n", ops);
582 break;
583
584 }
585 }
586 #endif
587
rtw_hal_config_mcc_role_setting(PADAPTER padapter,u8 order)588 static void rtw_hal_config_mcc_role_setting(PADAPTER padapter, u8 order)
589 {
590 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
591 struct mcc_obj_priv *pmccobjpriv = &(pdvobjpriv->mcc_objpriv);
592 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
593 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
594 struct wlan_network *cur_network = &(pmlmepriv->cur_network);
595 struct sta_priv *pstapriv = &padapter->stapriv;
596 struct sta_info *psta = NULL;
597 struct registry_priv *preg = &padapter->registrypriv;
598 _irqL irqL;
599 _list *phead =NULL, *plist = NULL;
600 u8 policy_index = 0;
601 u8 mcc_duration = 0;
602 u8 mcc_interval = 0;
603 u8 starting_ap_num = DEV_AP_STARTING_NUM(pdvobjpriv);
604 u8 ap_num = DEV_AP_NUM(pdvobjpriv);
605
606 policy_index = pmccobjpriv->policy_index;
607 mcc_duration = mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_DURATION_IDX]
608 - mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_GUARD_OFFSET0_IDX]
609 - mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_GUARD_OFFSET1_IDX];
610 mcc_interval = mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_INTERVAL_IDX];
611
612 if (starting_ap_num == 0 && ap_num == 0) {
613 pmccadapriv->order = order;
614
615 if (pmccadapriv->order == 0) {
616 /* setting is smiliar to GO/AP */
617 /* pmccadapriv->mcc_duration = mcc_interval - mcc_duration;*/
618 pmccadapriv->mgmt_queue_macid = MCC_ROLE_SOFTAP_GO_MGMT_QUEUE_MACID;
619 } else if (pmccadapriv->order == 1) {
620 /* pmccadapriv->mcc_duration = mcc_duration; */
621 pmccadapriv->mgmt_queue_macid = MCC_ROLE_STA_GC_MGMT_QUEUE_MACID;
622 } else {
623 RTW_INFO("[MCC] not support >= 3 interface\n");
624 rtw_warn_on(1);
625 }
626
627 rtw_hal_mcc_assign_tx_threshold(padapter);
628
629 psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
630 if (psta) {
631 /* combine AP/GO macid and mgmt queue macid to bitmap */
632 pmccadapriv->mcc_macid_bitmap = BIT(psta->cmn.mac_id) | BIT(pmccadapriv->mgmt_queue_macid);
633 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
634 rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_ADD_CLIENT, &psta->cmn.mac_id);
635 #endif
636 } else {
637 RTW_INFO(FUNC_ADPT_FMT":AP/GO station info is NULL\n", FUNC_ADPT_ARG(padapter));
638 rtw_warn_on(1);
639 }
640 } else {
641 /* GO/AP is 1nd order GC/STA is 2nd order */
642 switch (pmccadapriv->role) {
643 case MCC_ROLE_STA:
644 case MCC_ROLE_GC:
645 pmccadapriv->order = 1;
646 pmccadapriv->mcc_duration = mcc_duration;
647
648 rtw_hal_mcc_assign_tx_threshold(padapter);
649 /* assign used mac to avoid affecting RA */
650 pmccadapriv->mgmt_queue_macid = MCC_ROLE_STA_GC_MGMT_QUEUE_MACID;
651
652 psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
653 if (psta) {
654 /* combine AP/GO macid and mgmt queue macid to bitmap */
655 pmccadapriv->mcc_macid_bitmap = BIT(psta->cmn.mac_id) | BIT(pmccadapriv->mgmt_queue_macid);
656 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
657 rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_ADD_CLIENT, &psta->cmn.mac_id);
658 #endif
659 } else {
660 RTW_INFO(FUNC_ADPT_FMT":AP/GO station info is NULL\n", FUNC_ADPT_ARG(padapter));
661 rtw_warn_on(1);
662 }
663 break;
664 case MCC_ROLE_AP:
665 case MCC_ROLE_GO:
666 pmccadapriv->order = 0;
667 /* total druation value equals interval */
668 pmccadapriv->mcc_duration = mcc_interval - mcc_duration;
669 pmccadapriv->p2p_go_noa_ie_len = 0; /* not NoA attribute at init time */
670
671 rtw_hal_mcc_assign_tx_threshold(padapter);
672
673 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
674
675 phead = &pstapriv->asoc_list;
676 plist = get_next(phead);
677 pmccadapriv->mcc_macid_bitmap = 0;
678
679 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
680 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
681 plist = get_next(plist);
682 pmccadapriv->mcc_macid_bitmap |= BIT(psta->cmn.mac_id);
683 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
684 rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_ADD_CLIENT, &psta->cmn.mac_id);
685 #endif
686 }
687
688 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
689
690 psta = rtw_get_bcmc_stainfo(padapter);
691
692 if (psta != NULL)
693 pmccadapriv->mgmt_queue_macid = psta->cmn.mac_id;
694 else {
695 pmccadapriv->mgmt_queue_macid = MCC_ROLE_SOFTAP_GO_MGMT_QUEUE_MACID;
696 RTW_INFO(FUNC_ADPT_FMT":bcmc station is NULL, use macid %d\n"
697 , FUNC_ADPT_ARG(padapter), pmccadapriv->mgmt_queue_macid);
698 }
699
700 /* combine client macid and mgmt queue macid to bitmap */
701 pmccadapriv->mcc_macid_bitmap |= BIT(pmccadapriv->mgmt_queue_macid);
702 break;
703 default:
704 RTW_INFO("Unknown role\n");
705 rtw_warn_on(1);
706 break;
707 }
708
709 }
710
711 /* setting Null data parameters */
712 if (pmccadapriv->role == MCC_ROLE_STA) {
713 pmccadapriv->null_early = 3;
714 pmccadapriv->null_rty_num= 5;
715 } else if (pmccadapriv->role == MCC_ROLE_GC) {
716 pmccadapriv->null_early = 2;
717 pmccadapriv->null_rty_num= 5;
718 } else {
719 pmccadapriv->null_early = 0;
720 pmccadapriv->null_rty_num= 0;
721 }
722
723 RTW_INFO("********* "FUNC_ADPT_FMT" *********\n", FUNC_ADPT_ARG(padapter));
724 RTW_INFO("order:%d\n", pmccadapriv->order);
725 RTW_INFO("role:%d\n", pmccadapriv->role);
726 RTW_INFO("mcc duration:%d\n", pmccadapriv->mcc_duration);
727 RTW_INFO("null_early:%d\n", pmccadapriv->null_early);
728 RTW_INFO("null_rty_num:%d\n", pmccadapriv->null_rty_num);
729 RTW_INFO("mgmt queue macid:%d\n", pmccadapriv->mgmt_queue_macid);
730 RTW_INFO("bitmap:0x%02x\n", pmccadapriv->mcc_macid_bitmap);
731 RTW_INFO("target tx bytes:%d\n", pmccadapriv->mcc_target_tx_bytes_to_port);
732 RTW_INFO("**********************************\n");
733
734 pmccobjpriv->iface[pmccadapriv->order] = padapter;
735 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
736 rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_RF_CH, NULL);
737 #endif
738
739 }
740
rtw_hal_mcc_rqt_tsf(PADAPTER padapter,u64 * out_tsf)741 static void rtw_hal_mcc_rqt_tsf(PADAPTER padapter, u64 *out_tsf)
742 {
743 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
744 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
745 PADAPTER order0_iface = NULL;
746 PADAPTER order1_iface = NULL;
747 struct submit_ctx *tsf_req_sctx = NULL;
748 enum _hw_port tsfx = MAX_HW_PORT;
749 enum _hw_port tsfy = MAX_HW_PORT;
750 u8 cmd[H2C_MCC_RQT_TSF_LEN] = {0};
751
752 _enter_critical_mutex(&mccobjpriv->mcc_tsf_req_mutex, NULL);
753
754 order0_iface = mccobjpriv->iface[0];
755 order1_iface = mccobjpriv->iface[1];
756
757 tsf_req_sctx = &mccobjpriv->mcc_tsf_req_sctx;
758 rtw_sctx_init(tsf_req_sctx, MCC_EXPIRE_TIME);
759 mccobjpriv->mcc_tsf_req_sctx_order = 0;
760 tsfx = rtw_hal_get_port(order0_iface);
761 tsfy = rtw_hal_get_port(order1_iface);
762
763 SET_H2CCMD_MCC_RQT_TSFX(cmd, tsfx);
764 SET_H2CCMD_MCC_RQT_TSFY(cmd, tsfy);
765
766 rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_RQT_TSF, H2C_MCC_RQT_TSF_LEN, cmd);
767
768 if (!rtw_sctx_wait(tsf_req_sctx, __func__))
769 RTW_INFO(FUNC_ADPT_FMT": wait for mcc tsf req C2H time out\n", FUNC_ADPT_ARG(padapter));
770
771 if (tsf_req_sctx->status == RTW_SCTX_DONE_SUCCESS && out_tsf != NULL) {
772 out_tsf[0] = order0_iface->mcc_adapterpriv.tsf;
773 out_tsf[1] = order1_iface->mcc_adapterpriv.tsf;
774 }
775
776
777 _exit_critical_mutex(&mccobjpriv->mcc_tsf_req_mutex, NULL);
778 }
779
rtw_hal_mcc_check_start_time_is_valid(PADAPTER padapter,u8 case_num,u32 tsfdiff,s8 * upper_bound_0,s8 * lower_bound_0,s8 * upper_bound_1,s8 * lower_bound_1)780 static u8 rtw_hal_mcc_check_start_time_is_valid(PADAPTER padapter, u8 case_num,
781 u32 tsfdiff, s8 *upper_bound_0, s8 *lower_bound_0, s8 *upper_bound_1, s8 *lower_bound_1)
782 {
783 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
784 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
785 u8 duration_0 = 0, duration_1 = 0;
786 s8 final_upper_bound = 0, final_lower_bound = 0;
787 u8 intersection = _FALSE;
788 u8 min_start_time = 5;
789 u8 max_start_time = 95;
790
791 duration_0 = mccobjpriv->iface[0]->mcc_adapterpriv.mcc_duration;
792 duration_1 = mccobjpriv->iface[1]->mcc_adapterpriv.mcc_duration;
793
794 switch(case_num) {
795 case 1:
796 *upper_bound_0 = tsfdiff;
797 *lower_bound_0 = tsfdiff - duration_1;
798 *upper_bound_1 = 150 - duration_1;
799 *lower_bound_1= 0;
800 break;
801 case 2:
802 *upper_bound_0 = tsfdiff + 100;
803 *lower_bound_0 = tsfdiff + 100 - duration_1;
804 *upper_bound_1 = 150 - duration_1;
805 *lower_bound_1= 0;
806 break;
807 case 3:
808 *upper_bound_0 = tsfdiff + 50;
809 *lower_bound_0 = tsfdiff + 50 - duration_1;
810 *upper_bound_1 = 150 - duration_1;
811 *lower_bound_1= 0;
812 break;
813 case 4:
814 *upper_bound_0 = tsfdiff;
815 *lower_bound_0 = tsfdiff - duration_1;
816 *upper_bound_1 = 150 - duration_1;
817 *lower_bound_1= 0;
818 break;
819 case 5:
820 *upper_bound_0 = 200 - tsfdiff;
821 *lower_bound_0 = 200 - tsfdiff - duration_1;
822 *upper_bound_1 = 150 - duration_1;
823 *lower_bound_1= 0;
824 break;
825 case 6:
826 *upper_bound_0 = tsfdiff - 50;
827 *lower_bound_0 = tsfdiff - 50 - duration_1;
828 *upper_bound_1 = 150 - duration_1;
829 *lower_bound_1= 0;
830 break;
831 default:
832 RTW_ERR("[MCC] %s: error case number(%d\n)", __func__, case_num);
833 }
834
835
836 /* check Intersection or not */
837 if ((*lower_bound_1 >= *upper_bound_0) ||
838 (*lower_bound_0 >= *upper_bound_1))
839 intersection = _FALSE;
840 else
841 intersection = _TRUE;
842
843 if (intersection) {
844 if (*upper_bound_0 > *upper_bound_1)
845 final_upper_bound = *upper_bound_1;
846 else
847 final_upper_bound = *upper_bound_0;
848
849 if (*lower_bound_0 > *lower_bound_1)
850 final_lower_bound = *lower_bound_0;
851 else
852 final_lower_bound = *lower_bound_1;
853
854 mccobjpriv->start_time = (final_lower_bound + final_upper_bound) / 2;
855
856 /* check start time less than 5ms, request by Pablo@SD1 */
857 if (mccobjpriv->start_time <= min_start_time) {
858 mccobjpriv->start_time = 6;
859 if (mccobjpriv->start_time < final_lower_bound && mccobjpriv->start_time > final_upper_bound) {
860 intersection = _FALSE;
861 goto exit;
862 }
863 }
864
865 /* check start time less than 95ms */
866 if (mccobjpriv->start_time >= max_start_time) {
867 mccobjpriv->start_time = 90;
868 if (mccobjpriv->start_time < final_lower_bound && mccobjpriv->start_time > final_upper_bound) {
869 intersection = _FALSE;
870 goto exit;
871 }
872 }
873 }
874
875 exit:
876 return intersection;
877 }
878
rtw_hal_mcc_decide_duration(PADAPTER padapter)879 static void rtw_hal_mcc_decide_duration(PADAPTER padapter)
880 {
881 struct registry_priv *registry_par = &padapter->registrypriv;
882 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
883 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
884 struct mcc_adapter_priv *mccadapriv = NULL, *mccadapriv_order0 = NULL, *mccadapriv_order1 = NULL;
885 _adapter *iface = NULL, *iface_order0 = NULL, *iface_order1 = NULL;
886 u8 duration = 0, i = 0, duration_time;
887 u8 mcc_interval = 150;
888
889 iface_order0 = mccobjpriv->iface[0];
890 iface_order1 = mccobjpriv->iface[1];
891 mccadapriv_order0 = &iface_order0->mcc_adapterpriv;
892 mccadapriv_order1 = &iface_order1->mcc_adapterpriv;
893
894 if (mccobjpriv->duration == 0) {
895 /* default */
896 duration = 30;/*(%)*/
897 RTW_INFO("%s: mccobjpriv->duration=0, use default value(%d)\n",
898 __FUNCTION__, duration);
899 } else {
900 duration = mccobjpriv->duration;/*(%)*/
901 RTW_INFO("%s: mccobjpriv->duration=%d\n",
902 __FUNCTION__, duration);
903 }
904
905 mccobjpriv->interval = mcc_interval;
906 mccobjpriv->mcc_stop_threshold = 2000 * 4 / 300 - 6;
907 /* convert % to ms, for primary adapter */
908 duration_time = mccobjpriv->interval * duration / 100;
909
910 for (i = 0; i < dvobj->iface_nums; i++) {
911 iface = dvobj->padapters[i];
912
913 if (!iface)
914 continue;
915
916 mccadapriv = &iface->mcc_adapterpriv;
917 if (mccadapriv->role == MCC_ROLE_MAX)
918 continue;
919
920 if (is_primary_adapter(iface))
921 mccadapriv->mcc_duration = duration_time;
922 else
923 mccadapriv->mcc_duration = mccobjpriv->interval - duration_time;
924 }
925
926 RTW_INFO("[MCC]" FUNC_ADPT_FMT " order 0 duration=%d\n", FUNC_ADPT_ARG(iface_order0), mccadapriv_order0->mcc_duration);
927 RTW_INFO("[MCC]" FUNC_ADPT_FMT " order 1 duration=%d\n", FUNC_ADPT_ARG(iface_order1), mccadapriv_order1->mcc_duration);
928 }
929
rtw_hal_mcc_update_timing_parameters(PADAPTER padapter,u8 force_update)930 static u8 rtw_hal_mcc_update_timing_parameters(PADAPTER padapter, u8 force_update)
931 {
932 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
933 u8 need_update = _FALSE;
934 u8 starting_ap_num = DEV_AP_STARTING_NUM(dvobj);
935 u8 ap_num = DEV_AP_NUM(dvobj);
936
937
938 /* for STA+STA, modify policy table */
939 if (starting_ap_num == 0 && ap_num == 0) {
940 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
941 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
942 struct mcc_adapter_priv *pmccadapriv = NULL;
943 _adapter *iface = NULL;
944 u64 tsf[MAX_MCC_NUM] = {0};
945 u64 tsf0 = 0, tsf1 = 0;
946 u32 beaconperiod_0 = 0, beaconperiod_1 = 0, tsfdiff = 0;
947 s8 upper_bound_0 = 0, lower_bound_0 = 0;
948 s8 upper_bound_1 = 0, lower_bound_1 = 0;
949 u8 valid = _FALSE;
950 u8 case_num = 1;
951 u8 i = 0;
952
953 /* query TSF */
954 rtw_hal_mcc_rqt_tsf(padapter, tsf);
955
956 /* selecet policy table according TSF diff */
957 tsf0 = tsf[0];
958 beaconperiod_0 = pmccobjpriv->iface[0]->mlmepriv.cur_network.network.Configuration.BeaconPeriod;
959 tsf0 = rtw_modular64(tsf0, (beaconperiod_0 * TU));
960
961 tsf1 = tsf[1];
962 beaconperiod_1 = pmccobjpriv->iface[1]->mlmepriv.cur_network.network.Configuration.BeaconPeriod;
963 tsf1 = rtw_modular64(tsf1, (beaconperiod_1 * TU));
964
965 if (tsf0 > tsf1)
966 tsfdiff = tsf0- tsf1;
967 else
968 tsfdiff = (tsf0 + beaconperiod_0 * TU) - tsf1;
969
970 /* convert to ms */
971 tsfdiff = (tsfdiff / TU);
972
973 /* force update*/
974 if (force_update) {
975 RTW_INFO("orig TSF0:%lld, orig TSF1:%lld\n",
976 pmccobjpriv->iface[0]->mcc_adapterpriv.tsf, pmccobjpriv->iface[1]->mcc_adapterpriv.tsf);
977 RTW_INFO("tsf0:%lld, tsf1:%lld\n", tsf0, tsf1);
978 RTW_INFO("%s: force=%d, last_tsfdiff=%d, tsfdiff=%d, THRESHOLD=%d\n",
979 __func__, force_update, pmccobjpriv->last_tsfdiff, tsfdiff, MCC_UPDATE_PARAMETER_THRESHOLD);
980 pmccobjpriv->last_tsfdiff = tsfdiff;
981 need_update = _TRUE;
982 } else {
983 if (pmccobjpriv->last_tsfdiff > tsfdiff) {
984 /* last tsfdiff - current tsfdiff > THRESHOLD, update parameters */
985 if (pmccobjpriv->last_tsfdiff > (tsfdiff + MCC_UPDATE_PARAMETER_THRESHOLD)) {
986 RTW_INFO("orig TSF0:%lld, orig TSF1:%lld\n",
987 pmccobjpriv->iface[0]->mcc_adapterpriv.tsf, pmccobjpriv->iface[1]->mcc_adapterpriv.tsf);
988 RTW_INFO("tsf0:%lld, tsf1:%lld\n", tsf0, tsf1);
989 RTW_INFO("%s: force=%d, last_tsfdiff=%d, tsfdiff=%d, THRESHOLD=%d\n",
990 __func__, force_update, pmccobjpriv->last_tsfdiff, tsfdiff, MCC_UPDATE_PARAMETER_THRESHOLD);
991
992 pmccobjpriv->last_tsfdiff = tsfdiff;
993 need_update = _TRUE;
994 } else {
995 need_update = _FALSE;
996 }
997 } else if (tsfdiff > pmccobjpriv->last_tsfdiff){
998 /* current tsfdiff - last tsfdiff > THRESHOLD, update parameters */
999 if (tsfdiff > (pmccobjpriv->last_tsfdiff + MCC_UPDATE_PARAMETER_THRESHOLD)) {
1000 RTW_INFO("orig TSF0:%lld, orig TSF1:%lld\n",
1001 pmccobjpriv->iface[0]->mcc_adapterpriv.tsf, pmccobjpriv->iface[1]->mcc_adapterpriv.tsf);
1002 RTW_INFO("tsf0:%lld, tsf1:%lld\n", tsf0, tsf1);
1003 RTW_INFO("%s: force=%d, last_tsfdiff=%d, tsfdiff=%d, THRESHOLD=%d\n",
1004 __func__, force_update, pmccobjpriv->last_tsfdiff, tsfdiff, MCC_UPDATE_PARAMETER_THRESHOLD);
1005
1006 pmccobjpriv->last_tsfdiff = tsfdiff;
1007 need_update = _TRUE;
1008 } else {
1009 need_update = _FALSE;
1010 }
1011 } else {
1012 need_update = _FALSE;
1013 }
1014 }
1015
1016 if (need_update == _FALSE)
1017 goto exit;
1018
1019 rtw_hal_mcc_decide_duration(padapter);
1020
1021 if (tsfdiff <= 50) {
1022
1023 /* RX TBTT 0 */
1024 case_num = 1;
1025 valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1026 &upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1027
1028 if (valid)
1029 goto valid_result;
1030
1031 /* RX TBTT 1 */
1032 case_num = 2;
1033 valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1034 &upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1035
1036 if (valid)
1037 goto valid_result;
1038
1039 /* RX TBTT 2 */
1040 case_num = 3;
1041 valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1042 &upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1043
1044 if (valid)
1045 goto valid_result;
1046
1047 if (valid == _FALSE) {
1048 RTW_INFO("[MCC] do not find fit start time\n");
1049 RTW_INFO("[MCC] tsfdiff:%d, duration:%d(%c), interval:%d\n",
1050 tsfdiff, pmccobjpriv->duration, 37, pmccobjpriv->interval);
1051
1052 }
1053
1054 } else {
1055
1056 /* RX TBTT 0 */
1057 case_num = 4;
1058 valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1059 &upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1060
1061 if (valid)
1062 goto valid_result;
1063
1064
1065 /* RX TBTT 1 */
1066 case_num = 5;
1067 valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1068 &upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1069
1070 if (valid)
1071 goto valid_result;
1072
1073
1074 /* RX TBTT 2 */
1075 case_num = 6;
1076 valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1077 &upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1078
1079 if (valid)
1080 goto valid_result;
1081
1082 if (valid == _FALSE) {
1083 RTW_INFO("[MCC] do not find fit start time\n");
1084 RTW_INFO("[MCC] tsfdiff:%d, duration:%d(%c), interval:%d\n",
1085 tsfdiff, pmccobjpriv->duration, 37, pmccobjpriv->interval);
1086 }
1087 }
1088
1089
1090
1091 valid_result:
1092 RTW_INFO("********************\n");
1093 RTW_INFO("%s: case_num:%d, start time:%d\n",
1094 __func__, case_num, pmccobjpriv->start_time);
1095 RTW_INFO("%s: upper_bound_0:%d, lower_bound_0:%d\n",
1096 __func__, upper_bound_0, lower_bound_0);
1097 RTW_INFO("%s: upper_bound_1:%d, lower_bound_1:%d\n",
1098 __func__, upper_bound_1, lower_bound_1);
1099
1100 for (i = 0; i < dvobj->iface_nums; i++) {
1101 iface = dvobj->padapters[i];
1102 if (iface == NULL)
1103 continue;
1104
1105 pmccadapriv = &iface->mcc_adapterpriv;
1106 pmccadapriv = &iface->mcc_adapterpriv;
1107 if (pmccadapriv->role == MCC_ROLE_MAX)
1108 continue;
1109 #if 0
1110 if (pmccadapriv->order == 0) {
1111 pmccadapriv->mcc_duration = mcc_duration;
1112 } else if (pmccadapriv->order == 1) {
1113 pmccadapriv->mcc_duration = mcc_interval - mcc_duration;
1114 } else {
1115 RTW_INFO("[MCC] not support >= 3 interface\n");
1116 rtw_warn_on(1);
1117 }
1118 #endif
1119 RTW_INFO("********************\n");
1120 RTW_INFO(FUNC_ADPT_FMT": order:%d, role:%d\n",
1121 FUNC_ADPT_ARG(iface), pmccadapriv->order, pmccadapriv->role);
1122 RTW_INFO(FUNC_ADPT_FMT": mcc duration:%d, target tx bytes:%d\n",
1123 FUNC_ADPT_ARG(iface), pmccadapriv->mcc_duration, pmccadapriv->mcc_target_tx_bytes_to_port);
1124 RTW_INFO(FUNC_ADPT_FMT": mgmt queue macid:%d, bitmap:0x%02x\n",
1125 FUNC_ADPT_ARG(iface), pmccadapriv->mgmt_queue_macid, pmccadapriv->mcc_macid_bitmap);
1126 RTW_INFO("********************\n");
1127 }
1128
1129 }
1130 exit:
1131 return need_update;
1132 }
1133
rtw_hal_decide_mcc_role(PADAPTER padapter)1134 static u8 rtw_hal_decide_mcc_role(PADAPTER padapter)
1135 {
1136 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1137 _adapter *iface = NULL;
1138 struct mcc_adapter_priv *pmccadapriv = NULL;
1139 struct wifidirect_info *pwdinfo = NULL;
1140 struct mlme_priv *pmlmepriv = NULL;
1141 u8 ret = _SUCCESS, i = 0;
1142 u8 order = 1;
1143
1144 for (i = 0; i < dvobj->iface_nums; i++) {
1145 iface = dvobj->padapters[i];
1146 if (iface == NULL)
1147 continue;
1148
1149 pmccadapriv = &iface->mcc_adapterpriv;
1150 pwdinfo = &iface->wdinfo;
1151
1152 if (MLME_IS_GO(iface))
1153 pmccadapriv->role = MCC_ROLE_GO;
1154 else if (MLME_IS_AP(iface))
1155 pmccadapriv->role = MCC_ROLE_AP;
1156 else if (MLME_IS_GC(iface))
1157 pmccadapriv->role = MCC_ROLE_GC;
1158 else if (MLME_IS_STA(iface)) {
1159 if (MLME_IS_LINKING(iface) || MLME_IS_ASOC(iface))
1160 pmccadapriv->role = MCC_ROLE_STA;
1161 else {
1162 /* bypass non-linked/non-linking interface */
1163 RTW_INFO(FUNC_ADPT_FMT" mlme state:0x%2x\n",
1164 FUNC_ADPT_ARG(iface), MLME_STATE(iface));
1165 continue;
1166 }
1167 } else {
1168 /* bypass non-linked/non-linking interface */
1169 RTW_INFO(FUNC_ADPT_FMT" P2P Role:%d, mlme state:0x%2x\n",
1170 FUNC_ADPT_ARG(iface), pwdinfo->role, MLME_STATE(iface));
1171 continue;
1172 }
1173
1174 if (padapter == iface) {
1175 /* current adapter is order 0 */
1176 rtw_hal_config_mcc_role_setting(iface, 0);
1177 } else {
1178 rtw_hal_config_mcc_role_setting(iface, order);
1179 order ++;
1180 }
1181 }
1182
1183 rtw_hal_mcc_update_timing_parameters(padapter, _TRUE);
1184
1185 return ret;
1186 }
1187
rtw_hal_construct_CTS(PADAPTER padapter,u8 * pframe,u32 * pLength)1188 static void rtw_hal_construct_CTS(PADAPTER padapter, u8 *pframe, u32 *pLength)
1189 {
1190 u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1191
1192 /* frame type, length = 1*/
1193 set_frame_sub_type(pframe, WIFI_RTS);
1194
1195 /* frame control flag, length = 1 */
1196 *(pframe + 1) = 0;
1197
1198 /* frame duration, length = 2 */
1199 *(pframe + 2) = 0x00;
1200 *(pframe + 3) = 0x78;
1201
1202 /* frame recvaddr, length = 6 */
1203 _rtw_memcpy((pframe + 4), broadcast_addr, ETH_ALEN);
1204 _rtw_memcpy((pframe + 4 + ETH_ALEN), adapter_mac_addr(padapter), ETH_ALEN);
1205 _rtw_memcpy((pframe + 4 + ETH_ALEN*2), adapter_mac_addr(padapter), ETH_ALEN);
1206 *pLength = 22;
1207 }
1208
1209 /* avoid wrong information for power limit */
rtw_hal_mcc_upadate_chnl_bw(_adapter * padapter,u8 ch,u8 ch_offset,u8 bw,u8 print)1210 void rtw_hal_mcc_upadate_chnl_bw(_adapter *padapter, u8 ch, u8 ch_offset, u8 bw, u8 print)
1211 {
1212
1213 u8 center_ch, chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1214 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1215 PHAL_DATA_TYPE hal = GET_HAL_DATA(padapter);
1216 u8 cch_160, cch_80, cch_40, cch_20;
1217
1218 center_ch = rtw_get_center_ch(ch, bw, ch_offset);
1219
1220 if (bw == CHANNEL_WIDTH_80) {
1221 if (center_ch > ch)
1222 chnl_offset80 = HAL_PRIME_CHNL_OFFSET_LOWER;
1223 else if (center_ch < ch)
1224 chnl_offset80 = HAL_PRIME_CHNL_OFFSET_UPPER;
1225 else
1226 chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1227 }
1228
1229 /* set Channel */
1230 /* saved channel/bw info */
1231 rtw_set_oper_ch(padapter, ch);
1232 rtw_set_oper_bw(padapter, bw);
1233 rtw_set_oper_choffset(padapter, ch_offset);
1234
1235 cch_80 = bw == CHANNEL_WIDTH_80 ? center_ch : 0;
1236 cch_40 = bw == CHANNEL_WIDTH_40 ? center_ch : 0;
1237 cch_20 = bw == CHANNEL_WIDTH_20 ? center_ch : 0;
1238
1239 if (cch_80 != 0)
1240 cch_40 = rtw_get_scch_by_cch_offset(cch_80, CHANNEL_WIDTH_80, chnl_offset80);
1241 if (cch_40 != 0)
1242 cch_20 = rtw_get_scch_by_cch_offset(cch_40, CHANNEL_WIDTH_40, ch_offset);
1243
1244
1245 hal->cch_80 = cch_80;
1246 hal->cch_40 = cch_40;
1247 hal->cch_20 = cch_20;
1248 hal->current_channel = center_ch;
1249 hal->CurrentCenterFrequencyIndex1 = center_ch;
1250 hal->current_channel_bw = bw;
1251 hal->nCur40MhzPrimeSC = ch_offset;
1252 hal->nCur80MhzPrimeSC = chnl_offset80;
1253 hal->current_band_type = ch > 14 ? BAND_ON_5G:BAND_ON_2_4G;
1254
1255 if (print) {
1256 RTW_INFO(FUNC_ADPT_FMT" cch:%u, %s, offset40:%u, offset80:%u (%u, %u, %u), band:%s\n"
1257 , FUNC_ADPT_ARG(padapter), center_ch, ch_width_str(bw)
1258 , ch_offset, chnl_offset80
1259 , hal->cch_80, hal->cch_40, hal->cch_20
1260 , band_str(hal->current_band_type));
1261 }
1262 }
1263
rtw_hal_dl_mcc_fw_rsvd_page(_adapter * adapter,u8 * pframe,u16 * index,u8 tx_desc,u32 page_size,u8 * total_page_num,RSVDPAGE_LOC * rsvd_page_loc,u8 * page_num)1264 u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
1265 u8 tx_desc, u32 page_size, u8 *total_page_num, RSVDPAGE_LOC *rsvd_page_loc, u8 *page_num)
1266 {
1267 u32 len = 0;
1268 _adapter *iface = NULL;
1269 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
1270 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
1271 struct mlme_ext_info *pmlmeinfo = NULL;
1272 struct mlme_ext_priv *pmlmeext = NULL;
1273 struct hal_com_data *hal = GET_HAL_DATA(adapter);
1274 struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
1275 struct mcc_adapter_priv *mccadapriv = NULL;
1276 #if defined(CONFIG_RTL8822C)
1277 struct dm_struct *phydm = adapter_to_phydm(adapter);
1278 struct txagc_table_8822c tab;
1279 u8 agc_buff[2][NUM_RATE_AC_2SS]; /* tatol 0x40 rate index for PATH A/B */
1280 #endif
1281
1282 u8 ret = _SUCCESS, i = 0, j =0, order = 0, CurtPktPageNum = 0;
1283 u8 *start = NULL;
1284 u8 path = RF_PATH_A;
1285
1286 if (page_num) {
1287 #ifdef CONFIG_MCC_MODE_V2
1288 if (!hal->RegIQKFWOffload)
1289 RTW_WARN("[MCC] must enable FW IQK for New IC\n");
1290 #endif /* CONFIG_MCC_MODE_V2 */
1291 *total_page_num += (2 * MAX_MCC_NUM+ 1);
1292 RTW_INFO("[MCC] allocate mcc rsvd page num = %d\n", *total_page_num);
1293 goto exit;
1294 }
1295
1296 /* check proccess mcc start setting */
1297 if (!rtw_hal_check_mcc_status(adapter, MCC_STATUS_PROCESS_MCC_START_SETTING)) {
1298 ret = _FAIL;
1299 goto exit;
1300 }
1301
1302 for (i = 0; i < dvobj->iface_nums; i++) {
1303 iface = dvobj->padapters[i];
1304 if (iface == NULL)
1305 continue;
1306
1307 mccadapriv = &iface->mcc_adapterpriv;
1308 if (mccadapriv->role == MCC_ROLE_MAX)
1309 continue;
1310
1311 order = mccadapriv->order;
1312 pmccobjpriv->mcc_loc_rsvd_paga[order] = *total_page_num;
1313
1314 switch (mccadapriv->role) {
1315 case MCC_ROLE_STA:
1316 case MCC_ROLE_GC:
1317 /* Build NULL DATA */
1318 RTW_INFO("LocNull(order:%d): %d\n"
1319 , order, pmccobjpriv->mcc_loc_rsvd_paga[order]);
1320 len = 0;
1321
1322 rtw_hal_construct_NullFunctionData(iface
1323 , &pframe[*index], &len, _FALSE, 0, 0, _FALSE);
1324 rtw_hal_fill_fake_txdesc(iface, &pframe[*index-tx_desc],
1325 len, _FALSE, _FALSE, _FALSE);
1326
1327 CurtPktPageNum = (u8)PageNum(tx_desc + len, page_size);
1328 *total_page_num += CurtPktPageNum;
1329 *index += (CurtPktPageNum * page_size);
1330 RSVD_PAGE_CFG("LocNull", CurtPktPageNum, *total_page_num, *index);
1331 break;
1332 case MCC_ROLE_AP:
1333 /* Bulid CTS */
1334 RTW_INFO("LocCTS(order:%d): %d\n"
1335 , order, pmccobjpriv->mcc_loc_rsvd_paga[order]);
1336
1337 len = 0;
1338 rtw_hal_construct_CTS(iface, &pframe[*index], &len);
1339 rtw_hal_fill_fake_txdesc(iface, &pframe[*index-tx_desc],
1340 len, _FALSE, _FALSE, _FALSE);
1341
1342 CurtPktPageNum = (u8)PageNum(tx_desc + len, page_size);
1343 *total_page_num += CurtPktPageNum;
1344 *index += (CurtPktPageNum * page_size);
1345 RSVD_PAGE_CFG("LocCTS", CurtPktPageNum, *total_page_num, *index);
1346 break;
1347 case MCC_ROLE_GO:
1348 /* To DO */
1349 break;
1350 default:
1351 RTW_INFO(FUNC_ADPT_FMT": unknown role = %d\n"
1352 , FUNC_ADPT_ARG(iface), mccadapriv->role);
1353 break;
1354 }
1355 }
1356
1357 for (i = 0; i < MAX_MCC_NUM; i++) {
1358 u8 center_ch = 0, ch = 0, bw = 0, bw_offset = 0;
1359 BAND_TYPE band = BAND_MAX;
1360 u8 power_index = 0;
1361 u8 rate_array_sz = 0;
1362 u8 *rates = NULL;
1363 u8 rate = 0;
1364 u8 shift = 0;
1365 u32 power_index_4bytes = 0;
1366 u8 total_rate = 0;
1367 u8 *total_rate_offset = NULL;
1368
1369 iface = pmccobjpriv->iface[i];
1370 pmlmeext = &iface->mlmeextpriv;
1371 ch = pmlmeext->cur_channel;
1372 bw = pmlmeext->cur_bwmode;
1373 bw_offset = pmlmeext->cur_ch_offset;
1374 center_ch = rtw_get_center_ch(ch, bw, bw_offset);
1375 band = center_ch <= 14 ? BAND_ON_2_4G : BAND_ON_5G;
1376 rtw_hal_mcc_upadate_chnl_bw(iface, ch, bw_offset, bw, _TRUE);
1377
1378 start = &pframe[*index - tx_desc];
1379 _rtw_memset(start, 0, page_size);
1380 pmccobjpriv->mcc_pwr_idx_rsvd_page[i] = *total_page_num;
1381 RTW_INFO(ADPT_FMT" order:%d, pwr_idx_rsvd_page location[%d]: %d\n",
1382 ADPT_ARG(iface), mccadapriv->order,
1383 i, pmccobjpriv->mcc_pwr_idx_rsvd_page[i]);
1384
1385 total_rate_offset = start;
1386 #if !defined(CONFIG_RTL8822C)
1387 for (path = RF_PATH_A; path < hal_spec->rf_reg_path_num; ++path) {
1388 total_rate = 0;
1389 /* PATH A for 0~63 byte, PATH B for 64~127 byte*/
1390 if (path == RF_PATH_A)
1391 start = total_rate_offset + 1;
1392 else if (path == RF_PATH_B)
1393 start = total_rate_offset + 64;
1394 else {
1395 RTW_INFO("[MCC] %s: unknow RF PATH(%d)\n", __func__, path);
1396 break;
1397 }
1398
1399 /* CCK */
1400 if (ch <= 14) {
1401 rate_array_sz = rates_by_sections[CCK].rate_num;
1402 rates = rates_by_sections[CCK].rates;
1403 for (j = 0; j < rate_array_sz; ++j) {
1404 power_index = phy_get_tx_power_index_ex(iface, path, CCK, rates[j], bw, band, center_ch, ch);
1405 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1406
1407 shift = rate % 4;
1408 if (shift == 0) {
1409 *start = rate;
1410 start++;
1411 total_rate++;
1412
1413 #ifdef DBG_PWR_IDX_RSVD_PAGE
1414 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1415 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1416 center_ch, MGN_RATE_STR(rates[j]), power_index);
1417 #endif
1418 }
1419
1420 *start = power_index;
1421 start++;
1422
1423 #ifdef DBG_PWR_IDX_RSVD_PAGE
1424 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1425 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1426 center_ch, MGN_RATE_STR(rates[j]), power_index);
1427
1428
1429 shift = rate % 4;
1430 power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1431 if (shift == 3) {
1432 rate = rate - 3;
1433 RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1434 power_index_4bytes = 0;
1435 total_rate++;
1436 }
1437 #endif
1438
1439 }
1440 }
1441
1442 /* OFDM */
1443 rate_array_sz = rates_by_sections[OFDM].rate_num;
1444 rates = rates_by_sections[OFDM].rates;
1445 for (j = 0; j < rate_array_sz; ++j) {
1446 power_index = phy_get_tx_power_index_ex(iface, path, OFDM, rates[j], bw, band, center_ch, ch);
1447 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1448
1449 shift = rate % 4;
1450 if (shift == 0) {
1451 *start = rate;
1452 start++;
1453 total_rate++;
1454
1455 #ifdef DBG_PWR_IDX_RSVD_PAGE
1456 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1457 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1458 center_ch, MGN_RATE_STR(rates[j]), power_index);
1459 #endif
1460
1461 }
1462
1463 *start = power_index;
1464 start++;
1465
1466 #ifdef DBG_PWR_IDX_RSVD_PAGE
1467 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1468 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1469 center_ch, MGN_RATE_STR(rates[j]), power_index);
1470
1471 shift = rate % 4;
1472 power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1473 if (shift == 3) {
1474 rate = rate - 3;
1475 RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1476 power_index_4bytes = 0;
1477 total_rate++;
1478 }
1479 #endif
1480 }
1481
1482 /* HT_MCS0_MCS7 */
1483 rate_array_sz = rates_by_sections[HT_MCS0_MCS7].rate_num;
1484 rates = rates_by_sections[HT_MCS0_MCS7].rates;
1485 for (j = 0; j < rate_array_sz; ++j) {
1486 power_index = phy_get_tx_power_index_ex(iface, path, HT_1SS, rates[j], bw, band, center_ch, ch);
1487 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1488
1489 shift = rate % 4;
1490 if (shift == 0) {
1491 *start = rate;
1492 start++;
1493 total_rate++;
1494
1495 #ifdef DBG_PWR_IDX_RSVD_PAGE
1496 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1497 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1498 center_ch, MGN_RATE_STR(rates[j]), power_index);
1499 #endif
1500
1501 }
1502
1503 *start = power_index;
1504 start++;
1505
1506 #ifdef DBG_PWR_IDX_RSVD_PAGE
1507 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1508 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1509 center_ch, MGN_RATE_STR(rates[j]), power_index);
1510
1511 shift = rate % 4;
1512 power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1513 if (shift == 3) {
1514 rate = rate - 3;
1515 RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1516 power_index_4bytes = 0;
1517 total_rate++;
1518 }
1519 #endif
1520 }
1521
1522 /* HT_MCS8_MCS15 */
1523 rate_array_sz = rates_by_sections[HT_MCS8_MCS15].rate_num;
1524 rates = rates_by_sections[HT_MCS8_MCS15].rates;
1525 for (j = 0; j < rate_array_sz; ++j) {
1526 power_index = phy_get_tx_power_index_ex(iface, path, HT_2SS, rates[j], bw, band, center_ch, ch);
1527 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1528
1529 shift = rate % 4;
1530 if (shift == 0) {
1531 *start = rate;
1532 start++;
1533 total_rate++;
1534
1535 #ifdef DBG_PWR_IDX_RSVD_PAGE
1536 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1537 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1538 center_ch, MGN_RATE_STR(rates[j]), power_index);
1539 #endif
1540 }
1541
1542 *start = power_index;
1543 start++;
1544
1545 #ifdef DBG_PWR_IDX_RSVD_PAGE
1546 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1547 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1548 center_ch, MGN_RATE_STR(rates[j]), power_index);
1549
1550 shift = rate % 4;
1551 power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1552 if (shift == 3) {
1553 rate = rate - 3;
1554 RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1555 power_index_4bytes = 0;
1556 total_rate++;
1557 }
1558 #endif
1559 }
1560
1561 /* VHT_1SSMCS0_1SSMCS9 */
1562 rate_array_sz = rates_by_sections[VHT_1SSMCS0_1SSMCS9].rate_num;
1563 rates = rates_by_sections[VHT_1SSMCS0_1SSMCS9].rates;
1564 for (j = 0; j < rate_array_sz; ++j) {
1565 power_index = phy_get_tx_power_index_ex(iface, path, VHT_1SS, rates[j], bw, band, center_ch, ch);
1566 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1567
1568 shift = rate % 4;
1569 if (shift == 0) {
1570 *start = rate;
1571 start++;
1572 total_rate++;
1573 #ifdef DBG_PWR_IDX_RSVD_PAGE
1574 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:0x%02x\n",
1575 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1576 center_ch, MGN_RATE_STR(rates[j]), power_index);
1577 #endif
1578 }
1579 *start = power_index;
1580 start++;
1581 #ifdef DBG_PWR_IDX_RSVD_PAGE
1582 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1583 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1584 center_ch, MGN_RATE_STR(rates[j]), power_index);
1585
1586 shift = rate % 4;
1587 power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1588 if (shift == 3) {
1589 rate = rate - 3;
1590 RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1591 power_index_4bytes = 0;
1592 total_rate++;
1593 }
1594 #endif
1595 }
1596
1597 /* VHT_2SSMCS0_2SSMCS9 */
1598 rate_array_sz = rates_by_sections[VHT_2SSMCS0_2SSMCS9].rate_num;
1599 rates = rates_by_sections[VHT_2SSMCS0_2SSMCS9].rates;
1600 for (j = 0; j < rate_array_sz; ++j) {
1601 power_index = phy_get_tx_power_index_ex(iface, path, VHT_2SS, rates[j], bw, band, center_ch, ch);
1602 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1603
1604 shift = rate % 4;
1605 if (shift == 0) {
1606 *start = rate;
1607 start++;
1608 total_rate++;
1609 #ifdef DBG_PWR_IDX_RSVD_PAGE
1610 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1611 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1612 center_ch, MGN_RATE_STR(rates[j]), power_index);
1613 #endif
1614 }
1615 *start = power_index;
1616 start++;
1617 #ifdef DBG_PWR_IDX_RSVD_PAGE
1618 RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1619 ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1620 center_ch, MGN_RATE_STR(rates[j]), power_index);
1621
1622 shift = rate % 4;
1623 power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1624 if (shift == 3) {
1625 rate = rate - 3;
1626 RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1627 power_index_4bytes = 0;
1628 total_rate++;
1629 }
1630 #endif
1631 }
1632
1633 }
1634 /* total rate store in offset 0 */
1635 *total_rate_offset = total_rate;
1636
1637 #ifdef DBG_PWR_IDX_RSVD_PAGE
1638 RTW_INFO("total_rate=%d\n", total_rate);
1639 RTW_INFO(" ======================="ADPT_FMT"===========================\n", ADPT_ARG(iface));
1640 RTW_INFO_DUMP("\n", total_rate_offset, 128);
1641 RTW_INFO(" ==================================================\n");
1642 #endif
1643
1644 CurtPktPageNum = 1;
1645 *total_page_num += CurtPktPageNum;
1646 *index += (CurtPktPageNum * page_size);
1647 RSVD_PAGE_CFG("mcc_pwr_idx_rsvd_page", CurtPktPageNum, *total_page_num, *index);
1648 #else /* 8822C */
1649 for (path = RF_PATH_A; path < hal_spec->rf_reg_path_num; ++path) {
1650 /* CCK */
1651 if (ch <= 14) {
1652 rate_array_sz = rates_by_sections[CCK].rate_num;
1653 rates = rates_by_sections[CCK].rates;
1654 for (j = 0; j < rate_array_sz; ++j) {
1655 power_index = phy_get_tx_power_index_ex(iface, path, CCK, rates[j], bw, band, center_ch, ch);
1656 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1657 agc_buff[path][rate] = power_index;
1658 }
1659 }
1660
1661 /* OFDM */
1662 rate_array_sz = rates_by_sections[OFDM].rate_num;
1663 rates = rates_by_sections[OFDM].rates;
1664 for (j = 0; j < rate_array_sz; ++j) {
1665 power_index = phy_get_tx_power_index_ex(iface, path, OFDM, rates[j], bw, band, center_ch, ch);
1666 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1667 agc_buff[path][rate] = power_index;
1668 }
1669 /* HT */
1670 rate_array_sz = rates_by_sections[HT_MCS0_MCS7].rate_num;
1671 rates = rates_by_sections[HT_MCS0_MCS7].rates;
1672 for (j = 0; j < rate_array_sz; ++j) {
1673 power_index = phy_get_tx_power_index_ex(iface, path, HT_1SS, rates[j], bw, band, center_ch, ch);
1674 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1675 agc_buff[path][rate] = power_index;
1676 }
1677
1678 rate_array_sz = rates_by_sections[HT_MCS8_MCS15].rate_num;
1679 rates = rates_by_sections[HT_MCS8_MCS15].rates;
1680 for (j = 0; j < rate_array_sz; ++j) {
1681 power_index = phy_get_tx_power_index_ex(iface, path, HT_2SS, rates[j], bw, band, center_ch, ch);
1682 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1683 agc_buff[path][rate] = power_index;
1684 }
1685 /* VHT */
1686 rate_array_sz = rates_by_sections[VHT_1SSMCS0_1SSMCS9].rate_num;
1687 rates = rates_by_sections[VHT_1SSMCS0_1SSMCS9].rates;
1688 for (j = 0; j < rate_array_sz; ++j) {
1689 power_index = phy_get_tx_power_index_ex(iface, path, VHT_1SS, rates[j], bw, band, center_ch, ch);
1690 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1691 agc_buff[path][rate] = power_index;
1692 }
1693
1694 rate_array_sz = rates_by_sections[VHT_2SSMCS0_2SSMCS9].rate_num;
1695 rates = rates_by_sections[VHT_2SSMCS0_2SSMCS9].rates;
1696 for (j = 0; j < rate_array_sz; ++j) {
1697 power_index = phy_get_tx_power_index_ex(iface, path, VHT_2SS, rates[j], bw, band, center_ch, ch);
1698 rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
1699 agc_buff[path][rate] = power_index;
1700 }
1701 }
1702 phydm_get_txagc_ref_and_diff_8822c(phydm, agc_buff, NUM_RATE_AC_2SS, &tab);
1703 *start = tab.ref_pow_cck[0];
1704 start++;
1705 *start = tab.ref_pow_cck[1];
1706 start++;
1707 *start = tab.ref_pow_ofdm[0];
1708 start++;
1709 *start = tab.ref_pow_ofdm[1];
1710 start++;
1711 _rtw_memcpy(start, tab.diff_t, sizeof(tab.diff_t));
1712 CurtPktPageNum = 1;
1713 *total_page_num += CurtPktPageNum;
1714 *index += (CurtPktPageNum * page_size);
1715 RSVD_PAGE_CFG("mcc_pwr_idx_rsvd_page", CurtPktPageNum, *total_page_num, *index);
1716 #ifdef DBG_PWR_IDX_RSVD_PAGE
1717 if (1) {
1718 u8 path_idx;
1719 for (path_idx = 0; path_idx < 2; path_idx++) {
1720 for (j = 0; j < NUM_RATE_AC_2SS; j++)
1721 RTW_INFO("agc_buff[%d][%d]=%x\n", i, j, agc_buff[i][j]);
1722 }
1723 RTW_INFO("tab->ref_pow_cck[0]=%x\n", tab.ref_pow_cck[0]);
1724 RTW_INFO("tab->ref_pow_cck[1]=%x\n", tab.ref_pow_cck[1]);
1725 RTW_INFO("tab->ref_pow_ofdm[0]=%x\n", tab.ref_pow_ofdm[0]);
1726 RTW_INFO("tab->ref_pow_ofdm[1]=%x\n", tab.ref_pow_ofdm[1]);
1727 RTW_INFO_DUMP("diff_t ", tab.diff_t, NUM_RATE_AC_2SS);
1728 RTW_INFO_DUMP("tab ", (u8 *)&tab, sizeof(tab));
1729 }
1730 #endif
1731
1732 #endif
1733 }
1734
1735 exit:
1736 return ret;
1737 }
1738
1739 /*
1740 * 1. Download MCC rsvd page
1741 * 2. Re-Download beacon after download rsvd page
1742 */
rtw_hal_set_fw_mcc_rsvd_page(PADAPTER padapter)1743 static void rtw_hal_set_fw_mcc_rsvd_page(PADAPTER padapter)
1744 {
1745 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
1746 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
1747 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1748 PADAPTER port0_iface = dvobj_get_port0_adapter(dvobj);
1749 PADAPTER iface = NULL;
1750 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
1751 u8 mstatus = RT_MEDIA_CONNECT, i = 0;
1752
1753 RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1754
1755 rtw_hal_set_hwreg(port0_iface, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1756
1757 #ifdef CONFIG_AP_MODE
1758 /* Re-Download beacon */
1759 for (i = 0; i < MAX_MCC_NUM; i++) {
1760 iface = pmccobjpriv->iface[i];
1761 if (iface == NULL)
1762 continue;
1763
1764 pmccadapriv = &iface->mcc_adapterpriv;
1765
1766 if (pmccadapriv->role == MCC_ROLE_AP
1767 || pmccadapriv->role == MCC_ROLE_GO) {
1768 tx_beacon_hdl(iface, NULL);
1769 }
1770 }
1771 #endif
1772 }
1773
rtw_hal_set_mcc_rsvdpage_cmd(_adapter * padapter)1774 static void rtw_hal_set_mcc_rsvdpage_cmd(_adapter *padapter)
1775 {
1776 u8 cmd[H2C_MCC_LOCATION_LEN] = {0}, i = 0, order = 0;
1777 _adapter *iface = NULL;
1778 struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
1779 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1780 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
1781
1782 SET_H2CCMD_MCC_PWRIDX_OFFLOAD_EN(cmd, _TRUE);
1783 SET_H2CCMD_MCC_PWRIDX_OFFLOAD_RFNUM(cmd, hal_spec->rf_reg_path_num);
1784 for (order = 0; order < MAX_MCC_NUM; order++) {
1785 iface = pmccobjpriv->iface[i];
1786
1787 SET_H2CCMD_MCC_RSVDPAGE_LOC((cmd + order), pmccobjpriv->mcc_loc_rsvd_paga[order]);
1788 SET_H2CCMD_MCC_PWRIDX_RSVDPAGE_LOC ((cmd + order), pmccobjpriv->mcc_pwr_idx_rsvd_page[order]);
1789 }
1790
1791 #ifdef CONFIG_MCC_MODE_DEBUG
1792 RTW_INFO("=========================\n");
1793 RTW_INFO("MCC RSVD PAGE LOC:\n");
1794 for (i = 0; i < H2C_MCC_LOCATION_LEN; i++)
1795 pr_dbg("0x%x ", cmd[i]);
1796 pr_dbg("\n");
1797 RTW_INFO("=========================\n");
1798 #endif /* CONFIG_MCC_MODE_DEBUG */
1799
1800 rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_LOCATION, H2C_MCC_LOCATION_LEN, cmd);
1801 }
1802
rtw_hal_set_mcc_time_setting_cmd(PADAPTER padapter)1803 static void rtw_hal_set_mcc_time_setting_cmd(PADAPTER padapter)
1804 {
1805 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
1806 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1807 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1808 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
1809 u8 cmd[H2C_MCC_TIME_SETTING_LEN] = {0};
1810 u8 fw_eable = 1;
1811 u8 swchannel_early_time = MCC_SWCH_FW_EARLY_TIME;
1812 u8 starting_ap_num = DEV_AP_STARTING_NUM(dvobj);
1813 u8 ap_num = DEV_AP_NUM(dvobj);
1814
1815 if (starting_ap_num == 0 && ap_num == 0)
1816 /* For STA+GC/STA+STA, TSF of GC/STA does not need to sync from TSF of other STA/GC */
1817 fw_eable = 0;
1818 else
1819 /* Only for STA+GO/STA+AP, TSF of AP/GO need to sync from TSF of STA */
1820 fw_eable = 1;
1821
1822 if (fw_eable == 1) {
1823 PADAPTER order0_iface = NULL;
1824 PADAPTER order1_iface = NULL;
1825 u8 policy_idx = mccobjpriv->policy_index;
1826 u8 tsf_sync_offset = mcc_switch_channel_policy_table[policy_idx][MCC_TSF_SYNC_OFFSET_IDX];
1827 u8 start_time_offset = mcc_switch_channel_policy_table[policy_idx][MCC_START_TIME_OFFSET_IDX];
1828 u8 interval = mcc_switch_channel_policy_table[policy_idx][MCC_INTERVAL_IDX];
1829 u8 guard_offset0 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET0_IDX];
1830 u8 guard_offset1 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET1_IDX];
1831 enum _hw_port tsf_bsae_port = MAX_HW_PORT;
1832 enum _hw_port tsf_sync_port = MAX_HW_PORT;
1833 order0_iface = mccobjpriv->iface[0];
1834 order1_iface = mccobjpriv->iface[1];
1835
1836 tsf_bsae_port = rtw_hal_get_port(order1_iface);
1837 tsf_sync_port = rtw_hal_get_port(order0_iface);
1838
1839 /* FW set enable */
1840 SET_H2CCMD_MCC_TIME_SETTING_FW_EN(cmd, fw_eable);
1841 /* TSF Sync offset */
1842 SET_H2CCMD_MCC_TIME_SETTING_TSF_SYNC_OFFSET(cmd, tsf_sync_offset);
1843 /* start time offset */
1844 SET_H2CCMD_MCC_TIME_SETTING_START_TIME(cmd, (start_time_offset + guard_offset0));
1845 /* interval */
1846 SET_H2CCMD_MCC_TIME_SETTING_INTERVAL(cmd, interval);
1847 /* Early time to inform driver by C2H before switch channel */
1848 SET_H2CCMD_MCC_TIME_SETTING_EARLY_SWITCH_RPT(cmd, swchannel_early_time);
1849 /* Port0 sync from Port1, not support multi-port */
1850 SET_H2CCMD_MCC_TIME_SETTING_ORDER_BASE(cmd, tsf_bsae_port);
1851 SET_H2CCMD_MCC_TIME_SETTING_ORDER_SYNC(cmd, tsf_sync_port);
1852 } else {
1853 /* start time offset */
1854 SET_H2CCMD_MCC_TIME_SETTING_START_TIME(cmd, mccobjpriv->start_time);
1855 /* interval */
1856 SET_H2CCMD_MCC_TIME_SETTING_INTERVAL(cmd, mccobjpriv->interval);
1857 /* Early time to inform driver by C2H before switch channel */
1858 SET_H2CCMD_MCC_TIME_SETTING_EARLY_SWITCH_RPT(cmd, swchannel_early_time);
1859 }
1860
1861 #ifdef CONFIG_MCC_MODE_DEBUG
1862 {
1863 u8 i = 0;
1864
1865 RTW_INFO("=========================\n");
1866 RTW_INFO("NoA:\n");
1867 for (i = 0; i < H2C_MCC_TIME_SETTING_LEN; i++)
1868 pr_dbg("0x%x ", cmd[i]);
1869 pr_dbg("\n");
1870 RTW_INFO("=========================\n");
1871 }
1872 #endif /* CONFIG_MCC_MODE_DEBUG */
1873
1874 rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_TIME_SETTING, H2C_MCC_TIME_SETTING_LEN, cmd);
1875 }
1876
1877 #ifndef CONFIG_MCC_MODE_V2
rtw_hal_set_mcc_IQK_offload_cmd(PADAPTER padapter)1878 static void rtw_hal_set_mcc_IQK_offload_cmd(PADAPTER padapter)
1879 {
1880 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1881 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
1882 struct mcc_adapter_priv *pmccadapriv = NULL;
1883 _adapter *iface = NULL;
1884 u8 cmd[H2C_MCC_IQK_PARAM_LEN] = {0}, bready = 0, i = 0, order = 0;
1885 u16 TX_X = 0, TX_Y = 0, RX_X = 0, RX_Y = 0;
1886 u8 total_rf_path = GET_HAL_SPEC(padapter)->rf_reg_path_num;
1887 u8 rf_path_idx = 0, last_order = MAX_MCC_NUM - 1, last_rf_path_index = total_rf_path - 1;
1888
1889 /* by order, last order & last_rf_path_index must set ready bit = 1 */
1890 for (i = 0; i < MAX_MCC_NUM; i++) {
1891 iface = pmccobjpriv->iface[i];
1892 if (iface == NULL)
1893 continue;
1894
1895 pmccadapriv = &iface->mcc_adapterpriv;
1896 order = pmccadapriv->order;
1897
1898 for (rf_path_idx = 0; rf_path_idx < total_rf_path; rf_path_idx ++) {
1899
1900 _rtw_memset(cmd, 0, H2C_MCC_IQK_PARAM_LEN);
1901 TX_X = pmccadapriv->mcc_iqk_arr[rf_path_idx].TX_X & 0x7ff;/* [10:0] */
1902 TX_Y = pmccadapriv->mcc_iqk_arr[rf_path_idx].TX_Y & 0x7ff;/* [10:0] */
1903 RX_X = pmccadapriv->mcc_iqk_arr[rf_path_idx].RX_X & 0x3ff;/* [9:0] */
1904 RX_Y = pmccadapriv->mcc_iqk_arr[rf_path_idx].RX_Y & 0x3ff;/* [9:0] */
1905
1906 /* ready or not */
1907 if (order == last_order && rf_path_idx == last_rf_path_index)
1908 bready = 1;
1909 else
1910 bready = 0;
1911
1912 SET_H2CCMD_MCC_IQK_READY(cmd, bready);
1913 SET_H2CCMD_MCC_IQK_ORDER(cmd, order);
1914 SET_H2CCMD_MCC_IQK_PATH(cmd, rf_path_idx);
1915
1916 /* fill RX_X[7:0] to (cmd+1)[7:0] bitlen=8 */
1917 SET_H2CCMD_MCC_IQK_RX_L(cmd, (u8)(RX_X & 0xff));
1918 /* fill RX_X[9:8] to (cmd+2)[1:0] bitlen=2 */
1919 SET_H2CCMD_MCC_IQK_RX_M1(cmd, (u8)((RX_X >> 8) & 0x03));
1920 /* fill RX_Y[5:0] to (cmd+2)[7:2] bitlen=6 */
1921 SET_H2CCMD_MCC_IQK_RX_M2(cmd, (u8)(RX_Y & 0x3f));
1922 /* fill RX_Y[9:6] to (cmd+3)[3:0] bitlen=4 */
1923 SET_H2CCMD_MCC_IQK_RX_H(cmd, (u8)((RX_Y >> 6) & 0x0f));
1924
1925
1926 /* fill TX_X[7:0] to (cmd+4)[7:0] bitlen=8 */
1927 SET_H2CCMD_MCC_IQK_TX_L(cmd, (u8)(TX_X & 0xff));
1928 /* fill TX_X[10:8] to (cmd+5)[2:0] bitlen=3 */
1929 SET_H2CCMD_MCC_IQK_TX_M1(cmd, (u8)((TX_X >> 8) & 0x07));
1930 /* fill TX_Y[4:0] to (cmd+5)[7:3] bitlen=5 */
1931 SET_H2CCMD_MCC_IQK_TX_M2(cmd, (u8)(TX_Y & 0x1f));
1932 /* fill TX_Y[10:5] to (cmd+6)[5:0] bitlen=6 */
1933 SET_H2CCMD_MCC_IQK_TX_H(cmd, (u8)((TX_Y >> 5) & 0x3f));
1934
1935 #ifdef CONFIG_MCC_MODE_DEBUG
1936 RTW_INFO("=========================\n");
1937 RTW_INFO(FUNC_ADPT_FMT" IQK:\n", FUNC_ADPT_ARG(iface));
1938 RTW_INFO("TX_X: 0x%02x\n", TX_X);
1939 RTW_INFO("TX_Y: 0x%02x\n", TX_Y);
1940 RTW_INFO("RX_X: 0x%02x\n", RX_X);
1941 RTW_INFO("RX_Y: 0x%02x\n", RX_Y);
1942 RTW_INFO("cmd[0]:0x%02x\n", cmd[0]);
1943 RTW_INFO("cmd[1]:0x%02x\n", cmd[1]);
1944 RTW_INFO("cmd[2]:0x%02x\n", cmd[2]);
1945 RTW_INFO("cmd[3]:0x%02x\n", cmd[3]);
1946 RTW_INFO("cmd[4]:0x%02x\n", cmd[4]);
1947 RTW_INFO("cmd[5]:0x%02x\n", cmd[5]);
1948 RTW_INFO("cmd[6]:0x%02x\n", cmd[6]);
1949 RTW_INFO("=========================\n");
1950 #endif /* CONFIG_MCC_MODE_DEBUG */
1951
1952 rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_IQK_PARAM, H2C_MCC_IQK_PARAM_LEN, cmd);
1953 }
1954 }
1955 }
1956 #endif
1957
1958
rtw_hal_set_mcc_macid_cmd(PADAPTER padapter)1959 static void rtw_hal_set_mcc_macid_cmd(PADAPTER padapter)
1960 {
1961 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1962 struct mcc_adapter_priv *pmccadapriv = NULL;
1963 _adapter *iface = NULL;
1964 u8 cmd[H2C_MCC_MACID_BITMAP_LEN] = {0}, i = 0, order = 0;
1965 u16 bitmap = 0;
1966
1967 for (i = 0; i < dvobj->iface_nums; i++) {
1968 iface = dvobj->padapters[i];
1969 if (iface == NULL)
1970 continue;
1971
1972 pmccadapriv = &iface->mcc_adapterpriv;
1973 if (pmccadapriv->role == MCC_ROLE_MAX)
1974 continue;
1975
1976 order = pmccadapriv->order;
1977 bitmap = pmccadapriv->mcc_macid_bitmap;
1978
1979 if (order >= (H2C_MCC_MACID_BITMAP_LEN/2)) {
1980 RTW_INFO(FUNC_ADPT_FMT" only support 3 interface at most(%d)\n"
1981 , FUNC_ADPT_ARG(padapter), order);
1982 continue;
1983 }
1984 SET_H2CCMD_MCC_MACID_BITMAP_L((cmd + order * 2), (u8)(bitmap & 0xff));
1985 SET_H2CCMD_MCC_MACID_BITMAP_H((cmd + order * 2), (u8)((bitmap >> 8) & 0xff));
1986 }
1987
1988 #ifdef CONFIG_MCC_MODE_DEBUG
1989 RTW_INFO("=========================\n");
1990 RTW_INFO("MACID BITMAP: ");
1991 for (i = 0; i < H2C_MCC_MACID_BITMAP_LEN; i++)
1992 printk("0x%x ", cmd[i]);
1993 printk("\n");
1994 RTW_INFO("=========================\n");
1995 #endif /* CONFIG_MCC_MODE_DEBUG */
1996 rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_MACID_BITMAP, H2C_MCC_MACID_BITMAP_LEN, cmd);
1997 }
1998
1999 #ifdef CONFIG_MCC_MODE_V2
get_pri_ch_idx_by_adapter(u8 center_ch,u8 channel,u8 bw,u8 ch_offset40)2000 static u8 get_pri_ch_idx_by_adapter(u8 center_ch, u8 channel, u8 bw, u8 ch_offset40)
2001 {
2002 u8 pri_ch_idx = 0, chnl_offset80 = 0;
2003
2004 if (bw == CHANNEL_WIDTH_80) {
2005 if (center_ch > channel)
2006 chnl_offset80 = HAL_PRIME_CHNL_OFFSET_LOWER;
2007 else if (center_ch < channel)
2008 chnl_offset80 = HAL_PRIME_CHNL_OFFSET_UPPER;
2009 else
2010 chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2011 }
2012
2013 if (bw == CHANNEL_WIDTH_80) {
2014 /* primary channel is at lower subband of 80MHz & 40MHz */
2015 if ((ch_offset40 == HAL_PRIME_CHNL_OFFSET_LOWER) && (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_LOWER))
2016 pri_ch_idx = VHT_DATA_SC_20_LOWEST_OF_80MHZ;
2017 /* primary channel is at lower subband of 80MHz & upper subband of 40MHz */
2018 else if ((ch_offset40 == HAL_PRIME_CHNL_OFFSET_UPPER) && (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_LOWER))
2019 pri_ch_idx = VHT_DATA_SC_20_LOWER_OF_80MHZ;
2020 /* primary channel is at upper subband of 80MHz & lower subband of 40MHz */
2021 else if ((ch_offset40 == HAL_PRIME_CHNL_OFFSET_LOWER) && (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_UPPER))
2022 pri_ch_idx = VHT_DATA_SC_20_UPPER_OF_80MHZ;
2023 /* primary channel is at upper subband of 80MHz & upper subband of 40MHz */
2024 else if ((ch_offset40 == HAL_PRIME_CHNL_OFFSET_UPPER) && (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_UPPER))
2025 pri_ch_idx = VHT_DATA_SC_20_UPPERST_OF_80MHZ;
2026 else {
2027 if (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_LOWER)
2028 pri_ch_idx = VHT_DATA_SC_40_LOWER_OF_80MHZ;
2029 else if (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_UPPER)
2030 pri_ch_idx = VHT_DATA_SC_40_UPPER_OF_80MHZ;
2031 else
2032 RTW_INFO("SCMapping: DONOT CARE Mode Setting\n");
2033 }
2034 } else if (bw == CHANNEL_WIDTH_40) {
2035 /* primary channel is at upper subband of 40MHz */
2036 if (ch_offset40== HAL_PRIME_CHNL_OFFSET_UPPER)
2037 pri_ch_idx = VHT_DATA_SC_20_UPPER_OF_80MHZ;
2038 /* primary channel is at lower subband of 40MHz */
2039 else if (ch_offset40 == HAL_PRIME_CHNL_OFFSET_LOWER)
2040 pri_ch_idx = VHT_DATA_SC_20_LOWER_OF_80MHZ;
2041 else
2042 RTW_INFO("SCMapping: DONOT CARE Mode Setting\n");
2043 }
2044
2045 return pri_ch_idx;
2046 }
2047
rtw_hal_set_mcc_ctrl_cmd_v2(PADAPTER padapter,u8 stop)2048 static void rtw_hal_set_mcc_ctrl_cmd_v2(PADAPTER padapter, u8 stop)
2049 {
2050 u8 cmd[H2C_MCC_CTRL_LEN] = {0}, i = 0;
2051 u8 order = 0, totalnum = 0;
2052 u8 center_ch = 0, pri_ch_idx = 0, bw = 0;
2053 u8 duration = 0, role = 0, incurch = 0, rfetype = 0, distxnull = 0, c2hrpt = 0;
2054 u8 dis_sw_retry = 0, null_early_time=2, tsfx = 0, update_parm = 0;
2055 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2056 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
2057 struct mcc_adapter_priv *mccadapriv = NULL;
2058 struct mlme_ext_priv *pmlmeext = NULL;
2059 struct mlme_ext_info *pmlmeinfo = NULL;
2060 _adapter *iface = NULL;
2061
2062 RTW_INFO(FUNC_ADPT_FMT": stop=%d\n", FUNC_ADPT_ARG(padapter), stop);
2063
2064 for (i = 0; i < MAX_MCC_NUM; i++) {
2065 iface = pmccobjpriv->iface[i];
2066 if (iface == NULL)
2067 continue;
2068
2069 if (stop) {
2070 if (iface != padapter)
2071 continue;
2072 }
2073
2074 mccadapriv = &iface->mcc_adapterpriv;
2075 order = mccadapriv->order;
2076
2077 if (!stop)
2078 totalnum = MAX_MCC_NUM;
2079 else
2080 totalnum = 0xff; /* 0xff means stop */
2081
2082 pmlmeext = &iface->mlmeextpriv;
2083 center_ch = rtw_get_center_ch(pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
2084 pri_ch_idx = get_pri_ch_idx_by_adapter(center_ch, pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
2085 bw = pmlmeext->cur_bwmode;
2086 duration = mccadapriv->mcc_duration;
2087 role = mccadapriv->role;
2088
2089 incurch = _FALSE;
2090 dis_sw_retry = _TRUE;
2091
2092 /* STA/GC TX NULL data to inform AP/GC for ps mode */
2093 switch (role) {
2094 case MCC_ROLE_GO:
2095 case MCC_ROLE_AP:
2096 distxnull = MCC_DISABLE_TX_NULL;
2097 break;
2098 case MCC_ROLE_GC:
2099 set_channel_bwmode(iface, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
2100 distxnull = MCC_ENABLE_TX_NULL;
2101 break;
2102 case MCC_ROLE_STA:
2103 distxnull = MCC_ENABLE_TX_NULL;
2104 break;
2105 }
2106
2107 null_early_time = mccadapriv->null_early;
2108
2109 c2hrpt = MCC_C2H_REPORT_ALL_STATUS;
2110 tsfx = rtw_hal_get_port(iface);
2111 update_parm = 0;
2112
2113 SET_H2CCMD_MCC_CTRL_V2_ORDER(cmd, order);
2114 SET_H2CCMD_MCC_CTRL_V2_TOTALNUM(cmd, totalnum);
2115 SET_H2CCMD_MCC_CTRL_V2_CENTRAL_CH(cmd, center_ch);
2116 SET_H2CCMD_MCC_CTRL_V2_PRIMARY_CH(cmd, pri_ch_idx);
2117 SET_H2CCMD_MCC_CTRL_V2_BW(cmd, bw);
2118 SET_H2CCMD_MCC_CTRL_V2_DURATION(cmd, duration);
2119 SET_H2CCMD_MCC_CTRL_V2_ROLE(cmd, role);
2120 SET_H2CCMD_MCC_CTRL_V2_INCURCH(cmd, incurch);
2121 SET_H2CCMD_MCC_CTRL_V2_DIS_SW_RETRY(cmd, dis_sw_retry);
2122 SET_H2CCMD_MCC_CTRL_V2_DISTXNULL(cmd, distxnull);
2123 SET_H2CCMD_MCC_CTRL_V2_C2HRPT(cmd, c2hrpt);
2124 SET_H2CCMD_MCC_CTRL_V2_TSFX(cmd, tsfx);
2125 SET_H2CCMD_MCC_CTRL_V2_NULL_EARLY(cmd, null_early_time);
2126 SET_H2CCMD_MCC_CTRL_V2_UPDATE_PARM(cmd, update_parm);
2127
2128 #ifdef CONFIG_MCC_MODE_DEBUG
2129 RTW_INFO("=========================\n");
2130 RTW_INFO(FUNC_ADPT_FMT" MCC INFO:\n", FUNC_ADPT_ARG(iface));
2131 RTW_INFO("cmd[0]:0x%02x\n", cmd[0]);
2132 RTW_INFO("cmd[1]:0x%02x\n", cmd[1]);
2133 RTW_INFO("cmd[2]:0x%02x\n", cmd[2]);
2134 RTW_INFO("cmd[3]:0x%02x\n", cmd[3]);
2135 RTW_INFO("cmd[4]:0x%02x\n", cmd[4]);
2136 RTW_INFO("cmd[5]:0x%02x\n", cmd[5]);
2137 RTW_INFO("cmd[6]:0x%02x\n", cmd[6]);
2138 RTW_INFO("=========================\n");
2139 #endif /* CONFIG_MCC_MODE_DEBUG */
2140
2141 rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_CTRL_V2, H2C_MCC_CTRL_LEN, cmd);
2142 }
2143 }
2144
2145 #else
rtw_hal_set_mcc_ctrl_cmd_v1(PADAPTER padapter,u8 stop)2146 static void rtw_hal_set_mcc_ctrl_cmd_v1(PADAPTER padapter, u8 stop)
2147 {
2148 u8 cmd[H2C_MCC_CTRL_LEN] = {0}, i = 0;
2149 u8 order = 0, totalnum = 0, chidx = 0, bw = 0, bw40sc = 0, bw80sc = 0;
2150 u8 duration = 0, role = 0, incurch = 0, rfetype = 0, distxnull = 0, c2hrpt = 0, chscan = 0;
2151 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2152 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
2153 struct mcc_adapter_priv *mccadapriv = NULL;
2154 struct mlme_ext_priv *pmlmeext = NULL;
2155 struct mlme_ext_info *pmlmeinfo = NULL;
2156 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
2157 _adapter *iface = NULL;
2158
2159 RTW_INFO(FUNC_ADPT_FMT": stop=%d\n", FUNC_ADPT_ARG(padapter), stop);
2160
2161 for (i = 0; i < MAX_MCC_NUM; i++) {
2162 iface = pmccobjpriv->iface[i];
2163 if (iface == NULL)
2164 continue;
2165
2166 if (stop) {
2167 if (iface != padapter)
2168 continue;
2169 }
2170
2171 mccadapriv = &iface->mcc_adapterpriv;
2172 order = mccadapriv->order;
2173
2174 if (!stop)
2175 totalnum = MAX_MCC_NUM;
2176 else
2177 totalnum = 0xff; /* 0xff means stop */
2178
2179 pmlmeext = &iface->mlmeextpriv;
2180 chidx = pmlmeext->cur_channel;
2181 bw = pmlmeext->cur_bwmode;
2182 bw40sc = pmlmeext->cur_ch_offset;
2183
2184 /* decide 80 band width offset */
2185 if (bw == CHANNEL_WIDTH_80) {
2186 u8 center_ch = rtw_get_center_ch(chidx, bw, bw40sc);
2187
2188 if (center_ch > chidx)
2189 bw80sc = HAL_PRIME_CHNL_OFFSET_LOWER;
2190 else if (center_ch < chidx)
2191 bw80sc = HAL_PRIME_CHNL_OFFSET_UPPER;
2192 else
2193 bw80sc = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2194 } else
2195 bw80sc = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2196
2197 duration = mccadapriv->mcc_duration;
2198 role = mccadapriv->role;
2199
2200 incurch = _FALSE;
2201
2202 if (IS_HARDWARE_TYPE_8812(padapter))
2203 rfetype = pHalData->rfe_type; /* RFETYPE (only for 8812)*/
2204 else
2205 rfetype = 0;
2206
2207 /* STA/GC TX NULL data to inform AP/GC for ps mode */
2208 switch (role) {
2209 case MCC_ROLE_GO:
2210 case MCC_ROLE_AP:
2211 distxnull = MCC_DISABLE_TX_NULL;
2212 break;
2213 case MCC_ROLE_GC:
2214 case MCC_ROLE_STA:
2215 distxnull = MCC_ENABLE_TX_NULL;
2216 break;
2217 }
2218
2219 c2hrpt = MCC_C2H_REPORT_ALL_STATUS;
2220 chscan = MCC_CHIDX;
2221
2222 SET_H2CCMD_MCC_CTRL_ORDER(cmd, order);
2223 SET_H2CCMD_MCC_CTRL_TOTALNUM(cmd, totalnum);
2224 SET_H2CCMD_MCC_CTRL_CHIDX(cmd, chidx);
2225 SET_H2CCMD_MCC_CTRL_BW(cmd, bw);
2226 SET_H2CCMD_MCC_CTRL_BW40SC(cmd, bw40sc);
2227 SET_H2CCMD_MCC_CTRL_BW80SC(cmd, bw80sc);
2228 SET_H2CCMD_MCC_CTRL_DURATION(cmd, duration);
2229 SET_H2CCMD_MCC_CTRL_ROLE(cmd, role);
2230 SET_H2CCMD_MCC_CTRL_INCURCH(cmd, incurch);
2231 SET_H2CCMD_MCC_CTRL_RFETYPE(cmd, rfetype);
2232 SET_H2CCMD_MCC_CTRL_DISTXNULL(cmd, distxnull);
2233 SET_H2CCMD_MCC_CTRL_C2HRPT(cmd, c2hrpt);
2234 SET_H2CCMD_MCC_CTRL_CHSCAN(cmd, chscan);
2235
2236 #ifdef CONFIG_MCC_MODE_DEBUG
2237 RTW_INFO("=========================\n");
2238 RTW_INFO(FUNC_ADPT_FMT" MCC INFO:\n", FUNC_ADPT_ARG(iface));
2239 RTW_INFO("cmd[0]:0x%02x\n", cmd[0]);
2240 RTW_INFO("cmd[1]:0x%02x\n", cmd[1]);
2241 RTW_INFO("cmd[2]:0x%02x\n", cmd[2]);
2242 RTW_INFO("cmd[3]:0x%02x\n", cmd[3]);
2243 RTW_INFO("cmd[4]:0x%02x\n", cmd[4]);
2244 RTW_INFO("cmd[5]:0x%02x\n", cmd[5]);
2245 RTW_INFO("cmd[6]:0x%02x\n", cmd[6]);
2246 RTW_INFO("=========================\n");
2247 #endif /* CONFIG_MCC_MODE_DEBUG */
2248
2249 rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_CTRL, H2C_MCC_CTRL_LEN, cmd);
2250 }
2251 }
2252 #endif
2253
rtw_hal_set_mcc_ctrl_cmd(PADAPTER padapter,u8 stop)2254 static void rtw_hal_set_mcc_ctrl_cmd(PADAPTER padapter, u8 stop)
2255 {
2256 #ifdef CONFIG_MCC_MODE_V2
2257 /* new cmd 0x17 */
2258 rtw_hal_set_mcc_ctrl_cmd_v2(padapter, stop);
2259 #else
2260 /* old cmd 0x18 */
2261 rtw_hal_set_mcc_ctrl_cmd_v1(padapter, stop);
2262 #endif
2263 }
2264
check_mcc_support(PADAPTER adapter)2265 static u8 check_mcc_support(PADAPTER adapter)
2266 {
2267 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
2268 u8 sta_linked_num = DEV_STA_LD_NUM(dvobj);
2269 u8 starting_ap_num = DEV_AP_STARTING_NUM(dvobj);
2270 u8 ap_num = DEV_AP_NUM(dvobj);
2271 u8 ret = _FAIL;
2272
2273 RTW_INFO("[MCC] sta_linked_num=%d, starting_ap_num=%d,ap_num=%d\n",
2274 sta_linked_num, starting_ap_num, ap_num);
2275
2276 /* case for sta + sta case */
2277 if (sta_linked_num == MAX_MCC_NUM) {
2278 ret = _SUCCESS;
2279 goto exit;
2280 }
2281
2282 /* case for starting AP + linked sta */
2283 if ((starting_ap_num + sta_linked_num) == MAX_MCC_NUM) {
2284 ret = _SUCCESS;
2285 goto exit;
2286 }
2287
2288 /* case for started AP + linked sta */
2289 if ((ap_num + sta_linked_num) == MAX_MCC_NUM) {
2290 ret = _SUCCESS;
2291 goto exit;
2292 }
2293
2294 exit:
2295 return ret;
2296 }
2297
rtw_hal_mcc_start_prehdl(PADAPTER padapter)2298 static void rtw_hal_mcc_start_prehdl(PADAPTER padapter)
2299 {
2300 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2301 _adapter *iface = NULL;
2302 struct mcc_adapter_priv *mccadapriv = NULL;
2303 u8 i = 1;
2304
2305 for (i = 0; i < dvobj->iface_nums; i++) {
2306 iface = dvobj->padapters[i];
2307 if (iface == NULL)
2308 continue;
2309
2310 mccadapriv = &iface->mcc_adapterpriv;
2311 mccadapriv->role = MCC_ROLE_MAX;
2312 }
2313
2314 #ifdef CONFIG_RTL8822C
2315 if (IS_HARDWARE_TYPE_8822C(padapter)) {
2316 HAL_DATA_TYPE *hal = GET_HAL_DATA(padapter);
2317 struct dm_struct *dm = &hal->odmpriv;
2318
2319 odm_cmn_info_update(dm, ODM_CMNINFO_IS_DOWNLOAD_FW, hal->bFWReady);
2320 }
2321 #endif
2322 }
2323
rtw_hal_set_mcc_start_setting(PADAPTER padapter,u8 status)2324 static u8 rtw_hal_set_mcc_start_setting(PADAPTER padapter, u8 status)
2325 {
2326 u8 ret = _SUCCESS, enable_tsf_auto_sync = _FALSE;
2327 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2328 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
2329
2330 if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
2331 rtw_warn_on(1);
2332 RTW_INFO("PS mode is not active before start mcc, force exit ps mode\n");
2333 LeaveAllPowerSaveModeDirect(padapter);
2334 }
2335
2336 if (check_mcc_support(padapter) == _FAIL) {
2337 ret = _FAIL;
2338 goto exit;
2339 }
2340
2341 rtw_hal_mcc_start_prehdl(padapter);
2342
2343 /* configure mcc switch channel setting */
2344 rtw_hal_config_mcc_switch_channel_setting(padapter);
2345
2346 if (rtw_hal_decide_mcc_role(padapter) == _FAIL) {
2347 ret = _FAIL;
2348 goto exit;
2349 }
2350
2351 /* set mcc status to indicate process mcc start setting */
2352 rtw_hal_set_mcc_status(padapter, MCC_STATUS_PROCESS_MCC_START_SETTING);
2353
2354 /* only download rsvd page for connect */
2355 if (status == MCC_SETCMD_STATUS_START_CONNECT) {
2356 /* download mcc rsvd page */
2357 rtw_hal_set_fw_mcc_rsvd_page(padapter);
2358 rtw_hal_set_mcc_rsvdpage_cmd(padapter);
2359 }
2360
2361 /* configure time setting */
2362 rtw_hal_set_mcc_time_setting_cmd(padapter);
2363
2364 #ifndef CONFIG_MCC_MODE_V2
2365 /* IQK value offload */
2366 rtw_hal_set_mcc_IQK_offload_cmd(padapter);
2367 #endif
2368
2369 /* set mac id to fw */
2370 rtw_hal_set_mcc_macid_cmd(padapter);
2371 #ifdef CONFIG_HW_P0_TSF_SYNC
2372 if (dvobj->p0_tsf.sync_port != MAX_HW_PORT ) {
2373 /* disable tsf auto sync */
2374 RTW_INFO("[MCC] disable HW TSF sync\n");
2375 rtw_hal_set_hwreg(padapter, HW_VAR_TSF_AUTO_SYNC, &enable_tsf_auto_sync);
2376 } else {
2377 RTW_INFO("[MCC] already disable HW TSF sync\n");
2378 }
2379 #endif
2380 /* set mcc parameter */
2381 rtw_hal_set_mcc_ctrl_cmd(padapter, _FALSE);
2382
2383 exit:
2384 return ret;
2385 }
2386
rtw_hal_set_mcc_stop_setting(PADAPTER padapter,u8 status)2387 static void rtw_hal_set_mcc_stop_setting(PADAPTER padapter, u8 status)
2388 {
2389 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2390 struct mcc_obj_priv *mccobjpriv = &dvobj->mcc_objpriv;
2391 _adapter *iface = NULL;
2392 struct mcc_adapter_priv *mccadapriv = NULL;
2393 u8 i = 0;
2394 /*
2395 * when adapter disconnect, stop mcc mod
2396 * total=0xf means stop mcc mode
2397 */
2398
2399 switch (status) {
2400 default:
2401 /* let fw switch to other interface channel */
2402 for (i = 0; i < MAX_MCC_NUM; i++) {
2403 iface = mccobjpriv->iface[i];
2404 if (iface == NULL)
2405 continue;
2406
2407 mccadapriv = &iface->mcc_adapterpriv;
2408
2409 /* use other interface to set cmd */
2410 if (iface != padapter) {
2411 rtw_hal_set_mcc_ctrl_cmd(iface, _TRUE);
2412 break;
2413 }
2414 }
2415 break;
2416 }
2417 }
2418
rtw_hal_mcc_status_hdl(PADAPTER padapter,u8 status)2419 static void rtw_hal_mcc_status_hdl(PADAPTER padapter, u8 status)
2420 {
2421 switch (status) {
2422 case MCC_SETCMD_STATUS_STOP_DISCONNECT:
2423 rtw_hal_clear_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC);
2424 break;
2425 case MCC_SETCMD_STATUS_STOP_SCAN_START:
2426 rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC);
2427 rtw_hal_clear_mcc_status(padapter, MCC_STATUS_DOING_MCC);
2428 break;
2429
2430 case MCC_SETCMD_STATUS_START_CONNECT:
2431 case MCC_SETCMD_STATUS_START_SCAN_DONE:
2432 rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC);
2433 break;
2434 default:
2435 RTW_INFO(FUNC_ADPT_FMT" error status(%d)\n", FUNC_ADPT_ARG(padapter), status);
2436 break;
2437 }
2438 }
2439
rtw_hal_mcc_stop_posthdl(PADAPTER padapter)2440 static void rtw_hal_mcc_stop_posthdl(PADAPTER padapter)
2441 {
2442 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2443 struct mcc_obj_priv *mccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2444 struct mcc_adapter_priv *mccadapriv = NULL;
2445 _adapter *iface = NULL;
2446 PHAL_DATA_TYPE hal;
2447 u8 i = 0;
2448 u8 enable_rx_bar = _FALSE;
2449
2450 hal = GET_HAL_DATA(padapter);
2451
2452 for (i = 0; i < MAX_MCC_NUM; i++) {
2453 iface = mccobjpriv->iface[i];
2454 if (iface == NULL)
2455 continue;
2456
2457 /* release network queue */
2458 rtw_netif_wake_queue(iface->pnetdev);
2459 mccadapriv = &iface->mcc_adapterpriv;
2460 mccadapriv->mcc_tx_bytes_from_kernel = 0;
2461 mccadapriv->mcc_last_tx_bytes_from_kernel = 0;
2462 mccadapriv->mcc_tx_bytes_to_port = 0;
2463
2464 if (mccadapriv->role == MCC_ROLE_GO)
2465 rtw_hal_mcc_remove_go_p2p_ie(iface);
2466
2467 #ifdef CONFIG_TDLS
2468 if (MLME_IS_STA(iface)) {
2469 if (mccadapriv->backup_tdls_en) {
2470 rtw_enable_tdls_func(iface);
2471 RTW_INFO("%s: Disable MCC, Enable TDLS\n", __func__);
2472 mccadapriv->backup_tdls_en = _FALSE;
2473 }
2474 }
2475 #endif /* CONFIG_TDLS */
2476
2477 mccadapriv->role = MCC_ROLE_MAX;
2478 mccobjpriv->iface[i] = NULL;
2479 }
2480
2481 /* force switch channel */
2482 hal->current_channel = 0;
2483 hal->current_channel_bw = CHANNEL_WIDTH_MAX;
2484 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
2485 rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_STOP, NULL);
2486 #endif
2487
2488 #ifdef CONFIG_RTL8822C
2489 if (IS_HARDWARE_TYPE_8822C(padapter)) {
2490 HAL_DATA_TYPE *hal = GET_HAL_DATA(padapter);
2491 struct dm_struct *dm = &hal->odmpriv;
2492
2493 odm_cmn_info_update(dm, ODM_CMNINFO_IS_DOWNLOAD_FW, _FALSE);
2494 }
2495 #endif
2496 }
2497
rtw_hal_mcc_start_posthdl(PADAPTER padapter)2498 static void rtw_hal_mcc_start_posthdl(PADAPTER padapter)
2499 {
2500 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2501 struct mcc_obj_priv *mccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2502 struct mcc_adapter_priv *mccadapriv = NULL;
2503 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
2504 _adapter *iface = NULL;
2505 u8 i = 0, order = 0;
2506 u8 enable_rx_bar = _TRUE;
2507
2508 for (i = 0; i < MAX_MCC_NUM; i++) {
2509 iface = mccobjpriv->iface[i];
2510 if (iface == NULL)
2511 continue;
2512
2513 mccadapriv = &iface->mcc_adapterpriv;
2514 if (mccadapriv->role == MCC_ROLE_MAX)
2515 continue;
2516
2517 mccadapriv->mcc_tx_bytes_from_kernel = 0;
2518 mccadapriv->mcc_last_tx_bytes_from_kernel = 0;
2519 mccadapriv->mcc_tx_bytes_to_port = 0;
2520
2521 #ifdef CONFIG_TDLS
2522 if (MLME_IS_STA(iface)) {
2523 if (rtw_is_tdls_enabled(iface)) {
2524 mccadapriv->backup_tdls_en = _TRUE;
2525 rtw_disable_tdls_func(iface, _TRUE);
2526 RTW_INFO("%s: Enable MCC, Disable TDLS\n", __func__);
2527 }
2528 }
2529 #endif /* CONFIG_TDLS */
2530 }
2531 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
2532 rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_START, NULL);
2533 #endif
2534 }
2535
2536 /*
2537 * rtw_hal_set_mcc_setting - set mcc setting
2538 * @padapter: currnet padapter to stop/start MCC
2539 * @stop: stop mcc or not
2540 * @return val: 1 for SUCCESS, 0 for fail
2541 */
rtw_hal_set_mcc_setting(PADAPTER padapter,u8 status)2542 static u8 rtw_hal_set_mcc_setting(PADAPTER padapter, u8 status)
2543 {
2544 u8 ret = _FAIL;
2545 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2546 u8 stop = (status < MCC_SETCMD_STATUS_START_CONNECT) ? _TRUE : _FALSE;
2547 systime start_time = rtw_get_current_time();
2548
2549 RTW_INFO("===> "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
2550
2551 rtw_sctx_init(&pmccobjpriv->mcc_sctx, MCC_EXPIRE_TIME);
2552 pmccobjpriv->mcc_c2h_status = MCC_RPT_MAX;
2553
2554 if (stop == _FALSE) {
2555 /* handle mcc start */
2556 if (rtw_hal_set_mcc_start_setting(padapter, status) == _FAIL)
2557 goto exit;
2558
2559 /* wait for C2H */
2560 if (!rtw_sctx_wait(&pmccobjpriv->mcc_sctx, __func__))
2561 RTW_INFO(FUNC_ADPT_FMT": wait for mcc start C2H time out\n", FUNC_ADPT_ARG(padapter));
2562 else
2563 ret = _SUCCESS;
2564
2565 if (ret == _SUCCESS) {
2566 RTW_INFO(FUNC_ADPT_FMT": mcc start sucecssfully\n", FUNC_ADPT_ARG(padapter));
2567 rtw_hal_mcc_status_hdl(padapter, status);
2568 rtw_hal_mcc_start_posthdl(padapter);
2569 }
2570 } else {
2571
2572 /* set mcc status to indicate process mcc start setting */
2573 rtw_hal_set_mcc_status(padapter, MCC_STATUS_PROCESS_MCC_STOP_SETTING);
2574
2575 /* handle mcc stop */
2576 rtw_hal_set_mcc_stop_setting(padapter, status);
2577
2578 /* wait for C2H */
2579 if (!rtw_sctx_wait(&pmccobjpriv->mcc_sctx, __func__))
2580 RTW_INFO(FUNC_ADPT_FMT": wait for mcc stop C2H time out\n", FUNC_ADPT_ARG(padapter));
2581 else {
2582 ret = _SUCCESS;
2583 rtw_hal_mcc_status_hdl(padapter, status);
2584 rtw_hal_mcc_stop_posthdl(padapter);
2585 }
2586 }
2587
2588 exit:
2589 /* clear mcc status */
2590 rtw_hal_clear_mcc_status(padapter
2591 , MCC_STATUS_PROCESS_MCC_START_SETTING | MCC_STATUS_PROCESS_MCC_STOP_SETTING);
2592
2593 RTW_INFO(FUNC_ADPT_FMT" in %dms <===\n"
2594 , FUNC_ADPT_ARG(padapter), rtw_get_passing_time_ms(start_time));
2595 return ret;
2596 }
2597
2598 /**
2599 * rtw_hal_mcc_check_case_not_limit_traffic - handler flow ctrl for special case
2600 * @cur_iface: fw stay channel setting of this iface
2601 * @next_iface: fw will swich channel setting of this iface
2602 */
rtw_hal_mcc_check_case_not_limit_traffic(PADAPTER cur_iface,PADAPTER next_iface)2603 static void rtw_hal_mcc_check_case_not_limit_traffic(PADAPTER cur_iface, PADAPTER next_iface)
2604 {
2605 u8 cur_bw = cur_iface->mlmeextpriv.cur_bwmode;
2606 u8 next_bw = next_iface->mlmeextpriv.cur_bwmode;
2607
2608 /* for both interface are VHT80, doesn't limit_traffic according to iperf results */
2609 if (cur_bw == CHANNEL_WIDTH_80 && next_bw == CHANNEL_WIDTH_80) {
2610 cur_iface->mcc_adapterpriv.mcc_tp_limit = _FALSE;
2611 next_iface->mcc_adapterpriv.mcc_tp_limit = _FALSE;
2612 }
2613 }
2614
2615
2616 /**
2617 * rtw_hal_mcc_sw_ch_fw_notify_hdl - handler flow ctrl
2618 */
rtw_hal_mcc_sw_ch_fw_notify_hdl(PADAPTER padapter)2619 static void rtw_hal_mcc_sw_ch_fw_notify_hdl(PADAPTER padapter)
2620 {
2621 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
2622 struct mcc_obj_priv *pmccobjpriv = &(pdvobjpriv->mcc_objpriv);
2623 struct mcc_adapter_priv *cur_mccadapriv = NULL, *next_mccadapriv = NULL;
2624 _adapter *iface = NULL, *cur_iface = NULL, *next_iface = NULL;
2625 struct registry_priv *preg = &padapter->registrypriv;
2626 u8 cur_op_ch = pdvobjpriv->oper_channel;
2627 u8 i = 0, iface_num = pdvobjpriv->iface_nums, cur_order = 0, next_order = 0;
2628 static u8 cnt = 1;
2629 u32 single_tx_cri = preg->rtw_mcc_single_tx_cri;
2630
2631 for (i = 0; i < iface_num; i++) {
2632 iface = pdvobjpriv->padapters[i];
2633 if (iface == NULL)
2634 continue;
2635
2636 if (cur_op_ch == iface->mlmeextpriv.cur_channel) {
2637 cur_iface = iface;
2638 cur_mccadapriv = &cur_iface->mcc_adapterpriv;
2639 cur_order = cur_mccadapriv->order;
2640 next_order = (cur_order + 1) % iface_num;
2641 next_iface = pmccobjpriv->iface[next_order];
2642 next_mccadapriv = &next_iface->mcc_adapterpriv;
2643 break;
2644 }
2645 }
2646
2647 if (cur_iface == NULL || next_iface == NULL) {
2648 RTW_ERR("cur_iface=%p,next_iface=%p\n", cur_iface, next_iface);
2649 rtw_warn_on(1);
2650 return;
2651 }
2652
2653 /* check other interface tx busy traffic or not under every 2 switch channel notify(Mbits/100ms) */
2654 if (cnt == 2) {
2655 cur_mccadapriv->mcc_tp = (cur_mccadapriv->mcc_tx_bytes_from_kernel
2656 - cur_mccadapriv->mcc_last_tx_bytes_from_kernel) * 10 * 8 / 1024 / 1024;
2657 cur_mccadapriv->mcc_last_tx_bytes_from_kernel = cur_mccadapriv->mcc_tx_bytes_from_kernel;
2658
2659 next_mccadapriv->mcc_tp = (next_mccadapriv->mcc_tx_bytes_from_kernel
2660 - next_mccadapriv->mcc_last_tx_bytes_from_kernel) * 10 * 8 / 1024 / 1024;
2661 next_mccadapriv->mcc_last_tx_bytes_from_kernel = next_mccadapriv->mcc_tx_bytes_from_kernel;
2662
2663 cnt = 1;
2664 } else
2665 cnt = 2;
2666
2667 /* check single TX or cuncurrnet TX */
2668 if (next_mccadapriv->mcc_tp < single_tx_cri) {
2669 /* single TX, does not stop */
2670 cur_mccadapriv->mcc_tx_stop = _FALSE;
2671 cur_mccadapriv->mcc_tp_limit = _FALSE;
2672 } else {
2673 /* concurrent TX, stop */
2674 cur_mccadapriv->mcc_tx_stop = _TRUE;
2675 cur_mccadapriv->mcc_tp_limit = _TRUE;
2676 }
2677
2678 if (cur_mccadapriv->mcc_tp < single_tx_cri) {
2679 next_mccadapriv->mcc_tx_stop = _FALSE;
2680 next_mccadapriv->mcc_tp_limit = _FALSE;
2681 } else {
2682 next_mccadapriv->mcc_tx_stop = _FALSE;
2683 next_mccadapriv->mcc_tp_limit = _TRUE;
2684 next_mccadapriv->mcc_tx_bytes_to_port = 0;
2685 }
2686
2687 /* stop current iface kernel queue or not */
2688 if (cur_mccadapriv->mcc_tx_stop)
2689 rtw_netif_stop_queue(cur_iface->pnetdev);
2690 else
2691 rtw_netif_wake_queue(cur_iface->pnetdev);
2692
2693 /* stop next iface kernel queue or not */
2694 if (next_mccadapriv->mcc_tx_stop)
2695 rtw_netif_stop_queue(next_iface->pnetdev);
2696 else
2697 rtw_netif_wake_queue(next_iface->pnetdev);
2698
2699 /* start xmit tasklet */
2700 rtw_os_xmit_schedule(next_iface);
2701
2702 rtw_hal_mcc_check_case_not_limit_traffic(cur_iface, next_iface);
2703
2704 if (0) {
2705 RTW_INFO("order:%d, mcc_tx_stop:%d, mcc_tp:%d\n",
2706 cur_mccadapriv->order, cur_mccadapriv->mcc_tx_stop, cur_mccadapriv->mcc_tp);
2707 dump_os_queue(0, cur_iface);
2708 RTW_INFO("order:%d, mcc_tx_stop:%d, mcc_tp:%d\n",
2709 next_mccadapriv->order, next_mccadapriv->mcc_tx_stop, next_mccadapriv->mcc_tp);
2710 dump_os_queue(0, next_iface);
2711 }
2712 }
2713
rtw_hal_mcc_update_noa_start_time_hdl(PADAPTER padapter,u8 buflen,u8 * tmpBuf)2714 static void rtw_hal_mcc_update_noa_start_time_hdl(PADAPTER padapter, u8 buflen, u8 *tmpBuf)
2715 {
2716 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
2717 struct mcc_obj_priv *pmccobjpriv = &(pdvobjpriv->mcc_objpriv);
2718 struct mcc_adapter_priv *pmccadapriv = NULL;
2719 PADAPTER iface = NULL;
2720 u8 i = 0;
2721 u8 policy_idx = pmccobjpriv->policy_index;
2722 u8 noa_tsf_sync_offset = mcc_switch_channel_policy_table[policy_idx][MCC_TSF_SYNC_OFFSET_IDX];
2723 u8 noa_start_time_offset = mcc_switch_channel_policy_table[policy_idx][MCC_START_TIME_OFFSET_IDX];
2724
2725 for (i = 0; i < pdvobjpriv->iface_nums; i++) {
2726 iface = pdvobjpriv->padapters[i];
2727 if (iface == NULL)
2728 continue;
2729
2730 pmccadapriv = &iface->mcc_adapterpriv;
2731 if (pmccadapriv->role == MCC_ROLE_MAX)
2732 continue;
2733
2734 /* GO & channel match */
2735 if (pmccadapriv->role == MCC_ROLE_GO) {
2736 /* convert GO TBTT from FW to noa_start_time(TU convert to mircosecond) */
2737 pmccadapriv->noa_start_time = RTW_GET_LE32(tmpBuf + 2) + noa_start_time_offset * TU;
2738
2739 if (0) {
2740 RTW_INFO("TBTT:0x%02x\n", RTW_GET_LE32(tmpBuf + 2));
2741 RTW_INFO("noa_tsf_sync_offset:%d, noa_start_time_offset:%d\n", noa_tsf_sync_offset, noa_start_time_offset);
2742 RTW_INFO(FUNC_ADPT_FMT"buf=0x%02x:0x%02x:0x%02x:0x%02x, noa_start_time=0x%02x\n"
2743 , FUNC_ADPT_ARG(iface)
2744 , tmpBuf[2]
2745 , tmpBuf[3]
2746 , tmpBuf[4]
2747 , tmpBuf[5]
2748 ,pmccadapriv->noa_start_time);
2749 }
2750
2751 rtw_hal_mcc_update_go_p2p_ie(iface);
2752
2753 break;
2754 }
2755 }
2756
2757 }
2758
mcc_get_reg_hdl(PADAPTER adapter,const u8 * val)2759 static u8 mcc_get_reg_hdl(PADAPTER adapter, const u8 *val)
2760 {
2761 struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
2762 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
2763 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
2764 _adapter *cur_iface = NULL;
2765 u8 ret = _SUCCESS;
2766 u8 cur_order = 0;
2767 #ifdef CONFIG_RTL8822C
2768 u16 dbg_reg[DBG_MCC_REG_NUM] = {0x4d4,0x522,0x1d70};
2769 #else
2770 u16 dbg_reg[DBG_MCC_REG_NUM] = {0x4d4,0x522,0xc50,0xe50};
2771 #endif
2772 u16 dbg_rf_reg[DBG_MCC_RF_REG_NUM] = {0x18};
2773 u8 i;
2774 u32 reg_val;
2775 u8 path = 0, path_nums = 0;
2776
2777 if (!rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) {
2778 ret = _FAIL;
2779 goto exit;
2780 }
2781
2782 if (!val)
2783 cur_order = 0xff;
2784 else
2785 cur_order = *val;
2786
2787 if (cur_order >= MAX_MCC_NUM && cur_order != 0xff) {
2788 RTW_ERR("%s: cur_order=%d\n", __func__, cur_order);
2789 ret = _FAIL;
2790 goto exit;
2791 }
2792
2793 path_nums = hal_spec->rf_reg_path_num;
2794 if (cur_order == 0xff)
2795 cur_iface = adapter;
2796 else
2797 cur_iface = mccobjpriv->iface[cur_order];
2798
2799 if (!cur_iface) {
2800 RTW_ERR("%s: cur_iface = NULL, cur_order=%d\n", __func__, cur_order);
2801 ret = _FAIL;
2802 goto exit;
2803 }
2804
2805 _enter_critical_mutex(&mccobjpriv->mcc_dbg_reg_mutex, NULL);
2806 if (!RTW_CANNOT_IO(adapter)) {
2807 /* RTW_INFO("=================================\n");
2808 RTW_INFO(ADPT_FMT": cur_order:%d\n", ADPT_ARG(cur_iface), cur_order); */
2809
2810 for (i = 0; i < ARRAY_SIZE(dbg_reg); i++) {
2811 reg_val = rtw_read32(adapter, dbg_reg[i]);
2812 mccobjpriv->dbg_reg[i] = dbg_reg[i];
2813 mccobjpriv->dbg_reg_val[i] = reg_val;
2814 /* RTW_PRINT("REG_%X:0x%08x\n", dbg_reg[i], reg_val); */
2815 }
2816 for (i = 0; i < ARRAY_SIZE(dbg_rf_reg); i++) {
2817 for (path = 0; path < path_nums; path++) {
2818 reg_val = rtw_hal_read_rfreg(adapter, path, dbg_rf_reg[i], 0xffffffff);
2819 /* RTW_PRINT("RF_PATH_%d_REG_%X:0x%08x\n",
2820 path, dbg_rf_reg[i], reg_val); */
2821 mccobjpriv->dbg_rf_reg[i] = dbg_rf_reg[i];
2822 mccobjpriv->dbg_rf_reg_val[i][path] = reg_val;
2823 }
2824 }
2825 }
2826 _exit_critical_mutex(&mccobjpriv->mcc_dbg_reg_mutex, NULL);
2827
2828 exit:
2829 return ret;
2830 }
2831
mcc_get_reg_cmd(_adapter * adapter,u8 cur_order)2832 static u8 mcc_get_reg_cmd(_adapter *adapter, u8 cur_order)
2833 {
2834 struct cmd_obj *cmdobj;
2835 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
2836 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2837 u8 *mcc_cur_order = NULL;
2838 u8 res = _SUCCESS;
2839
2840
2841 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2842 if (cmdobj == NULL) {
2843 res = _FAIL;
2844 goto exit;
2845 }
2846
2847 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2848 if (pdrvextra_cmd_parm == NULL) {
2849 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2850 res = _FAIL;
2851 goto exit;
2852 }
2853
2854 mcc_cur_order = rtw_zmalloc(sizeof(u8));
2855 if (mcc_cur_order == NULL) {
2856 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2857 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
2858 res = _FAIL;
2859 goto exit;
2860 }
2861
2862 pdrvextra_cmd_parm->ec_id = MCC_CMD_WK_CID;
2863 pdrvextra_cmd_parm->type = MCC_GET_DBG_REG_WK_CID;
2864 pdrvextra_cmd_parm->size = 1;
2865 pdrvextra_cmd_parm->pbuf = mcc_cur_order;
2866
2867 _rtw_memcpy(mcc_cur_order, &cur_order, 1);
2868
2869 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
2870 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2871
2872 exit:
2873 return res;
2874 }
2875
rtw_hal_mcc_rpt_tsf_hdl(PADAPTER padapter,u8 buflen,u8 * tmpBuf)2876 static void rtw_hal_mcc_rpt_tsf_hdl(PADAPTER padapter, u8 buflen, u8 *tmpBuf)
2877 {
2878 struct dvobj_priv *dvobjpriv = adapter_to_dvobj(padapter);
2879 struct mcc_obj_priv *mccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2880 struct submit_ctx *mcc_tsf_req_sctx = &mccobjpriv->mcc_tsf_req_sctx;
2881 struct mcc_adapter_priv *mccadapriv = NULL;
2882 _adapter *iface = NULL;
2883 u8 order = 0;
2884
2885 order = mccobjpriv->mcc_tsf_req_sctx_order;
2886 iface = mccobjpriv->iface[order];
2887 mccadapriv = &iface->mcc_adapterpriv;
2888 mccadapriv->tsf = RTW_GET_LE64(tmpBuf + 2);
2889
2890
2891 if (0)
2892 RTW_INFO(FUNC_ADPT_FMT" TSF(order:%d):0x%02llx\n", FUNC_ADPT_ARG(iface), mccadapriv->order, mccadapriv->tsf);
2893
2894 if (mccadapriv->order == (MAX_MCC_NUM - 1))
2895 rtw_sctx_done(&mcc_tsf_req_sctx);
2896 else
2897 mccobjpriv->mcc_tsf_req_sctx_order ++;
2898
2899 }
2900
2901 /**
2902 * rtw_hal_mcc_c2h_handler - mcc c2h handler
2903 */
rtw_hal_mcc_c2h_handler(PADAPTER padapter,u8 buflen,u8 * tmpBuf)2904 void rtw_hal_mcc_c2h_handler(PADAPTER padapter, u8 buflen, u8 *tmpBuf)
2905 {
2906 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
2907 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2908 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
2909 struct submit_ctx *mcc_sctx = &pmccobjpriv->mcc_sctx;
2910 _adapter *cur_adapter = NULL;
2911 u8 cur_ch = 0, cur_bw = 0, cur_ch_offset = 0;
2912 _irqL irqL;
2913
2914 /* RTW_INFO("[length]=%d, [C2H data]="MAC_FMT"\n", buflen, MAC_ARG(tmpBuf)); */
2915 /* To avoid reg is set, but driver recive c2h to set wrong oper_channel */
2916 if (MCC_RPT_STOPMCC == pmccobjpriv->mcc_c2h_status) {
2917 RTW_INFO(FUNC_ADPT_FMT" MCC alread stops return\n", FUNC_ADPT_ARG(padapter));
2918 return;
2919 }
2920
2921 _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2922 pmccobjpriv->mcc_c2h_status = tmpBuf[0];
2923 pmccobjpriv->current_order = tmpBuf[1];
2924 cur_adapter = pmccobjpriv->iface[pmccobjpriv->current_order];
2925 cur_ch = cur_adapter->mlmeextpriv.cur_channel;
2926 cur_bw = cur_adapter->mlmeextpriv.cur_bwmode;
2927 cur_ch_offset = cur_adapter->mlmeextpriv.cur_ch_offset;
2928 rtw_set_oper_ch(cur_adapter, cur_ch);
2929 rtw_set_oper_bw(cur_adapter, cur_bw);
2930 rtw_set_oper_choffset(cur_adapter, cur_ch_offset);
2931 _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2932
2933 if (0)
2934 RTW_INFO("%d,order:%d,TSF:0x%llx\n", tmpBuf[0], tmpBuf[1], RTW_GET_LE64(tmpBuf + 2));
2935
2936 switch (pmccobjpriv->mcc_c2h_status) {
2937 case MCC_RPT_SUCCESS:
2938 _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2939 pmccobjpriv->cur_mcc_success_cnt++;
2940 rtw_hal_mcc_upadate_chnl_bw(cur_adapter, cur_ch, cur_ch_offset, cur_bw, _FALSE);
2941 mcc_get_reg_cmd(padapter, pmccobjpriv->current_order);
2942 _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2943 break;
2944 case MCC_RPT_TXNULL_FAIL:
2945 RTW_INFO("[MCC] TXNULL FAIL\n");
2946 break;
2947 case MCC_RPT_STOPMCC:
2948 RTW_INFO("[MCC] MCC stop\n");
2949 pmccobjpriv->mcc_c2h_status = MCC_RPT_STOPMCC;
2950 rtw_hal_mcc_upadate_chnl_bw(cur_adapter, cur_ch, cur_ch_offset, cur_bw, _TRUE);
2951 rtw_sctx_done(&mcc_sctx);
2952 break;
2953 case MCC_RPT_READY:
2954 _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2955 /* initialize counter & time */
2956 pmccobjpriv->mcc_launch_time = rtw_get_current_time();
2957 pmccobjpriv->mcc_c2h_status = MCC_RPT_READY;
2958 pmccobjpriv->cur_mcc_success_cnt = 0;
2959 pmccobjpriv->prev_mcc_success_cnt = 0;
2960 pmccobjpriv->mcc_tolerance_time = MCC_TOLERANCE_TIME;
2961 _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2962
2963 RTW_INFO("[MCC] MCC ready\n");
2964 rtw_sctx_done(&mcc_sctx);
2965 break;
2966 case MCC_RPT_SWICH_CHANNEL_NOTIFY:
2967 rtw_hal_mcc_sw_ch_fw_notify_hdl(padapter);
2968 break;
2969 case MCC_RPT_UPDATE_NOA_START_TIME:
2970 rtw_hal_mcc_update_noa_start_time_hdl(padapter, buflen, tmpBuf);
2971 break;
2972 case MCC_RPT_TSF:
2973 _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2974 rtw_hal_mcc_rpt_tsf_hdl(padapter, buflen, tmpBuf);
2975 _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2976 break;
2977 default:
2978 /* RTW_INFO("[MCC] Other MCC status(%d)\n", pmccobjpriv->mcc_c2h_status); */
2979 break;
2980 }
2981 }
2982
rtw_hal_mcc_update_parameter(PADAPTER padapter,u8 force_update)2983 void rtw_hal_mcc_update_parameter(PADAPTER padapter, u8 force_update)
2984 {
2985 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2986 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
2987 u8 cmd[H2C_MCC_TIME_SETTING_LEN] = {0};
2988 u8 swchannel_early_time = MCC_SWCH_FW_EARLY_TIME;
2989 u8 ap_num = DEV_AP_NUM(dvobj);
2990
2991 if (ap_num == 0) {
2992 u8 need_update = _FALSE;
2993 u8 start_time_offset = 0, interval = 0, duration = 0;
2994
2995 need_update = rtw_hal_mcc_update_timing_parameters(padapter, force_update);
2996
2997 if (need_update == _FALSE)
2998 return;
2999
3000 start_time_offset = mccobjpriv->start_time;
3001 interval = mccobjpriv->interval;
3002 duration = mccobjpriv->iface[0]->mcc_adapterpriv.mcc_duration;
3003
3004 SET_H2CCMD_MCC_TIME_SETTING_START_TIME(cmd, start_time_offset);
3005 SET_H2CCMD_MCC_TIME_SETTING_INTERVAL(cmd, interval);
3006 SET_H2CCMD_MCC_TIME_SETTING_EARLY_SWITCH_RPT(cmd, swchannel_early_time);
3007 SET_H2CCMD_MCC_TIME_SETTING_UPDATE(cmd, _TRUE);
3008 SET_H2CCMD_MCC_TIME_SETTING_ORDER0_DURATION(cmd, duration);
3009 } else {
3010 PADAPTER order0_iface = NULL;
3011 PADAPTER order1_iface = NULL;
3012 u8 policy_idx = mccobjpriv->policy_index;
3013 u8 duration = mcc_switch_channel_policy_table[policy_idx][MCC_DURATION_IDX];
3014 u8 tsf_sync_offset = mcc_switch_channel_policy_table[policy_idx][MCC_TSF_SYNC_OFFSET_IDX];
3015 u8 start_time_offset = mcc_switch_channel_policy_table[policy_idx][MCC_START_TIME_OFFSET_IDX];
3016 u8 interval = mcc_switch_channel_policy_table[policy_idx][MCC_INTERVAL_IDX];
3017 u8 guard_offset0 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET0_IDX];
3018 u8 guard_offset1 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET1_IDX];
3019 u8 order0_duration = 0;
3020 u8 i = 0;
3021 enum _hw_port tsf_bsae_port = MAX_HW_PORT;
3022 enum _hw_port tsf_sync_port = MAX_HW_PORT;
3023
3024 RTW_INFO("%s: policy_idx=%d\n", __func__, policy_idx);
3025
3026 order0_iface = mccobjpriv->iface[0];
3027 order1_iface = mccobjpriv->iface[1];
3028
3029 /* GO/AP is order 0, GC/STA is order 1 */
3030 order0_duration = order0_iface->mcc_adapterpriv.mcc_duration = interval - duration;
3031 order0_iface->mcc_adapterpriv.mcc_duration = duration;
3032
3033 tsf_bsae_port = rtw_hal_get_port(order1_iface);
3034 tsf_sync_port = rtw_hal_get_port(order0_iface);
3035
3036 /* update IE */
3037 for (i = 0; i < dvobj->iface_nums; i++) {
3038 PADAPTER iface = NULL;
3039 struct mcc_adapter_priv *mccadapriv = NULL;
3040
3041 iface = dvobj->padapters[i];
3042 if (iface == NULL)
3043 continue;
3044
3045 mccadapriv = &iface->mcc_adapterpriv;
3046 if (mccadapriv->role == MCC_ROLE_MAX)
3047 continue;
3048
3049 if (mccadapriv->role == MCC_ROLE_GO)
3050 rtw_hal_mcc_update_go_p2p_ie(iface);
3051 }
3052
3053 /* update H2C cmd */
3054 /* FW set enable */
3055 SET_H2CCMD_MCC_TIME_SETTING_FW_EN(cmd, _TRUE);
3056 /* TSF Sync offset */
3057 SET_H2CCMD_MCC_TIME_SETTING_TSF_SYNC_OFFSET(cmd, tsf_sync_offset);
3058 /* start time offset */
3059 SET_H2CCMD_MCC_TIME_SETTING_START_TIME(cmd, (start_time_offset + guard_offset0));
3060 /* interval */
3061 SET_H2CCMD_MCC_TIME_SETTING_INTERVAL(cmd, interval);
3062 /* Early time to inform driver by C2H before switch channel */
3063 SET_H2CCMD_MCC_TIME_SETTING_EARLY_SWITCH_RPT(cmd, swchannel_early_time);
3064 /* Port0 sync from Port1, not support multi-port */
3065 SET_H2CCMD_MCC_TIME_SETTING_ORDER_BASE(cmd, tsf_bsae_port);
3066 SET_H2CCMD_MCC_TIME_SETTING_ORDER_SYNC(cmd, tsf_sync_port);
3067 SET_H2CCMD_MCC_TIME_SETTING_UPDATE(cmd, _TRUE);
3068 SET_H2CCMD_MCC_TIME_SETTING_ORDER0_DURATION(cmd, order0_duration);
3069 }
3070
3071 rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_TIME_SETTING, H2C_MCC_TIME_SETTING_LEN, cmd);
3072 }
3073
3074 /**
3075 * rtw_hal_mcc_sw_status_check - check mcc swich channel status
3076 * @padapter: primary adapter
3077 */
rtw_hal_mcc_sw_status_check(PADAPTER padapter)3078 void rtw_hal_mcc_sw_status_check(PADAPTER padapter)
3079 {
3080 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3081 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
3082 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
3083 struct mcc_adapter_priv *mccadapriv = NULL;
3084 _adapter *iface = NULL;
3085 u8 cur_cnt = 0, prev_cnt = 0, diff_cnt = 0, check_ret = _FAIL, threshold = 0;
3086 u8 policy_idx = pmccobjpriv->policy_index;
3087 u8 noa_enable = _FALSE;
3088 u8 i = 0;
3089 _irqL irqL;
3090 u8 ap_num = DEV_AP_NUM(dvobj);
3091
3092 /* #define MCC_RESTART 1 */
3093
3094 if (!MCC_EN(padapter))
3095 return;
3096
3097 _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3098
3099 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3100
3101 /* check noa enable or not */
3102 for (i = 0; i < dvobj->iface_nums; i++) {
3103 iface = dvobj->padapters[i];
3104 if (iface == NULL)
3105 continue;
3106
3107 mccadapriv = &iface->mcc_adapterpriv;
3108 if (mccadapriv->role == MCC_ROLE_MAX)
3109 continue;
3110
3111 if (iface->wdinfo.p2p_ps_mode == P2P_PS_NOA) {
3112 noa_enable = _TRUE;
3113 break;
3114 }
3115 }
3116
3117 if (!noa_enable && ap_num == 0)
3118 rtw_hal_mcc_update_parameter(padapter, _FALSE);
3119
3120 threshold = pmccobjpriv->mcc_stop_threshold;
3121
3122 if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
3123 rtw_warn_on(1);
3124 RTW_INFO("PS mode is not active under mcc, force exit ps mode\n");
3125 LeaveAllPowerSaveModeDirect(padapter);
3126 }
3127
3128 if (rtw_get_passing_time_ms(pmccobjpriv->mcc_launch_time) > 2000) {
3129 _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
3130
3131 cur_cnt = pmccobjpriv->cur_mcc_success_cnt;
3132 prev_cnt = pmccobjpriv->prev_mcc_success_cnt;
3133 if (cur_cnt < prev_cnt)
3134 diff_cnt = (cur_cnt + 255) - prev_cnt;
3135 else
3136 diff_cnt = cur_cnt - prev_cnt;
3137
3138 if (diff_cnt < threshold) {
3139 pmccobjpriv->mcc_tolerance_time--;
3140 RTW_INFO("%s: diff_cnt:%d, tolerance_time:%d\n",
3141 __func__, diff_cnt, pmccobjpriv->mcc_tolerance_time);
3142 } else
3143 pmccobjpriv->mcc_tolerance_time = MCC_TOLERANCE_TIME;
3144
3145 pmccobjpriv->prev_mcc_success_cnt = pmccobjpriv->cur_mcc_success_cnt;
3146
3147 if (pmccobjpriv->mcc_tolerance_time != 0)
3148 check_ret = _SUCCESS;
3149
3150 _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
3151
3152 if (check_ret != _SUCCESS) {
3153 RTW_INFO("============ MCC swich channel check fail (%d)=============\n", diff_cnt);
3154 /* restart MCC */
3155 #ifdef MCC_RESTART
3156 rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_STOP_DISCONNECT);
3157 rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT);
3158 #endif /* MCC_RESTART */
3159 }
3160 } else {
3161 _enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
3162 pmccobjpriv->prev_mcc_success_cnt = pmccobjpriv->cur_mcc_success_cnt;
3163 _exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
3164 }
3165
3166 }
3167 _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3168 }
3169
3170 /**
3171 * rtw_hal_mcc_change_scan_flag - change scan flag under mcc
3172 *
3173 * MCC mode under sitesurvey goto AP channel to tx bcn & data
3174 * MCC mode under sitesurvey doesn't support TX data for station mode (FW not support)
3175 *
3176 * @padapter: the adapter to be change scan flag
3177 * @ch: pointer to rerurn ch
3178 * @bw: pointer to rerurn bw
3179 * @offset: pointer to rerurn offset
3180 */
rtw_hal_mcc_change_scan_flag(PADAPTER padapter,u8 * ch,u8 * bw,u8 * offset)3181 u8 rtw_hal_mcc_change_scan_flag(PADAPTER padapter, u8 *ch, u8 *bw, u8 *offset)
3182 {
3183 u8 need_ch_setting_union = _TRUE, i = 0, flags = 0, back_op = _FALSE;
3184 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3185 struct mcc_adapter_priv *mccadapriv = NULL;
3186 struct mlme_ext_priv *mlmeext = NULL;
3187 _adapter *iface = NULL;
3188
3189 if (!MCC_EN(padapter))
3190 goto exit;
3191
3192 if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC))
3193 goto exit;
3194
3195 /* disable PS_ANNC & TX_RESUME for all interface */
3196 /* ToDo: TX_RESUME by interface in SCAN_BACKING_OP */
3197 mlmeext = &padapter->mlmeextpriv;
3198
3199 flags = mlmeext_scan_backop_flags(mlmeext);
3200 if (mlmeext_chk_scan_backop_flags(mlmeext, SS_BACKOP_PS_ANNC))
3201 flags &= ~SS_BACKOP_PS_ANNC;
3202
3203 if (mlmeext_chk_scan_backop_flags(mlmeext, SS_BACKOP_TX_RESUME))
3204 flags &= ~SS_BACKOP_TX_RESUME;
3205
3206 mlmeext_assign_scan_backop_flags(mlmeext, flags);
3207
3208 for (i = 0; i < dvobj->iface_nums; i++) {
3209 iface = dvobj->padapters[i];
3210 if (!iface)
3211 continue;
3212
3213 mlmeext = &iface->mlmeextpriv;
3214
3215 if (MLME_IS_GO(iface) || MLME_IS_AP(iface))
3216 back_op = _TRUE;
3217 else if (MLME_IS_GC(iface) && (iface != padapter))
3218 /* switch to another linked interface(GO) to receive beacon to avoid no beacon disconnect */
3219 back_op = _TRUE;
3220 else if (MLME_IS_STA(iface) && MLME_IS_ASOC(iface) && (iface != padapter))
3221 /* switch to another linked interface(STA) to receive beacon to avoid no beacon disconnect */
3222 back_op = _TRUE;
3223 else {
3224 /* bypass non-linked/non-linking interface/scan interface */
3225 continue;
3226 }
3227
3228 if (back_op) {
3229 *ch = mlmeext->cur_channel;
3230 *bw = mlmeext->cur_bwmode;
3231 *offset = mlmeext->cur_ch_offset;
3232 need_ch_setting_union = _FALSE;
3233 }
3234 }
3235 exit:
3236 return need_ch_setting_union;
3237 }
3238
3239 /**
3240 * rtw_hal_mcc_calc_tx_bytes_from_kernel - calculte tx bytes from kernel to check concurrent tx or not
3241 * @padapter: the adapter to be record tx bytes
3242 * @len: data len
3243 */
rtw_hal_mcc_calc_tx_bytes_from_kernel(PADAPTER padapter,u32 len)3244 inline void rtw_hal_mcc_calc_tx_bytes_from_kernel(PADAPTER padapter, u32 len)
3245 {
3246 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3247
3248 if (MCC_EN(padapter)) {
3249 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3250 pmccadapriv->mcc_tx_bytes_from_kernel += len;
3251 if (0)
3252 RTW_INFO("%s(order:%d): mcc tx bytes from kernel:%lld\n"
3253 , __func__, pmccadapriv->order, pmccadapriv->mcc_tx_bytes_from_kernel);
3254 }
3255 }
3256 }
3257
3258 /**
3259 * rtw_hal_mcc_calc_tx_bytes_to_port - calculte tx bytes to write port in order to flow crtl
3260 * @padapter: the adapter to be record tx bytes
3261 * @len: data len
3262 */
rtw_hal_mcc_calc_tx_bytes_to_port(PADAPTER padapter,u32 len)3263 inline void rtw_hal_mcc_calc_tx_bytes_to_port(PADAPTER padapter, u32 len)
3264 {
3265 if (MCC_EN(padapter)) {
3266 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3267 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3268
3269 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3270 pmccadapriv->mcc_tx_bytes_to_port += len;
3271 if (0)
3272 RTW_INFO("%s(order:%d): mcc tx bytes to port:%d, mcc target tx bytes to port:%d\n"
3273 , __func__, pmccadapriv->order, pmccadapriv->mcc_tx_bytes_to_port
3274 , pmccadapriv->mcc_target_tx_bytes_to_port);
3275 }
3276 }
3277 }
3278
3279 /**
3280 * rtw_hal_mcc_stop_tx_bytes_to_port - stop write port to hw or not
3281 * @padapter: the adapter to be stopped
3282 */
rtw_hal_mcc_stop_tx_bytes_to_port(PADAPTER padapter)3283 inline u8 rtw_hal_mcc_stop_tx_bytes_to_port(PADAPTER padapter)
3284 {
3285 if (MCC_EN(padapter)) {
3286 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3287 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3288
3289 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3290 if (pmccadapriv->mcc_tp_limit) {
3291 if (pmccadapriv->mcc_tx_bytes_to_port >= pmccadapriv->mcc_target_tx_bytes_to_port) {
3292 pmccadapriv->mcc_tx_stop = _TRUE;
3293 rtw_netif_stop_queue(padapter->pnetdev);
3294 return _TRUE;
3295 }
3296 }
3297 }
3298 }
3299
3300 return _FALSE;
3301 }
3302
rtw_hal_mcc_assign_scan_flag(PADAPTER padapter,u8 scan_done)3303 static void rtw_hal_mcc_assign_scan_flag(PADAPTER padapter, u8 scan_done)
3304 {
3305 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3306 struct mcc_adapter_priv *mccadapriv = NULL;
3307 _adapter *iface = NULL;
3308 struct mlme_ext_priv *pmlmeext = NULL;
3309 u8 i = 0, flags;
3310
3311 if (!MCC_EN(padapter))
3312 return;
3313
3314 for (i = 0; i < dvobj->iface_nums; i++) {
3315 iface = dvobj->padapters[i];
3316 if (iface == NULL)
3317 continue;
3318
3319 mccadapriv = &iface->mcc_adapterpriv;
3320 if (mccadapriv->role == MCC_ROLE_MAX)
3321 continue;
3322
3323 pmlmeext = &iface->mlmeextpriv;
3324 if (is_client_associated_to_ap(iface)) {
3325 flags = mlmeext_scan_backop_flags_sta(pmlmeext);
3326 if (scan_done) {
3327 if (mlmeext_chk_scan_backop_flags_sta(pmlmeext, SS_BACKOP_EN)) {
3328 flags &= ~SS_BACKOP_EN;
3329 mlmeext_assign_scan_backop_flags_sta(pmlmeext, flags);
3330 }
3331 } else {
3332 if (!mlmeext_chk_scan_backop_flags_sta(pmlmeext, SS_BACKOP_EN)) {
3333 flags |= SS_BACKOP_EN;
3334 mlmeext_assign_scan_backop_flags_sta(pmlmeext, flags);
3335 }
3336 }
3337
3338 }
3339 }
3340 }
3341
3342 /**
3343 * rtw_hal_set_mcc_setting_scan_start - setting mcc under scan start
3344 * @padapter: the adapter to be setted
3345 * @ch_setting_changed: softap channel setting to be changed or not
3346 */
rtw_hal_set_mcc_setting_scan_start(PADAPTER padapter)3347 u8 rtw_hal_set_mcc_setting_scan_start(PADAPTER padapter)
3348 {
3349 u8 ret = _FAIL;
3350
3351 if (MCC_EN(padapter)) {
3352 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3353
3354 _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3355 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) {
3356 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3357 ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_STOP_SCAN_START);
3358 rtw_hal_mcc_assign_scan_flag(padapter, 0);
3359 }
3360 }
3361 _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3362 }
3363
3364 return ret;
3365 }
3366
3367 /**
3368 * rtw_hal_set_mcc_setting_scan_complete - setting mcc after scan commplete
3369 * @padapter: the adapter to be setted
3370 * @ch_setting_changed: softap channel setting to be changed or not
3371 */
rtw_hal_set_mcc_setting_scan_complete(PADAPTER padapter)3372 u8 rtw_hal_set_mcc_setting_scan_complete(PADAPTER padapter)
3373 {
3374 u8 ret = _FAIL;
3375
3376 if (MCC_EN(padapter)) {
3377 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3378
3379 _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3380
3381 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) {
3382 rtw_hal_mcc_assign_scan_flag(padapter, 1);
3383 ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_SCAN_DONE);
3384 }
3385 _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3386 }
3387
3388 return ret;
3389 }
3390
3391
3392 /**
3393 * rtw_hal_set_mcc_setting_start_bss_network - setting mcc under softap start
3394 * @padapter: the adapter to be setted
3395 * @chbw_grouped: channel bw offset can not be allowed or not
3396 */
rtw_hal_set_mcc_setting_start_bss_network(PADAPTER padapter,u8 chbw_allow)3397 u8 rtw_hal_set_mcc_setting_start_bss_network(PADAPTER padapter, u8 chbw_allow)
3398 {
3399 u8 ret = _FAIL;
3400
3401 if (MCC_EN(padapter)) {
3402 /* channel bw offset can not be allowed, start MCC */
3403 if (chbw_allow == _FALSE) {
3404 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3405
3406 //rtw_hal_mcc_restore_iqk_val(padapter);
3407 _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3408 ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT);
3409 _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3410
3411 if (ret == _FAIL) { /* MCC Start fail, AP/GO switch to buddy's channel */
3412 u8 ch_to_set = 0, bw_to_set, offset_to_set;
3413
3414 rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC);
3415 rtw_hal_set_mcc_setting_disconnect(padapter);
3416 if (rtw_mi_get_ch_setting_union_no_self(
3417 padapter, &ch_to_set, &bw_to_set,
3418 &offset_to_set) != 0) {
3419 PHAL_DATA_TYPE hal = GET_HAL_DATA(padapter);
3420 u8 doiqk = _TRUE;
3421
3422 rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk);
3423 hal->current_channel = 0;
3424 hal->current_channel_bw = CHANNEL_WIDTH_MAX;
3425 set_channel_bwmode(padapter, ch_to_set, offset_to_set, bw_to_set);
3426 doiqk = _FALSE;
3427 rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk);
3428 }
3429 }
3430 }
3431 }
3432
3433 return ret;
3434 }
3435
3436 /**
3437 * rtw_hal_set_mcc_setting_disconnect - setting mcc under mlme disconnect(stop softap/disconnect from AP)
3438 * @padapter: the adapter to be setted
3439 */
rtw_hal_set_mcc_setting_disconnect(PADAPTER padapter)3440 u8 rtw_hal_set_mcc_setting_disconnect(PADAPTER padapter)
3441 {
3442 u8 ret = _FAIL;
3443
3444 if (MCC_EN(padapter)) {
3445 struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3446
3447 _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3448 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) {
3449 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3450 ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_STOP_DISCONNECT);
3451 }
3452 _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3453 }
3454
3455 return ret;
3456 }
3457
3458 /**
3459 * rtw_hal_set_mcc_setting_join_done_chk_ch - setting mcc under join done
3460 * @padapter: the adapter to be checked
3461 */
rtw_hal_set_mcc_setting_join_done_chk_ch(PADAPTER padapter)3462 u8 rtw_hal_set_mcc_setting_join_done_chk_ch(PADAPTER padapter)
3463 {
3464 u8 ret = _FAIL;
3465
3466 if (MCC_EN(padapter)) {
3467 struct mi_state mstate;
3468
3469 rtw_mi_status_no_self(padapter, &mstate);
3470
3471 if (MSTATE_STA_LD_NUM(&mstate) || MSTATE_STA_LG_NUM(&mstate) || MSTATE_AP_NUM(&mstate)) {
3472 bool chbw_allow = _TRUE;
3473 u8 u_ch, u_offset, u_bw;
3474 struct mlme_ext_priv *cur_mlmeext = &padapter->mlmeextpriv;
3475 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3476
3477 if (rtw_mi_get_ch_setting_union_no_self(padapter, &u_ch, &u_bw, &u_offset) <= 0) {
3478 dump_adapters_status(RTW_DBGDUMP , dvobj);
3479 rtw_warn_on(1);
3480 }
3481
3482 RTW_INFO(FUNC_ADPT_FMT" union no self: %u,%u,%u\n"
3483 , FUNC_ADPT_ARG(padapter), u_ch, u_bw, u_offset);
3484
3485 /* chbw_allow? */
3486 chbw_allow = rtw_is_chbw_grouped(cur_mlmeext->cur_channel
3487 , cur_mlmeext->cur_bwmode, cur_mlmeext->cur_ch_offset
3488 , u_ch, u_bw, u_offset);
3489
3490 RTW_INFO(FUNC_ADPT_FMT" chbw_allow:%d\n"
3491 , FUNC_ADPT_ARG(padapter), chbw_allow);
3492
3493 /* if chbw_allow = false, start MCC setting */
3494 if (chbw_allow == _FALSE) {
3495 struct mcc_obj_priv *pmccobjpriv = &dvobj->mcc_objpriv;
3496
3497 rtw_hal_mcc_restore_iqk_val(padapter);
3498 _enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3499 ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT);
3500 _exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3501
3502 if (ret == _FAIL) { /* MCC Start Fail, then disconenct client join */
3503 rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC);
3504 rtw_disassoc_cmd(padapter, 0, RTW_CMDF_DIRECTLY);
3505 rtw_indicate_disconnect(padapter, 0, _FALSE);
3506 rtw_free_assoc_resources(padapter, _TRUE);
3507 rtw_free_network_queue(padapter, _TRUE);
3508 }
3509 }
3510 }
3511 }
3512
3513 return ret;
3514 }
3515
3516 /**
3517 * rtw_hal_set_mcc_setting_chk_start_clnt_join - check change channel under start clnt join
3518 * @padapter: the adapter to be checked
3519 * @ch: pointer to rerurn ch
3520 * @bw: pointer to rerurn bw
3521 * @offset: pointer to rerurn offset
3522 * @chbw_allow: allow to use adapter's channel setting
3523 */
rtw_hal_set_mcc_setting_chk_start_clnt_join(PADAPTER padapter,u8 * ch,u8 * bw,u8 * offset,u8 chbw_allow)3524 u8 rtw_hal_set_mcc_setting_chk_start_clnt_join(PADAPTER padapter, u8 *ch, u8 *bw, u8 *offset, u8 chbw_allow)
3525 {
3526 u8 ret = _FAIL;
3527
3528 /* if chbw_allow = false under en_mcc = TRUE, we do not change channel related setting */
3529 if (MCC_EN(padapter)) {
3530 /* restore union channel related setting to current channel related setting */
3531 if (chbw_allow == _FALSE) {
3532 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3533
3534 /* issue null data to other interface connected to AP */
3535 rtw_hal_mcc_issue_null_data(padapter, chbw_allow, _TRUE);
3536
3537 *ch = pmlmeext->cur_channel;
3538 *bw = pmlmeext->cur_bwmode;
3539 *offset = pmlmeext->cur_ch_offset;
3540
3541 RTW_INFO(FUNC_ADPT_FMT" en_mcc:%d(%d,%d,%d,)\n"
3542 , FUNC_ADPT_ARG(padapter), MCC_EN(padapter)
3543 , *ch, *bw, *offset);
3544 ret = _SUCCESS;
3545 }
3546 }
3547
3548 return ret;
3549 }
3550
rtw_hal_mcc_dump_noa_content(void * sel,PADAPTER padapter)3551 static void rtw_hal_mcc_dump_noa_content(void *sel, PADAPTER padapter)
3552 {
3553 struct mcc_adapter_priv *pmccadapriv = NULL;
3554 u8 *pos = NULL;
3555 pmccadapriv = &padapter->mcc_adapterpriv;
3556 /* last position for NoA attribute */
3557 pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len;
3558
3559
3560 RTW_PRINT_SEL(sel, "\nStart to dump NoA Content\n");
3561 RTW_PRINT_SEL(sel, "NoA Counts:%d\n", *(pos - 13));
3562 RTW_PRINT_SEL(sel, "NoA Duration(TU):%d\n", (RTW_GET_LE32(pos - 12))/TU);
3563 RTW_PRINT_SEL(sel, "NoA Interval(TU):%d\n", (RTW_GET_LE32(pos - 8))/TU);
3564 RTW_PRINT_SEL(sel, "NoA Start time(microseconds):0x%02x\n", RTW_GET_LE32(pos - 4));
3565 RTW_PRINT_SEL(sel, "End to dump NoA Content\n");
3566 }
3567
mcc_dump_dbg_reg(void * sel,_adapter * adapter)3568 static void mcc_dump_dbg_reg(void *sel, _adapter *adapter)
3569 {
3570 struct mcc_obj_priv *mccobjpriv = adapter_to_mccobjpriv(adapter);
3571 struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
3572 u8 i,j;
3573 _irqL irqL;
3574
3575 _enter_critical_bh(&mccobjpriv->mcc_lock, &irqL);
3576 RTW_PRINT_SEL(sel, "current order=%d\n", mccobjpriv->current_order);
3577 _exit_critical_bh(&mccobjpriv->mcc_lock, &irqL);
3578
3579 _enter_critical_mutex(&mccobjpriv->mcc_dbg_reg_mutex, NULL);
3580 for (i = 0; i < ARRAY_SIZE(mccobjpriv->dbg_reg); i++)
3581 RTW_PRINT_SEL(sel, "REG_0x%X:0x%08x\n", mccobjpriv->dbg_reg[i], mccobjpriv->dbg_reg_val[i]);
3582
3583 for (i = 0; i < ARRAY_SIZE(mccobjpriv->dbg_rf_reg); i++) {
3584 for (j = 0; j < hal_spec->rf_reg_path_num; j++)
3585 RTW_PRINT_SEL(sel, "RF_PATH_%d_REG_0x%X:0x%08x\n",
3586 j, mccobjpriv->dbg_rf_reg[i], mccobjpriv->dbg_rf_reg_val[i][j]);
3587 }
3588 _exit_critical_mutex(&mccobjpriv->mcc_dbg_reg_mutex, NULL);
3589 }
3590
3591
rtw_hal_dump_mcc_info(void * sel,struct dvobj_priv * dvobj)3592 void rtw_hal_dump_mcc_info(void *sel, struct dvobj_priv *dvobj)
3593 {
3594 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
3595 struct mcc_adapter_priv *mccadapriv = NULL;
3596 _adapter *iface = NULL, *pri_adapter = NULL;
3597 struct registry_priv *regpriv = NULL;
3598 HAL_DATA_TYPE *hal = NULL;
3599 u8 i = 0, j = 0;
3600 u64 tsf[MAX_MCC_NUM] = {0};
3601
3602 /* regpriv is common for all adapter */
3603 pri_adapter = dvobj_get_primary_adapter(dvobj);
3604 hal = GET_HAL_DATA(pri_adapter);
3605
3606 RTW_PRINT_SEL(sel, "**********************************************\n");
3607 RTW_PRINT_SEL(sel, "en_mcc:%d\n", MCC_EN(pri_adapter));
3608 RTW_PRINT_SEL(sel, "primary adapter("ADPT_FMT") duration:%d%c\n",
3609 ADPT_ARG(dvobj_get_primary_adapter(dvobj)), mccobjpriv->duration, 37);
3610 RTW_PRINT_SEL(sel, "runtime duration:%s\n", mccobjpriv->enable_runtime_duration ? "enable":"disable");
3611 RTW_PRINT_SEL(sel, "phydm offload:%s\n", mccobjpriv->mcc_phydm_offload ? "enable":"disable");
3612
3613 if (rtw_hal_check_mcc_status(pri_adapter, MCC_STATUS_DOING_MCC)) {
3614 rtw_hal_mcc_rqt_tsf(pri_adapter, tsf);
3615
3616 for (i = 0; i < MAX_MCC_NUM; i++) {
3617 iface = mccobjpriv->iface[i];
3618 if (!iface)
3619 continue;
3620
3621 regpriv = &iface->registrypriv;
3622 mccadapriv = &iface->mcc_adapterpriv;
3623
3624 if (mccadapriv) {
3625 u8 p2p_ps_mode = iface->wdinfo.p2p_ps_mode;
3626
3627 RTW_PRINT_SEL(sel, "adapter mcc info:\n");
3628 RTW_PRINT_SEL(sel, "ifname:%s\n", ADPT_ARG(iface));
3629 RTW_PRINT_SEL(sel, "order:%d\n", mccadapriv->order);
3630 RTW_PRINT_SEL(sel, "duration:%d\n", mccadapriv->mcc_duration);
3631 RTW_PRINT_SEL(sel, "target tx bytes:%d\n", mccadapriv->mcc_target_tx_bytes_to_port);
3632 RTW_PRINT_SEL(sel, "current TP:%d\n", mccadapriv->mcc_tp);
3633 RTW_PRINT_SEL(sel, "mgmt queue macid:%d\n", mccadapriv->mgmt_queue_macid);
3634 RTW_PRINT_SEL(sel, "macid bitmap:0x%02x\n", mccadapriv->mcc_macid_bitmap);
3635 RTW_PRINT_SEL(sel, "P2P NoA:%s\n\n", p2p_ps_mode == P2P_PS_NOA ? "enable":"disable");
3636 RTW_PRINT_SEL(sel, "registry data:\n");
3637 RTW_PRINT_SEL(sel, "ap target tx TP(BW:20M):%d Mbps\n", regpriv->rtw_mcc_ap_bw20_target_tx_tp);
3638 RTW_PRINT_SEL(sel, "ap target tx TP(BW:40M):%d Mbps\n", regpriv->rtw_mcc_ap_bw40_target_tx_tp);
3639 RTW_PRINT_SEL(sel, "ap target tx TP(BW:80M):%d Mbps\n", regpriv->rtw_mcc_ap_bw80_target_tx_tp);
3640 RTW_PRINT_SEL(sel, "sta target tx TP(BW:20M):%d Mbps\n", regpriv->rtw_mcc_sta_bw20_target_tx_tp);
3641 RTW_PRINT_SEL(sel, "sta target tx TP(BW:40M ):%d Mbps\n", regpriv->rtw_mcc_sta_bw40_target_tx_tp);
3642 RTW_PRINT_SEL(sel, "sta target tx TP(BW:80M):%d Mbps\n", regpriv->rtw_mcc_sta_bw80_target_tx_tp);
3643 RTW_PRINT_SEL(sel, "single tx criteria:%d Mbps\n", regpriv->rtw_mcc_single_tx_cri);
3644 RTW_PRINT_SEL(sel, "HW TSF=0x%llx\n", tsf[mccadapriv->order]);
3645 if (MLME_IS_GO(iface))
3646 rtw_hal_mcc_dump_noa_content(sel, iface);
3647 RTW_PRINT_SEL(sel, "**********************************************\n");
3648 }
3649 }
3650
3651 mcc_dump_dbg_reg(sel, pri_adapter);
3652 }
3653
3654 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
3655 RTW_PRINT_SEL(sel, "@@@@@@@@@@@@@@@@@@@@\n");
3656 rtw_hal_mcc_cfg_phydm(pri_adapter, MCC_CFG_PHYDM_DUMP, sel);
3657 RTW_PRINT_SEL(sel, "@@@@@@@@@@@@@@@@@@@@\n");
3658 #endif
3659
3660 RTW_PRINT_SEL(sel, "------------------------------------------\n");
3661 RTW_PRINT_SEL(sel, "policy index:%d\n", mccobjpriv->policy_index);
3662 RTW_PRINT_SEL(sel, "------------------------------------------\n");
3663 RTW_PRINT_SEL(sel, "define data:\n");
3664 RTW_PRINT_SEL(sel, "ap target tx TP(BW:20M):%d Mbps\n", MCC_AP_BW20_TARGET_TX_TP);
3665 RTW_PRINT_SEL(sel, "ap target tx TP(BW:40M):%d Mbps\n", MCC_AP_BW40_TARGET_TX_TP);
3666 RTW_PRINT_SEL(sel, "ap target tx TP(BW:80M):%d Mbps\n", MCC_AP_BW80_TARGET_TX_TP);
3667 RTW_PRINT_SEL(sel, "sta target tx TP(BW:20M):%d Mbps\n", MCC_STA_BW20_TARGET_TX_TP);
3668 RTW_PRINT_SEL(sel, "sta target tx TP(BW:40M):%d Mbps\n", MCC_STA_BW40_TARGET_TX_TP);
3669 RTW_PRINT_SEL(sel, "sta target tx TP(BW:80M):%d Mbps\n", MCC_STA_BW80_TARGET_TX_TP);
3670 RTW_PRINT_SEL(sel, "single tx criteria:%d Mbps\n", MCC_SINGLE_TX_CRITERIA);
3671 RTW_PRINT_SEL(sel, "------------------------------------------\n");
3672 }
3673
update_mcc_mgntframe_attrib(_adapter * padapter,struct pkt_attrib * pattrib)3674 inline void update_mcc_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
3675 {
3676 if (MCC_EN(padapter)) {
3677 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3678 /* use QSLT_MGNT to check mgnt queue or bcn queue */
3679 if (pattrib->qsel == QSLT_MGNT) {
3680 pattrib->mac_id = padapter->mcc_adapterpriv.mgmt_queue_macid;
3681 pattrib->qsel = QSLT_VO;
3682 }
3683 }
3684 }
3685 }
3686
rtw_hal_mcc_link_status_chk(_adapter * padapter,const char * msg)3687 inline u8 rtw_hal_mcc_link_status_chk(_adapter *padapter, const char *msg)
3688 {
3689 u8 ret = _TRUE, i = 0;
3690 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3691 _adapter *iface;
3692 struct mlme_ext_priv *mlmeext;
3693
3694 if (MCC_EN(padapter)) {
3695 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) {
3696 for (i = 0; i < dvobj->iface_nums; i++) {
3697 iface = dvobj->padapters[i];
3698 mlmeext = &iface->mlmeextpriv;
3699 if (mlmeext_scan_state(mlmeext) != SCAN_DISABLE) {
3700 #ifdef DBG_EXPIRATION_CHK
3701 RTW_INFO(FUNC_ADPT_FMT" don't enter %s under scan for MCC mode\n", FUNC_ADPT_ARG(padapter), msg);
3702 #endif
3703 ret = _FALSE;
3704 goto exit;
3705 }
3706 }
3707 }
3708 }
3709
3710 exit:
3711 return ret;
3712 }
3713
rtw_hal_mcc_issue_null_data(_adapter * padapter,u8 chbw_allow,u8 ps_mode)3714 void rtw_hal_mcc_issue_null_data(_adapter *padapter, u8 chbw_allow, u8 ps_mode)
3715 {
3716 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3717 _adapter *iface = NULL;
3718 systime start = rtw_get_current_time();
3719 u8 i = 0;
3720
3721 if (!MCC_EN(padapter))
3722 return;
3723
3724 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3725 return;
3726
3727 if (chbw_allow == _TRUE)
3728 return;
3729
3730 for (i = 0; i < dvobj->iface_nums; i++) {
3731 iface = dvobj->padapters[i];
3732 /* issue null data to inform ap station will leave */
3733 if (is_client_associated_to_ap(iface)) {
3734 struct mlme_ext_priv *mlmeext = &iface->mlmeextpriv;
3735 struct mlme_ext_info *mlmeextinfo = &mlmeext->mlmext_info;
3736 u8 ch = mlmeext->cur_channel;
3737 u8 bw = mlmeext->cur_bwmode;
3738 u8 offset = mlmeext->cur_ch_offset;
3739 struct sta_info *sta = rtw_get_stainfo(&iface->stapriv, get_my_bssid(&(mlmeextinfo->network)));
3740
3741 if (!sta)
3742 continue;
3743
3744 set_channel_bwmode(iface, ch, offset, bw);
3745
3746 if (ps_mode)
3747 rtw_hal_macid_sleep(iface, sta->cmn.mac_id);
3748 else
3749 rtw_hal_macid_wakeup(iface, sta->cmn.mac_id);
3750
3751 issue_nulldata(iface, NULL, ps_mode, 3, 50);
3752 }
3753 }
3754 RTW_INFO("%s(%d ms)\n", __func__, rtw_get_passing_time_ms(start));
3755 }
3756
rtw_hal_mcc_append_go_p2p_ie(PADAPTER padapter,u8 * pframe,u32 * len)3757 u8 *rtw_hal_mcc_append_go_p2p_ie(PADAPTER padapter, u8 *pframe, u32 *len)
3758 {
3759 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3760
3761 if (!MCC_EN(padapter))
3762 return pframe;
3763
3764 if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3765 return pframe;
3766
3767 if (pmccadapriv->p2p_go_noa_ie_len == 0)
3768 return pframe;
3769
3770 _rtw_memcpy(pframe, pmccadapriv->p2p_go_noa_ie, pmccadapriv->p2p_go_noa_ie_len);
3771 *len = *len + pmccadapriv->p2p_go_noa_ie_len;
3772
3773 return pframe + pmccadapriv->p2p_go_noa_ie_len;
3774 }
3775
rtw_hal_dump_mcc_policy_table(void * sel)3776 void rtw_hal_dump_mcc_policy_table(void *sel)
3777 {
3778 u8 idx = 0;
3779 RTW_PRINT_SEL(sel, "duration\t,tsf sync offset\t,start time offset\t,interval\t,guard offset0\t,guard offset1\n");
3780
3781 for (idx = 0; idx < mcc_max_policy_num; idx ++) {
3782 RTW_PRINT_SEL(sel, "%d\t\t,%d\t\t\t,%d\t\t\t,%d\t\t,%d\t\t,%d\n"
3783 , mcc_switch_channel_policy_table[idx][MCC_DURATION_IDX]
3784 , mcc_switch_channel_policy_table[idx][MCC_TSF_SYNC_OFFSET_IDX]
3785 , mcc_switch_channel_policy_table[idx][MCC_START_TIME_OFFSET_IDX]
3786 , mcc_switch_channel_policy_table[idx][MCC_INTERVAL_IDX]
3787 , mcc_switch_channel_policy_table[idx][MCC_GUARD_OFFSET0_IDX]
3788 , mcc_switch_channel_policy_table[idx][MCC_GUARD_OFFSET1_IDX]);
3789 }
3790 }
3791
rtw_hal_mcc_update_macid_bitmap(PADAPTER padapter,int mac_id,u8 add)3792 void rtw_hal_mcc_update_macid_bitmap(PADAPTER padapter, int mac_id, u8 add)
3793 {
3794 struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3795
3796 if (!MCC_EN(padapter))
3797 return;
3798
3799 if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3800 return;
3801
3802 if (pmccadapriv->role == MCC_ROLE_GC || pmccadapriv->role == MCC_ROLE_STA)
3803 return;
3804
3805 if (mac_id < 0) {
3806 RTW_WARN("%s: mac_id < 0(%d)\n", __func__, mac_id);
3807 return;
3808 }
3809
3810 RTW_INFO(ADPT_FMT" %s macid=%d, ori mcc_macid_bitmap=0x%08x\n"
3811 , ADPT_ARG(padapter), add ? "add" : "clear"
3812 , mac_id, pmccadapriv->mcc_macid_bitmap);
3813
3814 if (add) {
3815 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
3816 rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_ADD_CLIENT, &mac_id);
3817 #endif
3818 pmccadapriv->mcc_macid_bitmap |= BIT(mac_id);
3819 } else {
3820 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
3821 rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_REMOVE_CLIENT, &mac_id);
3822 #endif
3823 pmccadapriv->mcc_macid_bitmap &= ~(BIT(mac_id));
3824 }
3825 rtw_hal_set_mcc_macid_cmd(padapter);
3826 }
3827
rtw_hal_mcc_process_noa(PADAPTER padapter)3828 void rtw_hal_mcc_process_noa(PADAPTER padapter)
3829 {
3830 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3831 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3832 struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
3833
3834 if (!MCC_EN(padapter))
3835 return;
3836
3837 if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3838 return;
3839
3840 if (!MLME_IS_GC(padapter))
3841 return;
3842
3843 switch(pwdinfo->p2p_ps_mode) {
3844 case P2P_PS_NONE:
3845 RTW_INFO("[MCC] Disable NoA under MCC\n");
3846 rtw_hal_mcc_update_parameter(padapter, _TRUE);
3847 break;
3848 case P2P_PS_NOA:
3849 RTW_INFO("[MCC] Enable NoA under MCC\n");
3850 break;
3851 default:
3852 break;
3853
3854 }
3855 }
3856
rtw_hal_mcc_parameter_init(PADAPTER padapter)3857 void rtw_hal_mcc_parameter_init(PADAPTER padapter)
3858 {
3859 if (!padapter->registrypriv.en_mcc)
3860 return;
3861
3862 if (is_primary_adapter(padapter)) {
3863 SET_MCC_EN_FLAG(padapter, padapter->registrypriv.en_mcc);
3864 SET_MCC_DURATION(padapter, padapter->registrypriv.rtw_mcc_duration);
3865 SET_MCC_RUNTIME_DURATION(padapter, padapter->registrypriv.rtw_mcc_enable_runtime_duration);
3866 SET_MCC_PHYDM_OFFLOAD(padapter, padapter->registrypriv.rtw_mcc_phydm_offload);
3867 }
3868 }
3869
3870
set_mcc_duration_hdl(PADAPTER adapter,const u8 * val)3871 static u8 set_mcc_duration_hdl(PADAPTER adapter, const u8 *val)
3872 {
3873 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
3874 struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
3875 _adapter *iface = NULL;
3876 u8 duration = 50;
3877 u8 ret = _SUCCESS, noa_enable = _FALSE, i = 0;
3878 enum mcc_duration_setting type;
3879
3880 if (!mccobjpriv->enable_runtime_duration)
3881 goto exit;
3882
3883 #ifdef CONFIG_P2P_PS
3884 /* check noa enable or not */
3885 for (i = 0; i < dvobj->iface_nums; i++) {
3886 iface = dvobj->padapters[i];
3887 if (iface->wdinfo.p2p_ps_mode == P2P_PS_NOA) {
3888 noa_enable = _TRUE;
3889 break;
3890 }
3891 }
3892 #endif /* CONFIG_P2P_PS */
3893
3894 type = val[0];
3895 duration = val[1];
3896
3897 if (type == MCC_DURATION_MAPPING) {
3898 switch (duration) {
3899 /* 0 = fair scheduling */
3900 case 0:
3901 mccobjpriv->duration= 40;
3902 mccobjpriv->policy_index = 2;
3903 mccobjpriv->mchan_sched_mode = MCC_FAIR_SCHEDULE;
3904 break;
3905 /* 1 = favor STA */
3906 case 1:
3907 mccobjpriv->duration= 70;
3908 mccobjpriv->policy_index = 1;
3909 mccobjpriv->mchan_sched_mode = MCC_FAVOR_STA;
3910 break;
3911 /* 2 = favor P2P*/
3912 case 2:
3913 default:
3914 mccobjpriv->duration= 30;
3915 mccobjpriv->policy_index = 0;
3916 mccobjpriv->mchan_sched_mode = MCC_FAVOR_P2P;
3917 break;
3918 }
3919 } else {
3920 mccobjpriv->duration = duration;
3921 rtw_hal_mcc_update_policy_table(adapter);
3922 }
3923
3924 /* only update sw parameter under MCC
3925 it will be force update during */
3926 if (noa_enable)
3927 goto exit;
3928
3929 if (rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC))
3930 rtw_hal_mcc_update_parameter(adapter, _TRUE);
3931 exit:
3932 return ret;
3933 }
3934
rtw_set_mcc_duration_cmd(_adapter * adapter,u8 type,u8 val)3935 u8 rtw_set_mcc_duration_cmd(_adapter *adapter, u8 type, u8 val)
3936 {
3937 struct cmd_obj *cmdobj;
3938 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3939 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3940 u8 *buf = NULL;
3941 u8 sz = 2;
3942 u8 res = _SUCCESS;
3943
3944
3945 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3946 if (cmdobj == NULL) {
3947 res = _FAIL;
3948 goto exit;
3949 }
3950
3951 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3952 if (pdrvextra_cmd_parm == NULL) {
3953 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
3954 res = _FAIL;
3955 goto exit;
3956 }
3957
3958 buf = rtw_zmalloc(sizeof(u8) * sz);
3959 if (buf == NULL) {
3960 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
3961 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
3962 res = _FAIL;
3963 goto exit;
3964 }
3965
3966 pdrvextra_cmd_parm->ec_id = MCC_CMD_WK_CID;
3967 pdrvextra_cmd_parm->type = MCC_SET_DURATION_WK_CID;
3968 pdrvextra_cmd_parm->size = sz;
3969 pdrvextra_cmd_parm->pbuf = buf;
3970
3971 _rtw_memcpy(buf, &type, 1);
3972 _rtw_memcpy(buf + 1, &val, 1);
3973
3974 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
3975 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3976
3977 exit:
3978 return res;
3979 }
3980
3981 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
mcc_phydm_offload_enable_hdl(_adapter * adapter,const u8 * val)3982 static u8 mcc_phydm_offload_enable_hdl(_adapter *adapter, const u8 *val)
3983 {
3984 struct mcc_obj_priv *mccobjpriv = adapter_to_mccobjpriv(adapter);
3985 u8 ret = _SUCCESS;
3986 u8 enable = *val;
3987
3988 /*only modify driver parameter during non-mcc status */
3989 if (!rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) {
3990 mccobjpriv->mcc_phydm_offload = enable;
3991 } else {
3992 /*modify both driver & phydm parameter during mcc status */
3993 mccobjpriv->mcc_phydm_offload = enable;
3994 rtw_hal_mcc_cfg_phydm(adapter, MCC_CFG_PHYDM_OFFLOAD, &mccobjpriv->mcc_phydm_offload);
3995 }
3996
3997 RTW_INFO("[MCC] phydm offload enable hdl(%d)\n", mccobjpriv->mcc_phydm_offload);
3998
3999 return ret;
4000 }
4001
rtw_set_mcc_phydm_offload_enable_cmd(_adapter * adapter,u8 enable,u8 enqueue)4002 u8 rtw_set_mcc_phydm_offload_enable_cmd(_adapter *adapter, u8 enable, u8 enqueue)
4003 {
4004 u8 res = _SUCCESS;
4005
4006 if (enqueue) {
4007 struct cmd_obj *cmdobj;
4008 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
4009 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
4010 u8 *mcc_phydm_offload_enable = NULL;
4011
4012
4013 cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
4014 if (cmdobj == NULL) {
4015 res = _FAIL;
4016 goto exit;
4017 }
4018
4019 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
4020 if (pdrvextra_cmd_parm == NULL) {
4021 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
4022 res = _FAIL;
4023 goto exit;
4024 }
4025
4026 mcc_phydm_offload_enable = rtw_zmalloc(sizeof(u8));
4027 if (mcc_phydm_offload_enable == NULL) {
4028 rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
4029 rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
4030 res = _FAIL;
4031 goto exit;
4032 }
4033
4034 pdrvextra_cmd_parm->ec_id = MCC_CMD_WK_CID;
4035 pdrvextra_cmd_parm->type = MCC_SET_PHYDM_OFFLOAD_WK_CID;
4036 pdrvextra_cmd_parm->size = 1;
4037 pdrvextra_cmd_parm->pbuf = mcc_phydm_offload_enable;
4038
4039 _rtw_memcpy(mcc_phydm_offload_enable, &enable, 1);
4040 init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
4041 res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
4042 } else {
4043 mcc_phydm_offload_enable_hdl(adapter, &enable);
4044 }
4045
4046 exit:
4047 return res;
4048 }
4049 #endif
4050
rtw_mcc_cmd_hdl(_adapter * adapter,u8 type,const u8 * val)4051 u8 rtw_mcc_cmd_hdl(_adapter *adapter, u8 type, const u8 *val)
4052 {
4053 struct mcc_obj_priv *mccobjpriv = adapter_to_mccobjpriv(adapter);
4054 u8 ret = _SUCCESS;
4055
4056 switch (type) {
4057 case MCC_SET_DURATION_WK_CID:
4058 set_mcc_duration_hdl(adapter, val);
4059 break;
4060 case MCC_GET_DBG_REG_WK_CID:
4061 mcc_get_reg_hdl(adapter, val);
4062 break;
4063 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
4064 case MCC_SET_PHYDM_OFFLOAD_WK_CID:
4065 mcc_phydm_offload_enable_hdl(adapter, val);
4066 break;
4067 #endif
4068 default:
4069 RTW_ERR("[MCC] rtw_mcc_cmd_hdl fail(%d)\n", type);
4070 break;
4071 }
4072
4073
4074
4075 return ret;
4076 }
4077
4078 #endif /* CONFIG_MCC_MODE */
4079