1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2019 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _RTW_PWRCTRL_C_
16
17 #include <drv_types.h>
18 #ifdef CONFIG_RTW_IPS
rtw_core_set_ips_state(void * drv_priv,enum rtw_rf_state state)19 bool rtw_core_set_ips_state(void *drv_priv, enum rtw_rf_state state)
20 {
21 struct dvobj_priv *dvobj = (struct dvobj_priv *)drv_priv;
22 enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
23
24 if (state == RTW_RF_ON) {
25 pstatus = rtw_phl_rf_on(dvobj->phl);
26 } else if (state == RTW_RF_OFF) {
27 pstatus = rtw_phl_rf_off(dvobj->phl);
28 }
29
30 if (RTW_PHL_STATUS_SUCCESS == pstatus)
31 return true;
32 else
33 return false;
34 }
35 #endif
36 #ifdef DBG_CHECK_FW_PS_STATE
rtw_fw_ps_state(_adapter * padapter)37 int rtw_fw_ps_state(_adapter *padapter)
38 {
39 struct dvobj_priv *psdpriv = padapter->dvobj;
40 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
41 int ret = _FAIL, dont_care = 0;
42 u8 ps_state = 0;
43 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
44 struct registry_priv *registry_par = &padapter->registrypriv;
45
46 if (registry_par->check_fw_ps != 1)
47 return _SUCCESS;
48
49 _enter_pwrlock(&pwrpriv->check_32k_lock);
50
51 if (RTW_CANNOT_RUN(psdpriv)) {
52 RTW_INFO("%s: bSurpriseRemoved=%s , hw_init_completed=%d, bDriverStopped=%s\n", __func__
53 , dev_is_surprise_removed(adapter_to_dvobj(padapter)) ? "True" : "False"
54 , rtw_hw_get_init_completed(adapter_to_dvobj(padapter))
55 , dev_is_drv_stopped(adapter_to_dvobj(padapter)) ? "True" : "False");
56 goto exit_fw_ps_state;
57 }
58 rtw_hal_get_hwreg(padapter, HW_VAR_FW_PS_STATE, (u8 *)&ps_state);
59 if (ps_state == PS_ACTIVE) {
60 ret = _SUCCESS;
61 } else {
62 pdbgpriv->dbg_poll_fail_cnt++;
63 RTW_INFO("%s: fw_ps_state=%04x\n", __func__, ps_state);
64 }
65
66 exit_fw_ps_state:
67 _exit_pwrlock(&pwrpriv->check_32k_lock);
68 return ret;
69 }
70 #endif /*DBG_CHECK_FW_PS_STATE*/
71 #ifdef CONFIG_IPS
_ips_enter(_adapter * padapter)72 void _ips_enter(_adapter *padapter)
73 {
74 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
75
76 pwrpriv->bips_processing = _TRUE;
77
78 /* syn ips_mode with request */
79 pwrpriv->ips_mode = pwrpriv->ips_mode_req;
80
81 pwrpriv->ips_enter_cnts++;
82 RTW_INFO("==>ips_enter cnts:%d\n", pwrpriv->ips_enter_cnts);
83
84 if (rf_off == pwrpriv->change_rfpwrstate) {
85 pwrpriv->bpower_saving = _TRUE;
86 RTW_PRINT("nolinked power save enter\n");
87
88 if (pwrpriv->ips_mode == IPS_LEVEL_2)
89 pwrpriv->bkeepfwalive = _TRUE;
90
91 #ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
92 pwrpriv->pwr_saving_start_time = rtw_get_current_time();
93 #endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
94
95 rtw_ips_pwr_down(padapter);
96 pwrpriv->rf_pwrstate = rf_off;
97 }
98 pwrpriv->bips_processing = _FALSE;
99
100 }
101
ips_enter(_adapter * padapter)102 void ips_enter(_adapter *padapter)
103 {
104 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
105
106 _enter_pwrlock(&pwrpriv->lock);
107 _ips_enter(padapter);
108 _exit_pwrlock(&pwrpriv->lock);
109
110 #ifdef CONFIG_PCI_DYNAMIC_ASPM
111 rtw_pci_dynamic_aspm_set_mode(padapter, ASPM_MODE_PS);
112 #endif
113 }
114
_ips_leave(_adapter * padapter)115 int _ips_leave(_adapter *padapter)
116 {
117 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
118 int result = _SUCCESS;
119
120 if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) {
121 pwrpriv->bips_processing = _TRUE;
122 pwrpriv->change_rfpwrstate = rf_on;
123 pwrpriv->ips_leave_cnts++;
124 RTW_INFO("==>ips_leave cnts:%d\n", pwrpriv->ips_leave_cnts);
125
126 result = rtw_ips_pwr_up(padapter);
127 if (result == _SUCCESS)
128 pwrpriv->rf_pwrstate = rf_on;
129
130 #ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
131 pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);
132 #endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
133
134 RTW_PRINT("nolinked power save leave\n");
135 #if 0 /*GEORGIA_TODO_REDEFINE_IO*/
136 RTW_INFO("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
137 #endif
138 pwrpriv->bips_processing = _FALSE;
139
140 pwrpriv->bkeepfwalive = _FALSE;
141 pwrpriv->bpower_saving = _FALSE;
142 }
143
144 return result;
145 }
146
ips_leave(_adapter * padapter)147 int ips_leave(_adapter *padapter)
148 {
149 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
150 #ifdef DBG_CHECK_FW_PS_STATE
151 struct dvobj_priv *psdpriv = padapter->dvobj;
152 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
153 #endif
154 int ret;
155
156 if (!is_primary_adapter(padapter))
157 return _SUCCESS;
158
159 _enter_pwrlock(&pwrpriv->lock);
160 ret = _ips_leave(padapter);
161 #ifdef DBG_CHECK_FW_PS_STATE
162 if (rtw_fw_ps_state(padapter) == _FAIL) {
163 RTW_INFO("ips leave doesn't leave 32k\n");
164 pdbgpriv->dbg_leave_ips_fail_cnt++;
165 }
166 #endif /* DBG_CHECK_FW_PS_STATE */
167 _exit_pwrlock(&pwrpriv->lock);
168
169 #ifdef CONFIG_PCI_DYNAMIC_ASPM
170 rtw_pci_dynamic_aspm_set_mode(padapter, ASPM_MODE_PERF);
171 #endif
172 return ret;
173 }
174 #endif /* CONFIG_IPS */
175
176 #ifdef CONFIG_POWER_SAVING
rtw_pwr_unassociated_idle(_adapter * adapter)177 bool rtw_pwr_unassociated_idle(_adapter *adapter)
178 {
179 u8 i;
180 _adapter *iface;
181 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
182 struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
183 struct mlme_priv *pmlmepriv;
184 #ifdef CONFIG_P2P
185 struct wifidirect_info *pwdinfo;
186 #endif
187 u8 xmitbuf_nr = GET_HAL_XMITBUF_NR(dvobj);
188 u8 xmitbuf_ext_nr = GET_HAL_XMITBUF_EXT_NR(dvobj);
189
190 bool ret = _FALSE;
191
192 if (adapter_to_pwrctl(adapter)->bpower_saving == _TRUE) {
193 /* RTW_INFO("%s: already in LPS or IPS mode\n", __func__); */
194 goto exit;
195 }
196
197 if (rtw_time_after(adapter_to_pwrctl(adapter)->ips_deny_time, rtw_get_current_time())) {
198 /* RTW_INFO("%s ips_deny_time\n", __func__); */
199 goto exit;
200 }
201
202 for (i = 0; i < dvobj->iface_nums; i++) {
203 iface = dvobj->padapters[i];
204 if ((iface) && rtw_is_adapter_up(iface)) {
205 pmlmepriv = &(iface->mlmepriv);
206 #ifdef CONFIG_P2P
207 pwdinfo = &(iface->wdinfo);
208 #endif
209 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_UNDER_SURVEY)
210 || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS)
211 || MLME_IS_AP(iface)
212 || MLME_IS_MESH(iface)
213 || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE)
214 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
215 || rtw_cfg80211_get_is_roch(iface) == _TRUE
216 || (rtw_cfg80211_is_ro_ch_once(adapter)
217 && rtw_cfg80211_get_last_ro_ch_passing_ms(adapter) < 3000)
218 #endif
219 )
220 goto exit;
221
222 }
223 }
224
225 #if (MP_DRIVER == 1)
226 if (adapter->registrypriv.mp_mode == 1)
227 goto exit;
228 #endif
229
230 if (pxmit_priv->free_xmitbuf_cnt != xmitbuf_nr ||
231 pxmit_priv->free_xmit_extbuf_cnt != xmitbuf_ext_nr) {
232 RTW_PRINT("There are some pkts to transmit\n");
233 RTW_PRINT("free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
234 pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
235 goto exit;
236 }
237
238 ret = _TRUE;
239
240 exit:
241 return ret;
242 }
243
244
245 /*
246 * ATTENTION:
247 * rtw_ps_processor() doesn't handle LPS.
248 */
249
rtw_ps_processor(_adapter * padapter)250 void rtw_ps_processor(_adapter *padapter)
251 {
252 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
253 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
254 struct dvobj_priv *psdpriv = padapter->dvobj;
255 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
256 u32 ps_deny = 0;
257
258 _enter_pwrlock(&adapter_to_pwrctl(padapter)->lock);
259 ps_deny = rtw_ps_deny_get(padapter);
260 _exit_pwrlock(&adapter_to_pwrctl(padapter)->lock);
261 if (ps_deny != 0) {
262 if (!MLME_IS_MONITOR(padapter)) {
263 RTW_INFO(FUNC_ADPT_FMT ": ps_deny=0x%08X, skip power save!\n",
264 FUNC_ADPT_ARG(padapter), ps_deny);
265 }
266 goto exit;
267 }
268
269 if (pwrpriv->bInSuspend == _TRUE) { /* system suspend or autosuspend */
270 pdbgpriv->dbg_ps_insuspend_cnt++;
271 RTW_INFO("%s, pwrpriv->bInSuspend == _TRUE ignore this process\n", __FUNCTION__);
272 return;
273 }
274
275 pwrpriv->ps_processing = _TRUE;
276
277 if (pwrpriv->ips_mode_req == IPS_NONE)
278 goto exit;
279
280 if (rtw_pwr_unassociated_idle(padapter) == _FALSE)
281 goto exit;
282
283 if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts % 4) == 0)) {
284 RTW_INFO("==>%s .fw_state(%x)\n", __FUNCTION__, get_fwstate(pmlmepriv));
285 pwrpriv->change_rfpwrstate = rf_off;
286
287 #ifdef CONFIG_IPS
288 ips_enter(padapter);
289 #endif
290
291 }
292 exit:
293 #ifndef CONFIG_IPS_CHECK_IN_WD
294 rtw_set_pwr_state_check_timer(pwrpriv);
295 #endif
296 pwrpriv->ps_processing = _FALSE;
297 return;
298 }
299 #endif
300 #ifdef CONFIG_POWER_SAVING
pwr_state_check_handler(void * ctx)301 void pwr_state_check_handler(void *ctx)
302 {
303 _adapter *padapter = (_adapter *)ctx;
304 rtw_ps_cmd(padapter);
305 }
306 #endif
307 #ifdef CONFIG_LPS
308 #ifdef CONFIG_CHECK_LEAVE_LPS
309 #ifdef CONFIG_LPS_CHK_BY_TP
traffic_check_for_leave_lps_by_tp(_adapter * padapter,u8 tx,struct sta_info * sta)310 void traffic_check_for_leave_lps_by_tp(_adapter *padapter, u8 tx, struct sta_info *sta)
311 {
312 struct stainfo_stats *pstats = &sta->sta_stats;
313 u64 cur_acc_tx_bytes = 0, cur_acc_rx_bytes = 0;
314 u32 tx_tp_kbyte = 0, rx_tp_kbyte = 0;
315 u32 tx_tp_th = 0, rx_tp_th = 0;
316 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
317 u8 leave_lps = _FALSE;
318
319 if (tx) { /* from tx */
320 cur_acc_tx_bytes = pstats->tx_bytes - pstats->acc_tx_bytes;
321 tx_tp_kbyte = cur_acc_tx_bytes >> 10;
322 tx_tp_th = pwrpriv->lps_tx_tp_th * 1024 / 8 * 2; /*KBytes @2s*/
323
324 if (tx_tp_kbyte >= tx_tp_th ||
325 padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod >= pwrpriv->lps_tx_pkts){
326 if (pwrpriv->bLeisurePs
327 && (pwrpriv->pwr_mode != PM_PS_MODE_ACTIVE)
328 ) {
329 leave_lps = _TRUE;
330 }
331 }
332
333 } else { /* from rx path */
334 cur_acc_rx_bytes = pstats->rx_bytes - pstats->acc_rx_bytes;
335 rx_tp_kbyte = cur_acc_rx_bytes >> 10;
336 rx_tp_th = pwrpriv->lps_rx_tp_th * 1024 / 8 * 2;
337
338 if (rx_tp_kbyte>= rx_tp_th ||
339 padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod >= pwrpriv->lps_rx_pkts) {
340 if (pwrpriv->bLeisurePs
341 && (pwrpriv->pwr_mode != PM_PS_MODE_ACTIVE)
342 ) {
343 leave_lps = _TRUE;
344 }
345 }
346 }
347
348 if (leave_lps) {
349 #ifdef DBG_LPS_CHK_BY_TP
350 RTW_INFO("leave lps via %s, ", tx ? "Tx" : "Rx");
351 if (tx)
352 RTW_INFO("Tx = %d [%d] (KB)\n", tx_tp_kbyte, tx_tp_th);
353 else
354 RTW_INFO("Rx = %d [%d] (KB)\n", rx_tp_kbyte, rx_tp_th);
355 #endif
356 pwrpriv->lps_chk_cnt = pwrpriv->lps_chk_cnt_th;
357 /* rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 0); */
358 rtw_lps_ctrl_wk_cmd(padapter, tx ? LPS_CTRL_TX_TRAFFIC_LEAVE : LPS_CTRL_RX_TRAFFIC_LEAVE, 0);
359 }
360 }
361 #endif /*CONFIG_LPS_CHK_BY_TP*/
362
traffic_check_for_leave_lps(_adapter * padapter,u8 tx,u32 tx_packets)363 void traffic_check_for_leave_lps(_adapter *padapter, u8 tx, u32 tx_packets)
364 {
365 static systime start_time = 0;
366 static u32 xmit_cnt = 0;
367 u8 bLeaveLPS = _FALSE;
368 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
369
370
371
372 if (tx) { /* from tx */
373 xmit_cnt += tx_packets;
374
375 if (start_time == 0)
376 start_time = rtw_get_current_time();
377
378 if (rtw_get_passing_time_ms(start_time) > 2000) { /* 2 sec == watch dog timer */
379 if (xmit_cnt > 8) {
380 if ((adapter_to_pwrctl(padapter)->bLeisurePs)
381 && (adapter_to_pwrctl(padapter)->pwr_mode != PM_PS_MODE_ACTIVE)
382 ) {
383 /* RTW_INFO("leave lps via Tx = %d\n", xmit_cnt); */
384 bLeaveLPS = _TRUE;
385 }
386 }
387
388 start_time = rtw_get_current_time();
389 xmit_cnt = 0;
390 }
391
392 } else { /* from rx path */
393 if (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/) {
394 if ((adapter_to_pwrctl(padapter)->bLeisurePs)
395 && (adapter_to_pwrctl(padapter)->pwr_mode != PM_PS_MODE_ACTIVE)
396 ) {
397 /* RTW_INFO("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */
398 bLeaveLPS = _TRUE;
399 }
400 }
401 }
402
403 if (bLeaveLPS) {
404 /* RTW_INFO("leave lps via %s, Tx = %d, Rx = %d\n", tx?"Tx":"Rx", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */
405 /* rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 0); */
406 rtw_lps_ctrl_wk_cmd(padapter, tx ? LPS_CTRL_TX_TRAFFIC_LEAVE : LPS_CTRL_RX_TRAFFIC_LEAVE, tx ? RTW_CMDF_DIRECTLY : 0);
407 }
408 }
409 #endif /* CONFIG_CHECK_LEAVE_LPS */
410
411 #ifdef CONFIG_LPS_LCLK
412 #define LPS_CPWM_TIMEOUT_MS 10 /*ms*/
413 #define LPS_RPWM_RETRY_CNT 3
414
rtw_cpwm_polling(_adapter * adapter,u8 rpwm,u8 cpwm_orig)415 u8 rtw_cpwm_polling(_adapter *adapter, u8 rpwm, u8 cpwm_orig)
416 {
417 u8 rst = _FAIL;
418 u8 cpwm_now = 0;
419 systime start_time;
420 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
421 #ifdef DBG_CHECK_FW_PS_STATE
422 struct debug_priv *pdbgpriv = &(adapter_to_dvobj(adapter)->drv_dbg);
423 #endif
424
425 pwrpriv->rpwm_retry = 0;
426
427 do {
428 start_time = rtw_get_current_time();
429 do {
430 rtw_msleep_os(1);
431 rtw_hal_get_hwreg(adapter, HW_VAR_CPWM, &cpwm_now);
432
433 if ((cpwm_orig ^ cpwm_now) & 0x80) {
434 pwrpriv->cpwm = PS_STATE_S4;
435 pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE;
436 rst = _SUCCESS;
437 break;
438 }
439 } while (rtw_get_passing_time_ms(start_time) < LPS_CPWM_TIMEOUT_MS && !RTW_CANNOT_RUN(adapter_to_dvobj(adapter)));
440
441 if (rst == _SUCCESS)
442 break;
443 else {
444 /* rpwm retry */
445 cpwm_orig = cpwm_now;
446 rpwm &= ~PS_TOGGLE;
447 rpwm |= pwrpriv->tog;
448 rtw_hal_set_hwreg(adapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
449 pwrpriv->tog += 0x80;
450 }
451 } while (pwrpriv->rpwm_retry++ < LPS_RPWM_RETRY_CNT && !RTW_CANNOT_RUN(adapter_to_dvobj(adapter)));
452
453 if (rst == _SUCCESS) {
454 #ifdef DBG_CHECK_FW_PS_STATE
455 RTW_INFO("%s: polling cpwm OK! rpwm_retry=%d, cpwm_orig=%02x, cpwm_now=%02x , 0x100=0x%x\n"
456 , __func__, pwrpriv->rpwm_retry, cpwm_orig, cpwm_now, rtw_read8(adapter, REG_CR));
457 if (rtw_fw_ps_state(adapter) == _FAIL) {
458 RTW_INFO("leave 32k but fw state in 32k\n");
459 pdbgpriv->dbg_rpwm_toogle_cnt++;
460 }
461 #endif /* DBG_CHECK_FW_PS_STATE */
462 } else {
463 RTW_ERR("%s: polling cpwm timeout! rpwm_retry=%d, cpwm_orig=%02x, cpwm_now=%02x\n"
464 , __func__, pwrpriv->rpwm_retry, cpwm_orig, cpwm_now);
465 #ifdef DBG_CHECK_FW_PS_STATE
466 if (rtw_fw_ps_state(adapter) == _FAIL) {
467 RTW_INFO("rpwm timeout and fw ps state in 32k\n");
468 pdbgpriv->dbg_rpwm_timeout_fail_cnt++;
469 }
470 #endif /* DBG_CHECK_FW_PS_STATE */
471
472 #ifdef CONFIG_LPS_RPWM_TIMER
473 _set_timer(&pwrpriv->pwr_rpwm_timer, 1);
474 #endif /* CONFIG_LPS_RPWM_TIMER */
475 }
476
477 return rst;
478 }
479 #endif
480 /*
481 * Description:
482 * This function MUST be called under power lock protect
483 *
484 * Parameters
485 * padapter
486 * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
487 *
488 */
rtw_set_rpwm(_adapter * padapter,u8 pslv)489 u8 rtw_set_rpwm(_adapter *padapter, u8 pslv)
490 {
491 u8 rpwm = 0xFF;
492 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
493 #ifdef CONFIG_LPS_LCLK
494 u8 cpwm_orig;
495 #endif
496 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
497
498 pslv = PS_STATE(pslv);
499
500 #ifdef CONFIG_LPS_RPWM_TIMER
501 if (pwrpriv->brpwmtimeout == _TRUE)
502 RTW_INFO("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __FUNCTION__, pslv);
503 else
504 #endif /* CONFIG_LPS_RPWM_TIMER */
505 {
506 if ((pwrpriv->rpwm == pslv)
507 #ifdef CONFIG_LPS_LCLK
508 || ((pwrpriv->rpwm >= PS_STATE_S2) && (pslv >= PS_STATE_S2))
509 #endif
510 || (pwrpriv->lps_level == LPS_NORMAL)
511 ) {
512 return rpwm;
513 }
514 }
515
516 if (dev_is_surprise_removed(dvobj) ||
517 (!rtw_hw_is_init_completed(dvobj))) {
518
519 pwrpriv->cpwm = PS_STATE_S4;
520
521 return rpwm;
522 }
523
524 if (dev_is_drv_stopped(dvobj))
525 if (pslv < PS_STATE_S2)
526 return rpwm;
527
528 rpwm = pslv | pwrpriv->tog;
529 #ifdef CONFIG_LPS_LCLK
530 /* only when from PS_STATE S0/S1 to S2 and higher needs ACK */
531 if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2))
532 rpwm |= PS_ACK;
533 #endif
534
535 pwrpriv->rpwm = pslv;
536
537 #ifdef CONFIG_LPS_LCLK
538 cpwm_orig = 0;
539 if (rpwm & PS_ACK)
540 rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig);
541 #endif
542
543 #if defined(CONFIG_LPS_RPWM_TIMER) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
544 if (rpwm & PS_ACK) {
545 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) || defined(CONFIG_P2P_WOWLAN)
546 if (pwrpriv->wowlan_mode != _TRUE &&
547 pwrpriv->wowlan_ap_mode != _TRUE &&
548 pwrpriv->wowlan_p2p_mode != _TRUE)
549 #endif
550 _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_CPWM_TIMEOUT_MS);
551 }
552 #endif /* CONFIG_LPS_RPWM_TIMER & !CONFIG_DETECT_CPWM_BY_POLLING */
553
554 rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
555
556 pwrpriv->tog += 0x80;
557
558 #ifdef CONFIG_LPS_LCLK
559 /* No LPS 32K, No Ack */
560 if (rpwm & PS_ACK) {
561 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
562 rtw_cpwm_polling(padapter, rpwm, cpwm_orig);
563 #else
564 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) || defined(CONFIG_P2P_WOWLAN)
565 if (pwrpriv->wowlan_mode == _TRUE ||
566 pwrpriv->wowlan_ap_mode == _TRUE ||
567 pwrpriv->wowlan_p2p_mode == _TRUE)
568 rtw_cpwm_polling(padapter, rpwm, cpwm_orig);
569 #endif /*#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) || defined(CONFIG_P2P_WOWLAN)*/
570 #endif /*#ifdef CONFIG_DETECT_CPWM_BY_POLLING*/
571 } else
572 #endif /* CONFIG_LPS_LCLK */
573 {
574 pwrpriv->cpwm = pslv;
575 }
576
577 return rpwm;
578 }
579
PS_RDY_CHECK(_adapter * padapter)580 u8 PS_RDY_CHECK(_adapter *padapter)
581 {
582 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
583 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
584
585 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
586 if (_TRUE == pwrpriv->bInSuspend && pwrpriv->wowlan_mode)
587 return _TRUE;
588 else if (_TRUE == pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode)
589 return _TRUE;
590 else if (_TRUE == pwrpriv->bInSuspend)
591 return _FALSE;
592 #else
593 if (_TRUE == pwrpriv->bInSuspend)
594 return _FALSE;
595 #endif
596
597 if (rtw_time_after(pwrpriv->lps_deny_time, rtw_get_current_time()))
598 return _FALSE;
599
600 if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY)
601 || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS)
602 || MLME_IS_AP(padapter)
603 || MLME_IS_MESH(padapter)
604 || MLME_IS_MONITOR(padapter)
605 || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE)
606 #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
607 || rtw_cfg80211_get_is_roch(padapter) == _TRUE
608 #endif
609 || rtw_is_scan_deny(padapter)
610 #ifdef CONFIG_TDLS
611 /* TDLS link is established. */
612 || (padapter->tdlsinfo.link_established == _TRUE)
613 #endif /* CONFIG_TDLS */
614 #ifdef CONFIG_DFS_MASTER
615 || adapter_to_rfctl(padapter)->radar_detect_enabled
616 #endif
617 )
618 return _FALSE;
619
620 if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == _FALSE)) {
621 RTW_INFO("Group handshake still in progress !!!\n");
622 return _FALSE;
623 }
624
625 #ifdef CONFIG_IOCTL_CFG80211
626 if (!rtw_cfg80211_pwr_mgmt(padapter))
627 return _FALSE;
628 #endif
629
630 return _TRUE;
631 }
632
rtw_leave_lps_and_chk(_adapter * padapter,u8 ps_mode)633 void rtw_leave_lps_and_chk(_adapter *padapter, u8 ps_mode)
634 {
635 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
636
637 #ifdef CONFIG_LPS_ACK
638 _rtw_mutex_lock_interruptible(&pwrpriv->lps_ack_mutex);
639 rtw_sctx_init(&pwrpriv->lps_ack_sctx, 100);
640 #endif /* CONFIG_LPS_ACK */
641 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
642 rtw_hal_set_hwreg(padapter, HW_VAR_LPS_STATE_CHK, (u8 *)(&ps_mode));
643
644 #ifdef CONFIG_LPS_ACK
645 _rtw_mutex_unlock(&pwrpriv->lps_ack_mutex);
646 #endif /* CONFIG_LPS_ACK */
647
648 }
649
rtw_set_ps_mode(_adapter * padapter,u8 ps_mode,u8 smart_ps,u8 bcn_ant_mode,const char * msg)650 void rtw_set_ps_mode(_adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode, const char *msg)
651 {
652 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
653 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
654 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) || defined(CONFIG_P2P_WOWLAN)
655 struct dvobj_priv *psdpriv = padapter->dvobj;
656 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
657 #endif
658 #ifdef CONFIG_WMMPS_STA
659 struct registry_priv *pregistrypriv = &padapter->registrypriv;
660 #endif
661 #ifdef CONFIG_P2P
662 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
663 #endif /* CONFIG_P2P */
664 #ifdef CONFIG_TDLS
665 struct sta_priv *pstapriv = &padapter->stapriv;
666 int i, j;
667 _list *plist, *phead;
668 struct sta_info *ptdls_sta;
669 #endif /* CONFIG_TDLS */
670 #ifdef CONFIG_LPS_PG
671 u8 lps_pg_hdl_id = 0;
672 #endif
673
674
675
676 if (ps_mode > PM_CARD_DISABLE) {
677 return;
678 }
679
680 if (pwrpriv->pwr_mode == ps_mode) {
681 if (PM_PS_MODE_ACTIVE == ps_mode)
682 return;
683
684 #ifndef CONFIG_BTC
685 #ifdef CONFIG_WMMPS_STA
686 if (!rtw_is_wmmps_mode(padapter))
687 #endif /* CONFIG_WMMPS_STA */
688 if ((pwrpriv->smart_ps == smart_ps) &&
689 (pwrpriv->bcn_ant_mode == bcn_ant_mode))
690 return;
691 #endif /* !CONFIG_BTC */
692 }
693
694 #ifdef CONFIG_FW_MULTI_PORT_SUPPORT
695 if (PM_PS_MODE_ACTIVE != ps_mode) {
696 rtw_set_ps_rsvd_page(padapter);
697 rtw_set_default_port_id(padapter);
698 }
699 #endif
700
701 #ifdef CONFIG_LPS_PG
702 if ((PM_PS_MODE_ACTIVE != ps_mode) && (pwrpriv->lps_level == LPS_PG)) {
703 if (pwrpriv->wowlan_mode != _TRUE) {
704 /*rtw_hal_set_lps_pg_info(padapter);*/
705 lps_pg_hdl_id = LPS_PG_INFO_CFG;
706 rtw_hal_set_hwreg(padapter, HW_VAR_LPS_PG_HANDLE, (u8 *)(&lps_pg_hdl_id));
707 }
708 }
709 #endif
710
711 #ifdef CONFIG_LPS_LCLK
712 _enter_pwrlock(&pwrpriv->lock);
713 #endif
714
715 /* if(pwrpriv->pwr_mode == PM_PS_MODE_ACTIVE) */
716 if (ps_mode == PM_PS_MODE_ACTIVE) {
717 if (1
718 #ifdef CONFIG_P2P_PS
719 && (pwdinfo->opp_ps == 0)
720 #endif /* CONFIG_P2P_PS */
721 ) {
722 RTW_INFO(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n",
723 FUNC_ADPT_ARG(padapter), msg);
724
725 if (pwrpriv->lps_leave_cnts < UINT_MAX)
726 pwrpriv->lps_leave_cnts++;
727 else
728 pwrpriv->lps_leave_cnts = 0;
729 #ifdef CONFIG_TDLS
730 for (i = 0; i < NUM_STA; i++) {
731 phead = &(pstapriv->sta_hash[i]);
732 plist = get_next(phead);
733
734 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
735 ptdls_sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
736
737 if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)
738 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->phl_sta->mac_addr, 0, 0, 0);
739 plist = get_next(plist);
740 }
741 }
742 #endif /* CONFIG_TDLS */
743
744 pwrpriv->pwr_mode = ps_mode;
745 rtw_set_rpwm(padapter, PS_STATE_S4);
746
747 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) || defined(CONFIG_P2P_WOWLAN)
748 if (pwrpriv->wowlan_mode == _TRUE ||
749 pwrpriv->wowlan_ap_mode == _TRUE ||
750 pwrpriv->wowlan_p2p_mode == _TRUE) {
751 systime start_time;
752 u32 delay_ms;
753 u8 val8;
754 delay_ms = 20;
755 start_time = rtw_get_current_time();
756 do {
757 rtw_hal_get_hwreg(padapter, HW_VAR_SYS_CLKR, &val8);
758 if (!(val8 & BIT(4))) { /* 0x08 bit4 =1 --> in 32k, bit4 = 0 --> leave 32k */
759 pwrpriv->cpwm = PS_STATE_S4;
760 break;
761 }
762 if (rtw_get_passing_time_ms(start_time) > delay_ms) {
763 RTW_INFO("%s: Wait for FW 32K leave more than %u ms!!!\n",
764 __FUNCTION__, delay_ms);
765 pdbgpriv->dbg_wow_leave_ps_fail_cnt++;
766 break;
767 }
768 rtw_usleep_os(100);
769 } while (1);
770 }
771 #endif
772 #ifdef CONFIG_LPS_PG
773 if (pwrpriv->lps_level == LPS_PG) {
774 lps_pg_hdl_id = LPS_PG_REDLEMEM;
775 rtw_hal_set_hwreg(padapter, HW_VAR_LPS_PG_HANDLE, (u8 *)(&lps_pg_hdl_id));
776 }
777 #endif
778 #ifdef CONFIG_WOWLAN
779 if (pwrpriv->wowlan_mode == _TRUE)
780 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_INACTIVE_IPS, (u8 *)(&ps_mode));
781 #endif /* CONFIG_WOWLAN */
782
783 rtw_leave_lps_and_chk(padapter, ps_mode);
784
785 #ifdef CONFIG_LPS_PG
786 if (pwrpriv->lps_level == LPS_PG) {
787 lps_pg_hdl_id = LPS_PG_PHYDM_EN;
788 rtw_hal_set_hwreg(padapter, HW_VAR_LPS_PG_HANDLE, (u8 *)(&lps_pg_hdl_id));
789 }
790 #endif
791
792 pwrpriv->bFwCurrentInPSMode = _FALSE;
793 }
794 } else {
795 if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE))
796 #ifdef CONFIG_P2P_WOWLAN
797 || (_TRUE == pwrpriv->wowlan_p2p_mode)
798 #endif /* CONFIG_P2P_WOWLAN */
799 #ifdef CONFIG_WOWLAN
800 || WOWLAN_IS_STA_MIX_MODE(padapter)
801 #endif /* CONFIG_WOWLAN */
802 ) {
803 u8 pslv;
804
805 RTW_INFO(FUNC_ADPT_FMT" Enter 802.11 power save - %s\n",
806 FUNC_ADPT_ARG(padapter), msg);
807
808 if (pwrpriv->lps_enter_cnts < UINT_MAX)
809 pwrpriv->lps_enter_cnts++;
810 else
811 pwrpriv->lps_enter_cnts = 0;
812 #ifdef CONFIG_TDLS
813 for (i = 0; i < NUM_STA; i++) {
814 phead = &(pstapriv->sta_hash[i]);
815 plist = get_next(phead);
816
817 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
818 ptdls_sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
819
820 if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)
821 issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->phl_sta->mac_addr, 1, 0, 0);
822 plist = get_next(plist);
823 }
824 }
825 #endif /* CONFIG_TDLS */
826
827 pwrpriv->bFwCurrentInPSMode = _TRUE;
828 pwrpriv->pwr_mode = ps_mode;
829 pwrpriv->smart_ps = smart_ps;
830 pwrpriv->bcn_ant_mode = bcn_ant_mode;
831 #ifdef CONFIG_LPS_PG
832 if (pwrpriv->lps_level == LPS_PG) {
833 lps_pg_hdl_id = LPS_PG_PHYDM_DIS;
834 rtw_hal_set_hwreg(padapter, HW_VAR_LPS_PG_HANDLE, (u8 *)(&lps_pg_hdl_id));
835 }
836 #endif
837
838 #ifdef CONFIG_WMMPS_STA
839 pwrpriv->wmm_smart_ps = pregistrypriv->wmm_smart_ps;
840 #endif /* CONFIG_WMMPS_STA */
841
842
843 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE))
844 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
845 #ifdef CONFIG_WOWLAN
846 if (pwrpriv->wowlan_mode == _TRUE)
847 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_INACTIVE_IPS, (u8 *)(&ps_mode));
848 #endif /* CONFIG_WOWLAN */
849
850 #ifdef CONFIG_P2P_PS
851 /* Set CTWindow after LPS */
852 if (pwdinfo->opp_ps == 1)
853 p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0);
854 #endif /* CONFIG_P2P_PS */
855
856 pslv = PS_STATE_S2;
857 #ifdef CONFIG_LPS_LCLK
858 if (pwrpriv->alives == 0)
859 pslv = PS_STATE_S0;
860 #endif /* CONFIG_LPS_LCLK */
861
862 rtw_set_rpwm(padapter, pslv);
863 }
864 }
865
866 #ifdef CONFIG_LPS_LCLK
867 _exit_pwrlock(&pwrpriv->lock);
868 #endif
869
870 }
871
872 const char * const LPS_CTRL_PHYDM = "LPS_CTRL_PHYDM";
873
874 /*
875 * Description:
876 * Enter the leisure power save mode.
877 * */
LPS_Enter(_adapter * padapter,const char * msg)878 void LPS_Enter(_adapter *padapter, const char *msg)
879 {
880 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
881 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
882 int i;
883 char buf[32] = {0};
884 #ifdef DBG_LA_MODE
885 struct registry_priv *registry_par = &(padapter->registrypriv);
886 #endif
887
888 /* RTW_INFO("+LeisurePSEnter\n"); */
889 #if 0 /*GEORGIA_TODO_FIXIT*/
890 if (GET_PHL_COM(dvobj)->fw_ready == _FALSE)
891 return;
892 #endif
893
894 #ifdef DBG_LA_MODE
895 if(registry_par->la_mode_en == 1) {
896 RTW_INFO("%s LA debug mode lps_leave \n", __func__);
897 return;
898 }
899 #endif
900 /* Skip lps enter request if number of assocated adapters is not 1 */
901 if (rtw_mi_get_assoc_if_num(padapter) != 1)
902 return;
903
904 #ifndef CONFIG_FW_MULTI_PORT_SUPPORT
905 /* Skip lps enter request for adapter not port0 */
906 if (get_hw_port(padapter) != HW_PORT0)
907 return;
908 #endif
909
910 for (i = 0; i < dvobj->iface_nums; i++) {
911 if (PS_RDY_CHECK(dvobj->padapters[i]) == _FALSE)
912 return;
913 }
914
915
916 #ifdef CONFIG_P2P_PS
917 if (padapter->wdinfo.p2p_ps_mode == P2P_PS_NOA) {
918 return;/* supporting p2p client ps NOA via H2C_8723B_P2P_PS_OFFLOAD */
919 }
920 #endif /* CONFIG_P2P_PS */
921
922 if (pwrpriv->bLeisurePs) {
923 /* Idle for a while if we connect to AP a while ago. */
924 if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */
925 if (pwrpriv->pwr_mode == PM_PS_MODE_ACTIVE) {
926
927 #ifdef CONFIG_WMMPS_STA
928 if (rtw_is_wmmps_mode(padapter))
929 msg = "WMMPS_IDLE";
930 #endif /* CONFIG_WMMPS_STA */
931
932 sprintf(buf, "WIFI-%s", msg);
933 pwrpriv->bpower_saving = _TRUE;
934
935 #ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
936 pwrpriv->pwr_saving_start_time = rtw_get_current_time();
937 #endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
938
939 rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, padapter->registrypriv.smart_ps, 0, buf);
940
941 #ifdef CONFIG_PCI_DYNAMIC_ASPM
942 if (msg != LPS_CTRL_PHYDM)
943 rtw_pci_dynamic_aspm_set_mode(padapter, ASPM_MODE_PS);
944 #endif
945 }
946 } else
947 pwrpriv->LpsIdleCount++;
948 }
949
950 /* RTW_INFO("-LeisurePSEnter\n"); */
951
952 }
953
954 /*
955 * Description:
956 * Leave the leisure power save mode.
957 * */
LPS_Leave(_adapter * padapter,const char * msg)958 void LPS_Leave(_adapter *padapter, const char *msg)
959 {
960 #define LPS_LEAVE_TIMEOUT_MS 100
961
962 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
963 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
964 char buf[32] = {0};
965 #ifdef DBG_CHECK_FW_PS_STATE
966 struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
967 #endif
968
969
970 /* RTW_INFO("+LeisurePSLeave\n"); */
971
972 if (pwrpriv->bLeisurePs) {
973 if (pwrpriv->pwr_mode != PM_PS_MODE_ACTIVE) {
974 #ifdef CONFIG_PCI_DYNAMIC_ASPM
975 if (msg != LPS_CTRL_PHYDM)
976 rtw_pci_dynamic_aspm_set_mode(padapter, ASPM_MODE_PERF);
977 #endif
978 #ifdef CONFIG_WMMPS_STA
979 if (rtw_is_wmmps_mode(padapter))
980 msg = "WMMPS_BUSY";
981 #endif /* CONFIG_WMMPS_STA */
982
983 sprintf(buf, "WIFI-%s", msg);
984 rtw_set_ps_mode(padapter, PM_PS_MODE_ACTIVE, 0, 0, buf);
985
986 #ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
987 pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);
988 #endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
989 }
990 }
991
992 pwrpriv->bpower_saving = _FALSE;
993 #ifdef DBG_CHECK_FW_PS_STATE
994 if (rtw_fw_ps_state(padapter) == _FAIL) {
995 RTW_INFO("leave lps, fw in 32k\n");
996 pdbgpriv->dbg_leave_lps_fail_cnt++;
997 }
998 #endif /* DBG_CHECK_FW_PS_STATE
999 * RTW_INFO("-LeisurePSLeave\n"); */
1000
1001 }
1002
1003 #endif /* CONFIG_LPS */
1004
LeaveAllPowerSaveModeDirect(_adapter * adapter)1005 void LeaveAllPowerSaveModeDirect(_adapter *adapter)
1006 {
1007 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
1008 _adapter *pri_padapter = GET_PRIMARY_ADAPTER(adapter);
1009 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
1010
1011 #ifdef CONFIG_LPS_LCLK
1012 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1013 u8 cpwm_orig;
1014 #endif /* CONFIG_DETECT_CPWM_BY_POLLING */
1015 u8 rpwm;
1016 #endif
1017 int i;
1018
1019 RTW_INFO("%s.....\n", __FUNCTION__);
1020
1021 if (dev_is_surprise_removed(adapter_to_dvobj(adapter))) {
1022 RTW_INFO(FUNC_ADPT_FMT ": bSurpriseRemoved=_TRUE Skip!\n", FUNC_ADPT_ARG(adapter));
1023 return;
1024 }
1025
1026 if (rtw_mi_check_status(adapter, MI_LINKED)) { /*connect*/
1027
1028 if (pwrpriv->pwr_mode == PM_PS_MODE_ACTIVE) {
1029 RTW_INFO("%s: Driver Already Leave LPS\n", __FUNCTION__);
1030 return;
1031 }
1032
1033 #ifdef CONFIG_LPS_LCLK
1034 _enter_pwrlock(&pwrpriv->lock);
1035
1036 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1037 cpwm_orig = 0;
1038 rtw_hal_get_hwreg(adapter, HW_VAR_CPWM, &cpwm_orig);
1039 #endif /* CONFIG_DETECT_CPWM_BY_POLLING */
1040 rpwm = rtw_set_rpwm(adapter, PS_STATE_S4);
1041
1042 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1043 if (rpwm != 0xFF && rpwm & PS_ACK)
1044 rtw_cpwm_polling(adapter, rpwm, cpwm_orig);
1045 #endif /* CONFIG_DETECT_CPWM_BY_POLLING */
1046
1047 _exit_pwrlock(&pwrpriv->lock);
1048 #endif/*CONFIG_LPS_LCLK*/
1049
1050 #ifdef CONFIG_P2P_PS
1051 for (i = 0; i < dvobj->iface_nums; i++) {
1052 _adapter *iface = dvobj->padapters[i];
1053 struct wifidirect_info *pwdinfo = &(iface->wdinfo);
1054
1055 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
1056 p2p_ps_wk_cmd(iface, P2P_PS_DISABLE, 0);
1057 }
1058 #endif /* CONFIG_P2P_PS */
1059
1060 #ifdef CONFIG_LPS
1061 rtw_lps_ctrl_wk_cmd(pri_padapter, LPS_CTRL_LEAVE, RTW_CMDF_DIRECTLY);
1062 #endif
1063 } else {
1064 if (pwrpriv->rf_pwrstate == rf_off) {
1065
1066 #if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS)
1067 #ifdef CONFIG_IPS
1068 if (_FALSE == ips_leave(pri_padapter))
1069 RTW_INFO("======> ips_leave fail.............\n");
1070 #endif
1071 #endif /* defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS) */
1072
1073 }
1074 }
1075
1076 }
1077
1078 /*
1079 * Description: Leave all power save mode: LPS, FwLPS, IPS if needed.
1080 * Move code to function by tynli. 2010.03.26.
1081 * */
LeaveAllPowerSaveMode(_adapter * adapter)1082 void LeaveAllPowerSaveMode(_adapter *adapter)
1083 {
1084 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
1085 u8 enqueue = 0;
1086 int i;
1087
1088
1089 /* RTW_INFO(FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(adapter));*/
1090
1091 if (dev_is_surprise_removed(adapter_to_dvobj(adapter))) {
1092 RTW_INFO(FUNC_ADPT_FMT ": bSurpriseRemoved=_TRUE Skip!\n", FUNC_ADPT_ARG(adapter));
1093 return;
1094 }
1095
1096 if (rtw_mi_get_assoc_if_num(adapter)) {
1097 /* connect */
1098 #ifdef CONFIG_LPS_LCLK
1099 enqueue = 1;
1100 #endif
1101
1102 #ifdef CONFIG_P2P_PS
1103 for (i = 0; i < dvobj->iface_nums; i++) {
1104 _adapter *iface = dvobj->padapters[i];
1105 struct wifidirect_info *pwdinfo = &(iface->wdinfo);
1106
1107 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
1108 p2p_ps_wk_cmd(iface, P2P_PS_DISABLE, enqueue);
1109 }
1110 #endif /* CONFIG_P2P_PS */
1111
1112 #ifdef CONFIG_LPS
1113 rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_LEAVE, enqueue ? 0 : RTW_CMDF_DIRECTLY);
1114 #endif
1115
1116 #ifdef CONFIG_LPS_LCLK
1117 LPS_Leave_check(adapter);
1118 #endif
1119 } else {
1120 if (adapter_to_pwrctl(adapter)->rf_pwrstate == rf_off) {
1121
1122 #if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS)
1123 #ifdef CONFIG_IPS
1124 if (_FALSE == ips_leave(adapter))
1125 RTW_INFO("======> ips_leave fail.............\n");
1126 #endif
1127 #endif /* defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS) */
1128
1129 }
1130 }
1131
1132 }
1133
1134 #ifdef CONFIG_LPS_LCLK
LPS_Leave_check(_adapter * padapter)1135 void LPS_Leave_check(
1136 _adapter *padapter)
1137 {
1138 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1139 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1140 systime start_time;
1141 u8 bReady;
1142
1143 bReady = _FALSE;
1144 start_time = rtw_get_current_time();
1145
1146 rtw_yield_os();
1147
1148 while (1) {
1149 _enter_pwrlock(&pwrpriv->lock);
1150
1151 if (dev_is_surprise_removed(dvobj)
1152 || (!rtw_hw_is_init_completed(dvobj))
1153 #ifdef CONFIG_USB_HCI
1154 || dev_is_drv_stopped(dvobj)
1155 #endif
1156 || (pwrpriv->pwr_mode == PM_PS_MODE_ACTIVE)
1157 )
1158 bReady = _TRUE;
1159
1160 _exit_pwrlock(&pwrpriv->lock);
1161
1162 if (_TRUE == bReady)
1163 break;
1164
1165 if (rtw_get_passing_time_ms(start_time) > 100) {
1166 RTW_ERR("Wait for cpwm event than 100 ms!!!\n");
1167 break;
1168 }
1169 rtw_msleep_os(1);
1170 }
1171
1172 }
1173
1174 /*
1175 * Caller:ISR handler...
1176 *
1177 * This will be called when CPWM interrupt is up.
1178 *
1179 * using to update cpwn of drv; and drv willl make a decision to up or down pwr level
1180 */
cpwm_int_hdl(_adapter * padapter,struct reportpwrstate_parm * preportpwrstate)1181 void cpwm_int_hdl(
1182 _adapter *padapter,
1183 struct reportpwrstate_parm *preportpwrstate)
1184 {
1185 struct pwrctrl_priv *pwrpriv;
1186
1187 if (!padapter)
1188 goto exit;
1189
1190 if (RTW_CANNOT_RUN(adapter_to_dvobj(padapter)))
1191 goto exit;
1192
1193 pwrpriv = adapter_to_pwrctl(padapter);
1194 #if 0
1195 if (pwrpriv->cpwm_tog == (preportpwrstate->state & PS_TOGGLE)) {
1196 goto exit;
1197 }
1198 #endif
1199
1200 _enter_pwrlock(&pwrpriv->lock);
1201
1202 #ifdef CONFIG_LPS_RPWM_TIMER
1203 if (pwrpriv->rpwm < PS_STATE_S2) {
1204 RTW_INFO("%s: Redundant CPWM Int. RPWM=0x%02X CPWM=0x%02x\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1205 _exit_pwrlock(&pwrpriv->lock);
1206 goto exit;
1207 }
1208 #endif /* CONFIG_LPS_RPWM_TIMER */
1209
1210 pwrpriv->cpwm = PS_STATE(preportpwrstate->state);
1211 pwrpriv->cpwm_tog = preportpwrstate->state & PS_TOGGLE;
1212
1213 if (pwrpriv->cpwm >= PS_STATE_S2) {
1214 #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/
1215 if (pwrpriv->alives & CMD_ALIVE)
1216 _rtw_up_sema(&padapter->cmdpriv.cmd_queue_sema);
1217 #endif
1218 #if 0 /*def CONFIG_XMIT_THREAD_MODE*/
1219 if (pwrpriv->alives & XMIT_ALIVE)
1220 _rtw_up_sema(&padapter->xmitpriv.xmit_sema);
1221 #endif
1222 }
1223
1224 _exit_pwrlock(&pwrpriv->lock);
1225
1226 exit:
1227 return;
1228 }
1229
cpwm_event_callback(struct work_struct * work)1230 static void cpwm_event_callback(struct work_struct *work)
1231 {
1232 struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, cpwm_event);
1233 struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
1234 _adapter *adapter = dvobj_get_primary_adapter(dvobj);
1235 struct reportpwrstate_parm report;
1236
1237 /* RTW_INFO("%s\n",__FUNCTION__); */
1238
1239 report.state = PS_STATE_S2;
1240 cpwm_int_hdl(adapter, &report);
1241 }
1242
dma_event_callback(struct work_struct * work)1243 static void dma_event_callback(struct work_struct *work)
1244 {
1245 struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, dma_event);
1246 struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
1247 _adapter *adapter = dvobj_get_primary_adapter(dvobj);
1248
1249 rtw_unregister_tx_alive(adapter);
1250 }
1251
1252 #ifdef CONFIG_LPS_RPWM_TIMER
1253
1254 #if defined(DBG_CPWM_CHK_FAIL)
1255 extern void rtw_cpwm_chk_fail_debug(_adapter *padapter, struct pwrctrl_priv *pwrpriv);
1256 #endif
1257
rpwmtimeout_workitem_callback(struct work_struct * work)1258 static void rpwmtimeout_workitem_callback(struct work_struct *work)
1259 {
1260 _adapter *padapter;
1261 struct dvobj_priv *dvobj;
1262 struct pwrctrl_priv *pwrpriv;
1263
1264
1265 pwrpriv = container_of(work, struct pwrctrl_priv, rpwmtimeoutwi);
1266 dvobj = pwrctl_to_dvobj(pwrpriv);
1267 padapter = dvobj_get_primary_adapter(dvobj);
1268
1269 if (!padapter)
1270 return;
1271
1272 if (RTW_CANNOT_RUN(dvobj))
1273 return;
1274
1275 _enter_pwrlock(&pwrpriv->lock);
1276 if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
1277 RTW_INFO("%s: rpwm=0x%02X cpwm=0x%02X CPWM done!\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1278 goto exit;
1279 }
1280
1281 if (pwrpriv->rpwm_retry++ < LPS_RPWM_RETRY_CNT) {
1282 u8 rpwm = (pwrpriv->rpwm | pwrpriv->tog | PS_ACK);
1283
1284 rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
1285
1286 pwrpriv->tog += 0x80;
1287 _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_CPWM_TIMEOUT_MS);
1288 goto exit;
1289 }
1290
1291 pwrpriv->rpwm_retry = 0;
1292 _exit_pwrlock(&pwrpriv->lock);
1293
1294 #if defined(DBG_CPWM_CHK_FAIL)
1295 rtw_cpwm_chk_fail_debug(padapter, pwrpriv);
1296 #endif
1297
1298 #if 0 /*GEORGIA_TODO_REDEFINE_IO*/
1299 if (rtw_read8(padapter, 0x100) != 0xEA)
1300 #else
1301 if (!rtw_hal_is_leave_ps(padapter))
1302 #endif
1303
1304 {
1305 #if 1
1306 struct reportpwrstate_parm report;
1307
1308 report.state = PS_STATE_S2;
1309 RTW_INFO("\n%s: FW already leave 32K!\n\n", __func__);
1310 cpwm_int_hdl(padapter, &report);
1311 #else
1312 RTW_INFO("\n%s: FW already leave 32K!\n\n", __func__);
1313 cpwm_event_callback(&pwrpriv->cpwm_event);
1314 #endif
1315 return;
1316 }
1317
1318 _enter_pwrlock(&pwrpriv->lock);
1319
1320 if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
1321 RTW_INFO("%s: cpwm=%d, nothing to do!\n", __func__, pwrpriv->cpwm);
1322 goto exit;
1323 }
1324 pwrpriv->brpwmtimeout = _TRUE;
1325 rtw_set_rpwm(padapter, pwrpriv->rpwm);
1326 pwrpriv->brpwmtimeout = _FALSE;
1327
1328 exit:
1329 _exit_pwrlock(&pwrpriv->lock);
1330 }
1331
1332 /*
1333 * This function is a timer handler, can't do any IO in it.
1334 */
pwr_rpwm_timeout_handler(void * FunctionContext)1335 static void pwr_rpwm_timeout_handler(void *FunctionContext)
1336 {
1337 _adapter *padapter;
1338 struct pwrctrl_priv *pwrpriv;
1339
1340 padapter = (_adapter *)FunctionContext;
1341 if (!padapter)
1342 return;
1343
1344 pwrpriv = adapter_to_pwrctl(padapter);
1345
1346 if (RTW_CANNOT_RUN(adapter_to_dvobj(padapter)))
1347 return;
1348
1349 RTW_INFO("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
1350
1351 if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
1352 RTW_INFO("+%s: cpwm=%d, nothing to do!\n", __func__, pwrpriv->cpwm);
1353 return;
1354 }
1355
1356 _set_workitem(&pwrpriv->rpwmtimeoutwi);
1357 }
1358 #endif /* CONFIG_LPS_RPWM_TIMER */
1359
register_task_alive(struct pwrctrl_priv * pwrctrl,u32 tag)1360 __inline static void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
1361 {
1362 pwrctrl->alives |= tag;
1363 }
1364
unregister_task_alive(struct pwrctrl_priv * pwrctrl,u32 tag)1365 __inline static void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
1366 {
1367 pwrctrl->alives &= ~tag;
1368 }
1369
1370
1371 /*
1372 * Description:
1373 * Check if the fw_pwrstate is okay for I/O.
1374 * If not (cpwm is less than S2), then the sub-routine
1375 * will raise the cpwm to be greater than or equal to S2.
1376 *
1377 * Calling Context: Passive
1378 *
1379 * Constraint:
1380 * 1. this function will request pwrctrl->lock
1381 *
1382 * Return Value:
1383 * _SUCCESS hardware is ready for I/O
1384 * _FAIL can't I/O right now
1385 */
rtw_register_task_alive(_adapter * padapter,u32 task)1386 s32 rtw_register_task_alive(_adapter *padapter, u32 task)
1387 {
1388 s32 res;
1389 struct pwrctrl_priv *pwrctrl;
1390 u8 pslv;
1391
1392
1393 res = _SUCCESS;
1394 pwrctrl = adapter_to_pwrctl(padapter);
1395 pslv = PS_STATE_S2;
1396
1397 _enter_pwrlock(&pwrctrl->lock);
1398
1399 register_task_alive(pwrctrl, task);
1400
1401 if (pwrctrl->bFwCurrentInPSMode == _TRUE) {
1402
1403 if (pwrctrl->cpwm < pslv) {
1404 if (pwrctrl->cpwm < PS_STATE_S2)
1405 res = _FAIL;
1406 if (pwrctrl->rpwm < pslv)
1407 rtw_set_rpwm(padapter, pslv);
1408 }
1409 }
1410
1411 _exit_pwrlock(&pwrctrl->lock);
1412
1413 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
1414 if (_FAIL == res) {
1415 if (pwrctrl->cpwm >= PS_STATE_S2)
1416 res = _SUCCESS;
1417 }
1418 #endif /* CONFIG_DETECT_CPWM_BY_POLLING */
1419
1420
1421 return res;
1422 }
1423
1424 /*
1425 * Description:
1426 * If task is done, call this func. to power down firmware again.
1427 *
1428 * Constraint:
1429 * 1. this function will request pwrctrl->lock
1430 *
1431 * Return Value:
1432 * none
1433 */
rtw_unregister_task_alive(_adapter * padapter,u32 task)1434 void rtw_unregister_task_alive(_adapter *padapter, u32 task)
1435 {
1436 struct pwrctrl_priv *pwrctrl;
1437 u8 pslv;
1438
1439
1440 pwrctrl = adapter_to_pwrctl(padapter);
1441 pslv = PS_STATE_S0;
1442
1443 _enter_pwrlock(&pwrctrl->lock);
1444
1445 unregister_task_alive(pwrctrl, task);
1446
1447 if ((pwrctrl->pwr_mode != PM_PS_MODE_ACTIVE)
1448 && (pwrctrl->bFwCurrentInPSMode == _TRUE)) {
1449
1450 if (pwrctrl->cpwm > pslv) {
1451 if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1452 rtw_set_rpwm(padapter, pslv);
1453 }
1454 }
1455
1456 _exit_pwrlock(&pwrctrl->lock);
1457
1458 }
1459
1460 /*
1461 * Caller: rtw_xmit_thread
1462 *
1463 * Check if the fw_pwrstate is okay for xmit.
1464 * If not (cpwm is less than S3), then the sub-routine
1465 * will raise the cpwm to be greater than or equal to S3.
1466 *
1467 * Calling Context: Passive
1468 *
1469 * Return Value:
1470 * _SUCCESS rtw_xmit_thread can write fifo/txcmd afterwards.
1471 * _FAIL rtw_xmit_thread can not do anything.
1472 */
rtw_register_tx_alive(_adapter * padapter)1473 s32 rtw_register_tx_alive(_adapter *padapter)
1474 {
1475 s32 res;
1476 struct pwrctrl_priv *pwrctrl;
1477 u8 pslv;
1478
1479
1480 res = _SUCCESS;
1481 pwrctrl = adapter_to_pwrctl(padapter);
1482 pslv = PS_STATE_S2;
1483
1484 _enter_pwrlock(&pwrctrl->lock);
1485
1486 register_task_alive(pwrctrl, XMIT_ALIVE);
1487
1488 if (pwrctrl->bFwCurrentInPSMode == _TRUE) {
1489
1490 if (pwrctrl->cpwm < pslv) {
1491 if (pwrctrl->cpwm < PS_STATE_S2)
1492 res = _FAIL;
1493 if (pwrctrl->rpwm < pslv)
1494 rtw_set_rpwm(padapter, pslv);
1495 }
1496 }
1497
1498 _exit_pwrlock(&pwrctrl->lock);
1499
1500 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
1501 if (_FAIL == res) {
1502 if (pwrctrl->cpwm >= PS_STATE_S2)
1503 res = _SUCCESS;
1504 }
1505 #endif /* CONFIG_DETECT_CPWM_BY_POLLING */
1506
1507
1508 return res;
1509 }
1510
1511 /*
1512 * Caller: rtw_cmd_thread
1513 *
1514 * Check if the fw_pwrstate is okay for issuing cmd.
1515 * If not (cpwm should be is less than S2), then the sub-routine
1516 * will raise the cpwm to be greater than or equal to S2.
1517 *
1518 * Calling Context: Passive
1519 *
1520 * Return Value:
1521 * _SUCCESS rtw_cmd_thread can issue cmds to firmware afterwards.
1522 * _FAIL rtw_cmd_thread can not do anything.
1523 */
1524 #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/
1525 s32 rtw_register_cmd_alive(_adapter *padapter)
1526 {
1527 s32 res;
1528 struct pwrctrl_priv *pwrctrl;
1529 u8 pslv;
1530
1531
1532 res = _SUCCESS;
1533 pwrctrl = adapter_to_pwrctl(padapter);
1534 pslv = PS_STATE_S2;
1535
1536 _enter_pwrlock(&pwrctrl->lock);
1537
1538 register_task_alive(pwrctrl, CMD_ALIVE);
1539
1540 if (pwrctrl->bFwCurrentInPSMode == _TRUE) {
1541
1542 if (pwrctrl->cpwm < pslv) {
1543 if (pwrctrl->cpwm < PS_STATE_S2)
1544 res = _FAIL;
1545 if (pwrctrl->rpwm < pslv)
1546 rtw_set_rpwm(padapter, pslv);
1547 }
1548 }
1549
1550 _exit_pwrlock(&pwrctrl->lock);
1551
1552 #ifdef CONFIG_DETECT_CPWM_BY_POLLING
1553 if (_FAIL == res) {
1554 if (pwrctrl->cpwm >= PS_STATE_S2)
1555 res = _SUCCESS;
1556 }
1557 #endif /* CONFIG_DETECT_CPWM_BY_POLLING */
1558
1559
1560 return res;
1561 }
1562 #endif
1563 /*
1564 * Caller: rx_isr
1565 *
1566 * Calling Context: Dispatch/ISR
1567 *
1568 * Return Value:
1569 * _SUCCESS
1570 * _FAIL
1571 */
rtw_register_rx_alive(_adapter * padapter)1572 s32 rtw_register_rx_alive(_adapter *padapter)
1573 {
1574 struct pwrctrl_priv *pwrctrl;
1575
1576
1577 pwrctrl = adapter_to_pwrctl(padapter);
1578
1579 _enter_pwrlock(&pwrctrl->lock);
1580
1581 register_task_alive(pwrctrl, RECV_ALIVE);
1582
1583 _exit_pwrlock(&pwrctrl->lock);
1584
1585
1586 return _SUCCESS;
1587 }
1588
1589 /*
1590 * Caller: ISR
1591 *
1592 * If ISR's txdone,
1593 * No more pkts for TX,
1594 * Then driver shall call this fun. to power down firmware again.
1595 */
rtw_unregister_tx_alive(_adapter * padapter)1596 void rtw_unregister_tx_alive(_adapter *padapter)
1597 {
1598 struct pwrctrl_priv *pwrctrl;
1599 _adapter *iface;
1600 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1601 u8 pslv, i;
1602
1603
1604 pwrctrl = adapter_to_pwrctl(padapter);
1605 pslv = PS_STATE_S0;
1606
1607 #ifdef CONFIG_P2P_PS
1608 for (i = 0; i < dvobj->iface_nums; i++) {
1609 iface = dvobj->padapters[i];
1610 if ((iface) && rtw_is_adapter_up(iface)) {
1611 if (iface->wdinfo.p2p_ps_mode > P2P_PS_NONE) {
1612 pslv = PS_STATE_S2;
1613 break;
1614 }
1615 }
1616 }
1617 #endif
1618 _enter_pwrlock(&pwrctrl->lock);
1619
1620 unregister_task_alive(pwrctrl, XMIT_ALIVE);
1621
1622 if ((pwrctrl->pwr_mode != PM_PS_MODE_ACTIVE)
1623 && (pwrctrl->bFwCurrentInPSMode == _TRUE)) {
1624
1625 if (pwrctrl->cpwm > pslv) {
1626 if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1627 rtw_set_rpwm(padapter, pslv);
1628 }
1629 }
1630
1631 _exit_pwrlock(&pwrctrl->lock);
1632
1633 }
1634
1635 /*
1636 * Caller: ISR
1637 *
1638 * If all commands have been done,
1639 * and no more command to do,
1640 * then driver shall call this fun. to power down firmware again.
1641 */
1642 #if 0 /*#ifdef CONFIG_CORE_CMD_THREAD*/
1643 void rtw_unregister_cmd_alive(_adapter *padapter)
1644 {
1645 _adapter *iface;
1646 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1647 struct pwrctrl_priv *pwrctrl;
1648 u8 pslv, i;
1649
1650
1651 pwrctrl = adapter_to_pwrctl(padapter);
1652 pslv = PS_STATE_S0;
1653
1654 #ifdef CONFIG_P2P_PS
1655 for (i = 0; i < dvobj->iface_nums; i++) {
1656 iface = dvobj->padapters[i];
1657 if ((iface) && rtw_is_adapter_up(iface)) {
1658 if (iface->wdinfo.p2p_ps_mode > P2P_PS_NONE) {
1659 pslv = PS_STATE_S2;
1660 break;
1661 }
1662 }
1663 }
1664 #endif
1665
1666 _enter_pwrlock(&pwrctrl->lock);
1667
1668 unregister_task_alive(pwrctrl, CMD_ALIVE);
1669
1670 if ((pwrctrl->pwr_mode != PM_PS_MODE_ACTIVE)
1671 && (pwrctrl->bFwCurrentInPSMode == _TRUE)) {
1672
1673 if (pwrctrl->cpwm > pslv) {
1674 if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
1675 rtw_set_rpwm(padapter, pslv);
1676 }
1677 }
1678
1679 _exit_pwrlock(&pwrctrl->lock);
1680
1681 }
1682 #endif
1683 /*
1684 * Caller: ISR
1685 */
rtw_unregister_rx_alive(_adapter * padapter)1686 void rtw_unregister_rx_alive(_adapter *padapter)
1687 {
1688 struct pwrctrl_priv *pwrctrl;
1689
1690
1691 pwrctrl = adapter_to_pwrctl(padapter);
1692
1693 _enter_pwrlock(&pwrctrl->lock);
1694
1695 unregister_task_alive(pwrctrl, RECV_ALIVE);
1696
1697
1698 _exit_pwrlock(&pwrctrl->lock);
1699
1700 }
1701 #endif /* CONFIG_LPS_LCLK */
1702
1703 #ifdef CONFIG_RESUME_IN_WORKQUEUE
1704 static void resume_workitem_callback(struct work_struct *work);
1705 #endif /* CONFIG_RESUME_IN_WORKQUEUE */
1706
rtw_init_pwrctrl_priv(_adapter * padapter)1707 void rtw_init_pwrctrl_priv(_adapter *padapter)
1708 {
1709 #ifdef CONFIG_LPS_1T1R
1710 #define LPS_1T1R_FMT ", LPS_1T1R=%d"
1711 #define LPS_1T1R_ARG , pwrctrlpriv->lps_1t1r
1712 #else
1713 #define LPS_1T1R_FMT ""
1714 #define LPS_1T1R_ARG
1715 #endif
1716
1717 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
1718
1719 #if defined(CONFIG_CONCURRENT_MODE)
1720 if (!is_primary_adapter(padapter))
1721 return;
1722 #endif
1723
1724 _init_pwrlock(&pwrctrlpriv->lock);
1725 _init_pwrlock(&pwrctrlpriv->check_32k_lock);
1726 pwrctrlpriv->rf_pwrstate = rf_on;
1727 pwrctrlpriv->ips_enter_cnts = 0;
1728 pwrctrlpriv->ips_leave_cnts = 0;
1729 pwrctrlpriv->lps_enter_cnts = 0;
1730 pwrctrlpriv->lps_leave_cnts = 0;
1731 pwrctrlpriv->bips_processing = _FALSE;
1732 #ifdef CONFIG_LPS_CHK_BY_TP
1733 pwrctrlpriv->lps_chk_by_tp = padapter->registrypriv.lps_chk_by_tp;
1734 pwrctrlpriv->lps_tx_tp_th = LPS_TX_TP_TH;
1735 pwrctrlpriv->lps_rx_tp_th = LPS_RX_TP_TH;
1736 pwrctrlpriv->lps_bi_tp_th = LPS_BI_TP_TH;
1737 pwrctrlpriv->lps_chk_cnt = pwrctrlpriv->lps_chk_cnt_th = LPS_TP_CHK_CNT;
1738 pwrctrlpriv->lps_tx_pkts = LPS_CHK_PKTS_TX;
1739 pwrctrlpriv->lps_rx_pkts = LPS_CHK_PKTS_RX;
1740 #endif
1741
1742 pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
1743 pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
1744 pwrctrlpriv->ips_deny_time = rtw_get_current_time();
1745 pwrctrlpriv->lps_level = padapter->registrypriv.lps_level;
1746 #ifdef CONFIG_LPS_1T1R
1747 pwrctrlpriv->lps_1t1r = padapter->registrypriv.lps_1t1r;
1748 #endif
1749
1750 pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
1751 pwrctrlpriv->pwr_state_check_cnts = 0;
1752 pwrctrlpriv->bInSuspend = _FALSE;
1753 pwrctrlpriv->bkeepfwalive = _FALSE;
1754 pwrctrlpriv->LpsIdleCount = 0;
1755
1756 /* pwrctrlpriv->FWCtrlPSMode =padapter->registrypriv.power_mgnt; */ /* PM_PS_MODE_MIN; */
1757 if (padapter->registrypriv.mp_mode == 1)
1758 pwrctrlpriv->power_mgnt = PM_PS_MODE_ACTIVE ;
1759 else
1760 pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt; /* PM_PS_MODE_MIN; */
1761 pwrctrlpriv->bLeisurePs = (PM_PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? _TRUE : _FALSE;
1762
1763 pwrctrlpriv->bFwCurrentInPSMode = _FALSE;
1764 pwrctrlpriv->lps_deny_time = rtw_get_current_time();
1765
1766 pwrctrlpriv->rpwm = 0;
1767 pwrctrlpriv->cpwm = PS_STATE_S4;
1768
1769 pwrctrlpriv->pwr_mode = PM_PS_MODE_ACTIVE;
1770 pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
1771 pwrctrlpriv->bcn_ant_mode = 0;
1772 pwrctrlpriv->dtim = 0;
1773
1774 pwrctrlpriv->tog = 0x80;
1775 pwrctrlpriv->rpwm_retry = 0;
1776
1777 RTW_INFO("%s: IPS_mode=%d, LPS_mode=%d, LPS_level=%d"LPS_1T1R_FMT"\n",
1778 __func__, pwrctrlpriv->ips_mode, pwrctrlpriv->power_mgnt, pwrctrlpriv->lps_level
1779 LPS_1T1R_ARG
1780 );
1781
1782 #ifdef CONFIG_LPS_LCLK
1783 rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&pwrctrlpriv->rpwm));
1784
1785 _init_workitem(&pwrctrlpriv->cpwm_event, cpwm_event_callback, NULL);
1786
1787 _init_workitem(&pwrctrlpriv->dma_event, dma_event_callback, NULL);
1788
1789 #ifdef CONFIG_LPS_RPWM_TIMER
1790 pwrctrlpriv->brpwmtimeout = _FALSE;
1791 _init_workitem(&pwrctrlpriv->rpwmtimeoutwi, rpwmtimeout_workitem_callback, NULL);
1792 rtw_init_timer(&pwrctrlpriv->pwr_rpwm_timer, pwr_rpwm_timeout_handler, padapter);
1793 #endif /* CONFIG_LPS_RPWM_TIMER */
1794 #endif /* CONFIG_LPS_LCLK */
1795
1796 #ifdef CONFIG_LPS_PG
1797 pwrctrlpriv->lpspg_info.name = "LPSPG_INFO";
1798 #ifdef CONFIG_RTL8822C
1799 pwrctrlpriv->lpspg_dpk_info.name = "LPSPG_DPK_INFO";
1800 pwrctrlpriv->lpspg_iqk_info.name = "LPSPG_IQK_INFO";
1801 #endif
1802 #endif
1803 #ifdef CONFIG_POWER_SAVING
1804 rtw_init_timer(&pwrctrlpriv->pwr_state_check_timer, pwr_state_check_handler, padapter);
1805 #endif
1806
1807 #ifdef CONFIG_RESUME_IN_WORKQUEUE
1808 _init_workitem(&pwrctrlpriv->resume_work, resume_workitem_callback, NULL);
1809 pwrctrlpriv->rtw_workqueue = create_singlethread_workqueue("rtw_workqueue");
1810 #endif /* CONFIG_RESUME_IN_WORKQUEUE */
1811
1812 #ifdef CONFIG_LPS_ACK
1813 _rtw_mutex_init(&pwrctrlpriv->lps_ack_mutex);
1814 pwrctrlpriv->lps_ack_status = -1;
1815 #endif /* CONFIG_LPS_ACK */
1816 }
1817
1818
rtw_free_pwrctrl_priv(_adapter * adapter)1819 void rtw_free_pwrctrl_priv(_adapter *adapter)
1820 {
1821 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(adapter);
1822
1823 #if defined(CONFIG_CONCURRENT_MODE)
1824 if (!is_primary_adapter(adapter))
1825 return;
1826 #endif
1827
1828
1829 /* _rtw_memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv)); */
1830
1831
1832 #ifdef CONFIG_RESUME_IN_WORKQUEUE
1833 if (pwrctrlpriv->rtw_workqueue) {
1834 flush_workqueue(pwrctrlpriv->rtw_workqueue);
1835 destroy_workqueue(pwrctrlpriv->rtw_workqueue);
1836 }
1837 #endif
1838
1839 #ifdef CONFIG_LPS_LCLK
1840 _cancel_workitem_sync(&pwrctrlpriv->cpwm_event);
1841 _cancel_workitem_sync(&pwrctrlpriv->dma_event);
1842 #ifdef CONFIG_LPS_RPWM_TIMER
1843 _cancel_workitem_sync(&pwrctrlpriv->rpwmtimeoutwi);
1844 #endif
1845 #endif /* CONFIG_LPS_LCLK */
1846
1847 #ifdef CONFIG_LPS_PG
1848 rsvd_page_cache_free(&pwrctrlpriv->lpspg_info);
1849 #ifdef CONFIG_RTL8822C
1850 rsvd_page_cache_free(&pwrctrlpriv->lpspg_dpk_info);
1851 rsvd_page_cache_free(&pwrctrlpriv->lpspg_iqk_info);
1852 #endif
1853 #endif
1854
1855 _free_pwrlock(&pwrctrlpriv->lock);
1856 _free_pwrlock(&pwrctrlpriv->check_32k_lock);
1857
1858 #ifdef CONFIG_LPS_ACK
1859 _rtw_mutex_free(&pwrctrlpriv->lps_ack_mutex);
1860 #endif /* CONFIG_LPS_ACK */
1861 }
1862
1863 #ifdef CONFIG_RESUME_IN_WORKQUEUE
1864 extern int rtw_resume_process(_adapter *padapter);
1865
resume_workitem_callback(struct work_struct * work)1866 static void resume_workitem_callback(struct work_struct *work)
1867 {
1868 struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, resume_work);
1869 struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
1870 _adapter *adapter = dvobj_get_primary_adapter(dvobj);
1871
1872 RTW_INFO("%s\n", __FUNCTION__);
1873
1874 rtw_resume_process(adapter);
1875
1876 rtw_resume_unlock_suspend();
1877 }
1878
rtw_resume_in_workqueue(struct pwrctrl_priv * pwrpriv)1879 void rtw_resume_in_workqueue(struct pwrctrl_priv *pwrpriv)
1880 {
1881 /* accquire system's suspend lock preventing from falliing asleep while resume in workqueue */
1882 /* rtw_lock_suspend(); */
1883
1884 rtw_resume_lock_suspend();
1885
1886 #if 1
1887 queue_work(pwrpriv->rtw_workqueue, &pwrpriv->resume_work);
1888 #else
1889 _set_workitem(&pwrpriv->resume_work);
1890 #endif
1891 }
1892 #endif /* CONFIG_RESUME_IN_WORKQUEUE */
1893
1894 #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
rtw_is_earlysuspend_registered(struct pwrctrl_priv * pwrpriv)1895 inline bool rtw_is_earlysuspend_registered(struct pwrctrl_priv *pwrpriv)
1896 {
1897 return (pwrpriv->early_suspend.suspend) ? _TRUE : _FALSE;
1898 }
1899
rtw_is_do_late_resume(struct pwrctrl_priv * pwrpriv)1900 inline bool rtw_is_do_late_resume(struct pwrctrl_priv *pwrpriv)
1901 {
1902 return (pwrpriv->do_late_resume) ? _TRUE : _FALSE;
1903 }
1904
rtw_set_do_late_resume(struct pwrctrl_priv * pwrpriv,bool enable)1905 inline void rtw_set_do_late_resume(struct pwrctrl_priv *pwrpriv, bool enable)
1906 {
1907 pwrpriv->do_late_resume = enable;
1908 }
1909 #endif
1910
1911 #ifdef CONFIG_HAS_EARLYSUSPEND
1912 extern int rtw_resume_process(_adapter *padapter);
rtw_early_suspend(struct early_suspend * h)1913 static void rtw_early_suspend(struct early_suspend *h)
1914 {
1915 struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
1916 RTW_INFO("%s\n", __FUNCTION__);
1917
1918 rtw_set_do_late_resume(pwrpriv, _FALSE);
1919 }
1920
rtw_late_resume(struct early_suspend * h)1921 static void rtw_late_resume(struct early_suspend *h)
1922 {
1923 struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
1924 struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
1925 _adapter *adapter = dvobj_get_primary_adapter(dvobj);
1926
1927 RTW_INFO("%s\n", __FUNCTION__);
1928
1929 if (pwrpriv->do_late_resume) {
1930 rtw_set_do_late_resume(pwrpriv, _FALSE);
1931 rtw_resume_process(adapter);
1932 }
1933 }
1934
rtw_register_early_suspend(struct pwrctrl_priv * pwrpriv)1935 void rtw_register_early_suspend(struct pwrctrl_priv *pwrpriv)
1936 {
1937 RTW_INFO("%s\n", __FUNCTION__);
1938
1939 /* jeff: set the early suspend level before blank screen, so we wll do late resume after scree is lit */
1940 pwrpriv->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
1941 pwrpriv->early_suspend.suspend = rtw_early_suspend;
1942 pwrpriv->early_suspend.resume = rtw_late_resume;
1943 register_early_suspend(&pwrpriv->early_suspend);
1944
1945
1946 }
1947
rtw_unregister_early_suspend(struct pwrctrl_priv * pwrpriv)1948 void rtw_unregister_early_suspend(struct pwrctrl_priv *pwrpriv)
1949 {
1950 RTW_INFO("%s\n", __FUNCTION__);
1951
1952 rtw_set_do_late_resume(pwrpriv, _FALSE);
1953
1954 if (pwrpriv->early_suspend.suspend)
1955 unregister_early_suspend(&pwrpriv->early_suspend);
1956
1957 pwrpriv->early_suspend.suspend = NULL;
1958 pwrpriv->early_suspend.resume = NULL;
1959 }
1960 #endif /* CONFIG_HAS_EARLYSUSPEND */
1961
1962 #ifdef CONFIG_ANDROID_POWER
1963 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
1964 extern int rtw_resume_process(_adapter *padapter);
1965 #endif
rtw_early_suspend(android_early_suspend_t * h)1966 static void rtw_early_suspend(android_early_suspend_t *h)
1967 {
1968 struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
1969 RTW_INFO("%s\n", __FUNCTION__);
1970
1971 rtw_set_do_late_resume(pwrpriv, _FALSE);
1972 }
1973
rtw_late_resume(android_early_suspend_t * h)1974 static void rtw_late_resume(android_early_suspend_t *h)
1975 {
1976 struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
1977 struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
1978 _adapter *adapter = dvobj_get_primary_adapter(dvobj);
1979
1980 RTW_INFO("%s\n", __FUNCTION__);
1981 if (pwrpriv->do_late_resume) {
1982 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
1983 rtw_set_do_late_resume(pwrpriv, _FALSE);
1984 rtw_resume_process(adapter);
1985 #endif
1986 }
1987 }
1988
rtw_register_early_suspend(struct pwrctrl_priv * pwrpriv)1989 void rtw_register_early_suspend(struct pwrctrl_priv *pwrpriv)
1990 {
1991 RTW_INFO("%s\n", __FUNCTION__);
1992
1993 /* jeff: set the early suspend level before blank screen, so we wll do late resume after scree is lit */
1994 pwrpriv->early_suspend.level = ANDROID_EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
1995 pwrpriv->early_suspend.suspend = rtw_early_suspend;
1996 pwrpriv->early_suspend.resume = rtw_late_resume;
1997 android_register_early_suspend(&pwrpriv->early_suspend);
1998 }
1999
rtw_unregister_early_suspend(struct pwrctrl_priv * pwrpriv)2000 void rtw_unregister_early_suspend(struct pwrctrl_priv *pwrpriv)
2001 {
2002 RTW_INFO("%s\n", __FUNCTION__);
2003
2004 rtw_set_do_late_resume(pwrpriv, _FALSE);
2005
2006 if (pwrpriv->early_suspend.suspend)
2007 android_unregister_early_suspend(&pwrpriv->early_suspend);
2008
2009 pwrpriv->early_suspend.suspend = NULL;
2010 pwrpriv->early_suspend.resume = NULL;
2011 }
2012 #endif /* CONFIG_ANDROID_POWER */
2013
2014
rtw_set_ips_deny(_adapter * padapter,u32 ms)2015 inline void rtw_set_ips_deny(_adapter *padapter, u32 ms)
2016 {
2017 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
2018 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ms);
2019 }
2020
2021 /*
2022 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
2023 * @adapter: pointer to _adapter structure
2024 * @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
2025 * Return _SUCCESS or _FAIL
2026 */
2027
_rtw_pwr_wakeup(_adapter * padapter,u32 ips_deffer_ms,const char * caller)2028 int _rtw_pwr_wakeup(_adapter *padapter, u32 ips_deffer_ms, const char *caller)
2029 {
2030 int ret = _SUCCESS;
2031
2032 #ifdef CONFIG_POWER_SAVING
2033 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2034 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
2035 struct mlme_priv *pmlmepriv;
2036
2037 systime start = rtw_get_current_time();
2038
2039 /*RTW_INFO(FUNC_ADPT_FMT "===>\n", FUNC_ADPT_ARG(padapter));*/
2040 /* for LPS */
2041 LeaveAllPowerSaveMode(padapter);
2042
2043 /* IPS still bound with primary adapter */
2044 padapter = GET_PRIMARY_ADAPTER(padapter);
2045 pmlmepriv = &padapter->mlmepriv;
2046
2047 if (rtw_time_after(rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms), pwrpriv->ips_deny_time))
2048 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms);
2049
2050
2051 if (pwrpriv->ps_processing) {
2052 RTW_INFO("%s wait ps_processing...\n", __func__);
2053 while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
2054 rtw_msleep_os(10);
2055 if (pwrpriv->ps_processing)
2056 RTW_INFO("%s wait ps_processing timeout\n", __func__);
2057 else
2058 RTW_INFO("%s wait ps_processing done\n", __func__);
2059 }
2060
2061 #ifdef DBG_CONFIG_ERROR_DETECT
2062 if (rtw_hal_sreset_inprogress(padapter)) {
2063 RTW_INFO("%s wait sreset_inprogress...\n", __func__);
2064 while (rtw_hal_sreset_inprogress(padapter) && rtw_get_passing_time_ms(start) <= 4000)
2065 rtw_msleep_os(10);
2066 if (rtw_hal_sreset_inprogress(padapter))
2067 RTW_INFO("%s wait sreset_inprogress timeout\n", __func__);
2068 else
2069 RTW_INFO("%s wait sreset_inprogress done\n", __func__);
2070 }
2071 #endif
2072
2073 if (pwrpriv->bInSuspend) {
2074 RTW_INFO("%s wait bInSuspend...\n", __func__);
2075 while (pwrpriv->bInSuspend
2076 && ((rtw_get_passing_time_ms(start) <= 3000 && !rtw_is_do_late_resume(pwrpriv))
2077 || (rtw_get_passing_time_ms(start) <= 500 && rtw_is_do_late_resume(pwrpriv)))
2078 )
2079 rtw_msleep_os(10);
2080 if (pwrpriv->bInSuspend)
2081 RTW_INFO("%s wait bInSuspend timeout\n", __func__);
2082 else
2083 RTW_INFO("%s wait bInSuspend done\n", __func__);
2084 }
2085
2086 /* System suspend is not allowed to wakeup */
2087 if (_TRUE == pwrpriv->bInSuspend) {
2088 ret = _FAIL;
2089 goto exit;
2090 }
2091 /* I think this should be check in IPS, LPS, autosuspend functions... */
2092 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
2093 ret = _SUCCESS;
2094 goto exit;
2095 }
2096
2097 if (rf_off == pwrpriv->rf_pwrstate) {
2098
2099 #ifdef CONFIG_IPS
2100 RTW_INFO("%s call ips_leave....\n", __FUNCTION__);
2101 if (_FAIL == ips_leave(padapter)) {
2102 RTW_INFO("======> ips_leave fail.............\n");
2103 ret = _FAIL;
2104 goto exit;
2105 }
2106 #endif
2107
2108 }
2109
2110 /* TODO: the following checking need to be merged... */
2111 if (dev_is_drv_stopped(dvobj)
2112 || !padapter->netif_up
2113 || !rtw_hw_is_init_completed(dvobj)
2114 ) {
2115 RTW_INFO("%s: bDriverStopped=%s, netif_up=%d, hw_init_completed=%u\n"
2116 , caller
2117 , dev_is_drv_stopped(dvobj) ? "True" : "False"
2118 , padapter->netif_up
2119 , rtw_hw_get_init_completed(dvobj));
2120 ret = _FALSE;
2121 goto exit;
2122 }
2123
2124 exit:
2125 if (rtw_time_after(rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms), pwrpriv->ips_deny_time))
2126 pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms);
2127 /*RTW_INFO(FUNC_ADPT_FMT "<===\n", FUNC_ADPT_ARG(padapter));*/
2128 #endif
2129 return ret;
2130 }
2131
rtw_pm_set_lps(_adapter * padapter,u8 mode)2132 int rtw_pm_set_lps(_adapter *padapter, u8 mode)
2133 {
2134 int ret = 0;
2135 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2136
2137 if (mode < PM_PS_MODE_NUM) {
2138 if (pwrctrlpriv->power_mgnt != mode) {
2139 if (PM_PS_MODE_ACTIVE == mode)
2140 LeaveAllPowerSaveMode(padapter);
2141 else
2142 pwrctrlpriv->LpsIdleCount = 2;
2143 pwrctrlpriv->power_mgnt = mode;
2144 pwrctrlpriv->bLeisurePs = (PM_PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? _TRUE : _FALSE;
2145 }
2146 } else
2147 ret = -EINVAL;
2148
2149 return ret;
2150 }
2151
rtw_pm_set_lps_level(_adapter * padapter,u8 level)2152 int rtw_pm_set_lps_level(_adapter *padapter, u8 level)
2153 {
2154 int ret = 0;
2155 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2156
2157 if (level < LPS_LEVEL_MAX) {
2158 if (pwrctrlpriv->lps_level != level) {
2159 #ifdef CONFIG_LPS
2160 if (rtw_lps_ctrl_leave_set_level_cmd(padapter, level, RTW_CMDF_WAIT_ACK) != _SUCCESS)
2161 #endif
2162 pwrctrlpriv->lps_level = level;
2163 }
2164 } else
2165 ret = -EINVAL;
2166
2167 return ret;
2168 }
2169
2170 #ifdef CONFIG_LPS_1T1R
rtw_pm_set_lps_1t1r(_adapter * padapter,u8 en)2171 int rtw_pm_set_lps_1t1r(_adapter *padapter, u8 en)
2172 {
2173 int ret = 0;
2174 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2175
2176 en = en ? 1 : 0;
2177 if (pwrctrlpriv->lps_1t1r != en) {
2178 if (rtw_lps_ctrl_leave_set_1t1r_cmd(padapter, en, RTW_CMDF_WAIT_ACK) != _SUCCESS)
2179 pwrctrlpriv->lps_1t1r = en;
2180 }
2181
2182 return ret;
2183 }
2184 #endif
2185
rtw_set_lps_deny(_adapter * adapter,u32 ms)2186 inline void rtw_set_lps_deny(_adapter *adapter, u32 ms)
2187 {
2188 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
2189 pwrpriv->lps_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ms);
2190 }
2191
rtw_pm_set_ips(_adapter * padapter,u8 mode)2192 int rtw_pm_set_ips(_adapter *padapter, u8 mode)
2193 {
2194 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
2195
2196 if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
2197 rtw_ips_mode_req(pwrctrlpriv, mode);
2198 RTW_INFO("%s %s\n", __FUNCTION__, mode == IPS_NORMAL ? "IPS_NORMAL" : "IPS_LEVEL_2");
2199 return 0;
2200 } else if (mode == IPS_NONE) {
2201 rtw_ips_mode_req(pwrctrlpriv, mode);
2202 RTW_INFO("%s %s\n", __FUNCTION__, "IPS_NONE");
2203 if (!dev_is_surprise_removed(adapter_to_dvobj(padapter)) && (_FAIL == rtw_pwr_wakeup(padapter)))
2204 return -EFAULT;
2205 } else
2206 return -EINVAL;
2207 return 0;
2208 }
2209
2210 /*
2211 * ATTENTION:
2212 * This function will request pwrctrl LOCK!
2213 */
rtw_ps_deny(_adapter * padapter,PS_DENY_REASON reason)2214 void rtw_ps_deny(_adapter *padapter, PS_DENY_REASON reason)
2215 {
2216 struct pwrctrl_priv *pwrpriv;
2217
2218 /* RTW_INFO("+" FUNC_ADPT_FMT ": Request PS deny for %d (0x%08X)\n",
2219 * FUNC_ADPT_ARG(padapter), reason, BIT(reason)); */
2220
2221 pwrpriv = adapter_to_pwrctl(padapter);
2222
2223 _enter_pwrlock(&pwrpriv->lock);
2224 if (pwrpriv->ps_deny & BIT(reason)) {
2225 RTW_INFO(FUNC_ADPT_FMT ": [WARNING] Reason %d had been set before!!\n",
2226 FUNC_ADPT_ARG(padapter), reason);
2227 }
2228 pwrpriv->ps_deny |= BIT(reason);
2229 _exit_pwrlock(&pwrpriv->lock);
2230
2231 /* RTW_INFO("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n",
2232 * FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny); */
2233 }
2234
2235 /*
2236 * ATTENTION:
2237 * This function will request pwrctrl LOCK!
2238 */
rtw_ps_deny_cancel(_adapter * padapter,PS_DENY_REASON reason)2239 void rtw_ps_deny_cancel(_adapter *padapter, PS_DENY_REASON reason)
2240 {
2241 struct pwrctrl_priv *pwrpriv;
2242
2243
2244 /* RTW_INFO("+" FUNC_ADPT_FMT ": Cancel PS deny for %d(0x%08X)\n",
2245 * FUNC_ADPT_ARG(padapter), reason, BIT(reason)); */
2246
2247 pwrpriv = adapter_to_pwrctl(padapter);
2248
2249 _enter_pwrlock(&pwrpriv->lock);
2250 if ((pwrpriv->ps_deny & BIT(reason)) == 0) {
2251 RTW_INFO(FUNC_ADPT_FMT ": [ERROR] Reason %d had been canceled before!!\n",
2252 FUNC_ADPT_ARG(padapter), reason);
2253 }
2254 pwrpriv->ps_deny &= ~BIT(reason);
2255 _exit_pwrlock(&pwrpriv->lock);
2256
2257 /* RTW_INFO("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n",
2258 * FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny); */
2259 }
2260
2261 /*
2262 * ATTENTION:
2263 * Before calling this function pwrctrl lock should be occupied already,
2264 * otherwise it may return incorrect value.
2265 */
rtw_ps_deny_get(_adapter * padapter)2266 u32 rtw_ps_deny_get(_adapter *padapter)
2267 {
2268 u32 deny;
2269
2270
2271 deny = adapter_to_pwrctl(padapter)->ps_deny;
2272
2273 return deny;
2274 }
2275
_rtw_ssmps(_adapter * adapter,struct sta_info * sta)2276 static void _rtw_ssmps(_adapter *adapter, struct sta_info *sta)
2277 {
2278 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
2279 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2280
2281 issue_action_SM_PS_wait_ack(adapter , get_my_bssid(&(pmlmeinfo->network)),
2282 sta->phl_sta->asoc_cap.sm_ps, 3 , 1);
2283
2284 if (sta->phl_sta->asoc_cap.sm_ps == SM_PS_STATIC) {
2285 pmlmeext->txss_bk = sta->phl_sta->asoc_cap.nss_rx;
2286 sta->phl_sta->asoc_cap.nss_rx = 1;
2287 } else {
2288 sta->phl_sta->asoc_cap.nss_rx = pmlmeext->txss_bk;
2289 }
2290
2291 rtw_phl_cmd_change_stainfo(adapter_to_dvobj(adapter)->phl,
2292 sta->phl_sta,
2293 STA_CHG_RAMASK,
2294 NULL,
2295 0,
2296 PHL_CMD_DIRECTLY,
2297 0);
2298 }
rtw_ssmps_enter(_adapter * adapter,struct sta_info * sta)2299 void rtw_ssmps_enter(_adapter *adapter, struct sta_info *sta)
2300 {
2301 if (MLME_IS_AP(adapter))
2302 return;
2303
2304 if (sta->phl_sta->asoc_cap.sm_ps == SM_PS_STATIC)
2305 return;
2306
2307 RTW_INFO(ADPT_FMT" STA [" MAC_FMT "]\n", ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr));
2308
2309 sta->phl_sta->asoc_cap.sm_ps = SM_PS_STATIC;
2310 _rtw_ssmps(adapter, sta);
2311 }
rtw_ssmps_leave(_adapter * adapter,struct sta_info * sta)2312 void rtw_ssmps_leave(_adapter *adapter, struct sta_info *sta)
2313 {
2314 if (MLME_IS_AP(adapter))
2315 return;
2316
2317 if (sta->phl_sta->asoc_cap.sm_ps == SM_PS_DISABLE)
2318 return;
2319
2320 RTW_INFO(ADPT_FMT" STA [" MAC_FMT "] \n", ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr));
2321 sta->phl_sta->asoc_cap.sm_ps = SM_PS_DISABLE;
2322 _rtw_ssmps(adapter, sta);
2323 }
2324
2325