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