• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 /* ****************************************************************************
20   1 Header File Including
21 **************************************************************************** */
22 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
23 #include <linux/module.h> /* kernel module definitions */
24 #include <linux/interrupt.h>
25 #include <linux/timer.h>
26 #ifndef HAVE_PCLINT_CHECK
27 #include <linux/platform_device.h>
28 #include <linux/wakelock.h>
29 #endif
30 
31 #include "oal_sdio.h"
32 #include "oal_sdio_comm.h"
33 #include "oal_sdio_host_if.h"
34 #include "oal_mm.h"
35 #include "hi_types.h"
36 #include "plat_pm_wlan.h"
37 #include "plat_pm.h"
38 #include "hcc_host.h"
39 #include "oam_ext_if.h"
40 #include "exception_rst.h"
41 #include "oal_interrupt.h"
42 #ifdef _PRE_WLAN_FEATURE_WOW
43 #include "hmac_wow.h"
44 #endif
45 
46 #elif (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
47 #include <linux/module.h> /* kernel module definitions */
48 #include <linux/init.h>
49 #include <linux/interrupt.h>
50 #include <linux/timer.h>
51 #include <linux/platform_device.h>
52 #include <linux/kobject.h>
53 #include <linux/irq.h>
54 #include <linux/mmc/sdio.h>
55 #include <linux/mmc/host.h>
56 #include <linux/mmc/card.h>
57 #include <linux/mmc/sdio_func.h>
58 #include <linux/mmc/sdio_ids.h>
59 #include <linux/mmc/sdio_func.h>
60 #include <linux/mmc/host.h>
61 #include <linux/gpio.h>
62 #include <linux/sched.h>
63 #include <asm/siginfo.h>
64 #include <linux/pid_namespace.h>
65 #include <linux/pid.h>
66 #include <linux/version.h>
67 #include "oal_sdio_comm.h"
68 #include "oal_sdio_host_if.h"
69 #include "plat_pm_wlan.h"
70 #include "plat_pm.h"
71 #include "hcc_host.h"
72 #include "oam_ext_if.h"
73 #include "oal_mm.h"
74 #include "exception_rst.h"
75 #ifdef _PRE_WLAN_FEATURE_WOW
76 #include "hmac_wow.h"
77 #endif
78 #endif
79 
80 /* 公用数据与函数接口 */
81 struct wlan_pm_info *g_gpst_wlan_pm_info = HI_NULL;
82 
83 wlan_pm_callback_stru     g_wlan_pm_callback = {
84     .wlan_pm_wakeup_dev  = wlan_pm_wakeup_dev,
85     .wlan_pm_state_get   = wlan_pm_state_get,
86     .wlan_pm_wakeup_host = wlan_pm_wakeup_host,
87     .wlan_pm_feed_wdg    = wlan_pm_feed_wdg,
88     .wlan_pm_wakeup_dev_ack    = wlan_pm_wakeup_dev_ack,
89 };
90 
91 int g_wk_fail_process_pid = 0; /* 由应用层注册处理唤醒device失败时的进程ID */
92 hi_wifi_wkup_fail_cb g_wkup_fail_cb = NULL;
93 oal_bool_enum_uint8 g_wlan_pm_switch = 0; /* 1131C-debug */
94 oal_atomic g_wakeup_dev_wait_ack;
95 oal_atomic g_dev_sleep_wait_ack;
96 volatile hi_u8 g_wlan_pm_disabling = 0;
97 
98 void wlan_pm_sleep_work(oal_work_stru *worker);
99 hi_s32 wlan_pm_wakeup_done_callback(void *data);
100 hi_s32 wlan_pm_close_done_callback(void *data);
101 
102 hi_s32 wlan_pm_stop_wdg(hi_void);
103 hi_s32 wlan_pm_work_submit(struct wlan_pm_info *wlan_pm, oal_work_stru *worker);
104 void wlan_pm_info_clean(void);
105 
106 /* ****************************************************************************
107  功能描述  : 获取全局wlan结构
108  输入参数  : 无
109  输出参数  : 无
110  返 回 值  : 初始化返回值,成功或失败原因
111 **************************************************************************** */
wlan_pm_get_drv(hi_void)112 struct wlan_pm_info *wlan_pm_get_drv(hi_void)
113 {
114     return g_gpst_wlan_pm_info;
115 }
116 
117 /* ****************************************************************************
118  功能描述  : wifi是否上电
119  输入参数  : 无
120  输出参数  : 无
121  返 回 值  : 初始化返回值,成功或失败原因
122 **************************************************************************** */
wlan_pm_is_poweron(hi_void)123 hi_s32 wlan_pm_is_poweron(hi_void)
124 {
125     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
126 
127     if (wlan_pm == HI_NULL) {
128         return HI_TRUE;
129     }
130     if (wlan_pm->wlan_power_state == POWER_STATE_OPEN) {
131         return HI_TRUE;
132     } else {
133         return HI_FALSE;
134     }
135 }
136 
wlan_pm_is_shutdown(hi_void)137 hi_s32 wlan_pm_is_shutdown(hi_void)
138 {
139     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
140     if (wlan_pm == HI_NULL) {
141         oam_error_log0(0, 0, "pm_data is HI_NULL!");
142         return -FAILURE;
143     }
144 
145     return ((wlan_pm->wlan_power_state == POWER_STATE_SHUTDOWN) ? true : false);
146 }
147 
wlan_pm_set_wkfail_pid(int pid)148 hi_void wlan_pm_set_wkfail_pid(int pid)
149 {
150     g_wk_fail_process_pid = pid;
151 }
152 
153 /* ****************************************************************************
154  功能描述  : 注册唤醒device失败时的回调处理函数
155  输入参数  : 无
156  输出参数  : 无
157  返 回 值  : 初始化返回值,成功或失败原因
158 **************************************************************************** */
hi_wifi_register_wkup_fail_process_handle(hi_wifi_wkup_fail_cb cb)159 hi_s32 hi_wifi_register_wkup_fail_process_handle(hi_wifi_wkup_fail_cb cb)
160 {
161     if (cb == NULL) {
162         return FAILURE;
163     }
164     g_wkup_fail_cb = cb;
165     return SUCCESS;
166 }
167 
168 /* ****************************************************************************
169  功能描述  : 获取回调handler指针
170  输入参数  : 无
171  输出参数  : 无
172  返 回 值  : 初始化返回值,成功或失败原因
173 **************************************************************************** */
wlan_pm_get_wifi_srv_handler(hi_void)174 struct wifi_srv_callback_handler *wlan_pm_get_wifi_srv_handler(hi_void)
175 {
176     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
177     if (wlan_pm == HI_NULL) {
178         return HI_FALSE;
179     }
180     return &wlan_pm->st_wifi_srv_handler;
181 }
182 
183 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
184 /* ****************************************************************************
185  功能描述  : 提交一个kernel work
186  输入参数  : 无
187  输出参数  : 无
188  返 回 值  : 初始化返回值,成功或失败原因
189 **************************************************************************** */
wlan_pm_work_submit(struct wlan_pm_info * wlan_pm,oal_work_stru * worker)190 hi_s32 wlan_pm_work_submit(struct wlan_pm_info *wlan_pm, oal_work_stru *worker)
191 {
192     hi_s32 ret = 0;
193 
194     if (work_busy(worker)) {
195         /* If comm worker is processing,
196           we need't submit again */
197         ret = -OAL_EBUSY;
198         return ret;
199     } else {
200         oam_info_log1(0, OAM_SF_PWR, "WiFi %pF Worker Submit\n", (uintptr_t)(hi_void *)worker->func);
201         queue_work(wlan_pm->pm_wq, worker);
202     }
203     return ret;
204 }
205 #elif (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
206 /* ****************************************************************************
207  功能描述  : 提交一个kernel work
208  输入参数  : 无
209  输出参数  : 无
210  返 回 值  : 初始化返回值,成功或失败原因
211 **************************************************************************** */
wlan_pm_work_submit(struct wlan_pm_info * wlan_pm,oal_work_stru * worker)212 hi_s32 wlan_pm_work_submit(struct wlan_pm_info *wlan_pm, oal_work_stru *worker)
213 {
214     hi_s32 ret = 0;
215     if (oal_work_is_busy(worker)) {
216         /* If comm worker is processing,
217           we need't submit again */
218         ret = -OAL_EBUSY;
219         return ret;
220     } else {
221         oam_info_log1(0, OAM_SF_PWR, "WiFi %pF Worker Submit\n", (hi_void *)worker->func);
222         if (oal_queue_work(wlan_pm->pm_wq, worker) == false) {
223             ret = -OAL_EFAIL;
224         }
225     }
226     return ret;
227 }
228 
229 /* ****************************************************************************
230  功能描述  : device应答poweroff ack消息处理
231  输入参数  : 无
232  输出参数  : 无
233  返 回 值  :
234 **************************************************************************** */
wlan_pm_close_done_callback(void * data)235 hi_s32 wlan_pm_close_done_callback(void *data)
236 {
237     struct wlan_pm_info *wlan_pm = (struct wlan_pm_info *)data;
238     if (wlan_pm == HI_NULL) {
239         return FAILURE;
240     }
241     /* 关闭RX通道,防止SDIO RX thread继续访问SDIO */
242     oal_disable_bus_state(wlan_pm->bus, OAL_SDIO_RX);
243     wlan_pm->close_done_callback++;
244     OAL_COMPLETE(&wlan_pm->close_done);
245     oam_warning_log0(0, OAM_SF_PWR, "complete H2D_MSG_PM_WLAN_OFF done!");
246     return SUCCESS;
247 }
248 
wlan_pm_wkfail_send_sig(void)249 hi_void wlan_pm_wkfail_send_sig(void)
250 {
251 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0))
252     struct kernel_siginfo info = { 0 };
253 #else
254     struct siginfo info = { 0 };
255 #endif
256     int ret;
257     if (g_wk_fail_process_pid <= 0) {
258         printk("wk fail process not register \n");
259         return;
260     }
261     printk("wkup fail process pid:%d, sig id:%d \n", g_wk_fail_process_pid, WK_FAIL_SIG);
262     info.si_signo = WK_FAIL_SIG;
263     info.si_code = 0;
264     info.si_int = 0;
265     struct task_struct *current_task = HI_NULL;
266     rcu_read_lock();
267     current_task = pid_task(find_vpid(g_wk_fail_process_pid), PIDTYPE_PID);
268     rcu_read_unlock();
269     ret = send_sig_info(WK_FAIL_SIG, &info, current_task);
270     if (ret < 0) {
271         printk("error sending signal\n");
272     }
273 }
274 
275 #endif
276 
277 /* ****************************************************************************
278  功能描述  : 使能wlan平台低功耗
279  输入参数  : 无
280  输出参数  : 无
281  返 回 值  : 初始化返回值,成功或失败原因
282 **************************************************************************** */
hi_wifi_plat_pm_enable(hi_void)283 hi_u32 hi_wifi_plat_pm_enable(hi_void)
284 {
285 #ifndef _PRE_FEATURE_NO_GPIO
286     if (!g_wlan_pm_switch) {
287         return HI_SUCCESS;
288     }
289 #endif
290     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
291     if (wlan_pm == NULL) {
292         oam_warning_log0(0, OAM_SF_PWR, "hi_wifi_plat_pm_enable pst_wlan_pm is null!");
293         return HI_FAIL;
294     }
295 
296     if (wlan_pm->wlan_pm_enable == HI_TRUE) {
297         oam_warning_log0(0, OAM_SF_PWR, "hi_wifi_plat_pm_enable already enabled!");
298         return HI_SUCCESS;
299     }
300     wlan_pm->wlan_pm_enable = HI_TRUE;
301     /* 将timeout值恢复为默认值,并启动定时器 */
302     wlan_pm_set_timeout(WLAN_SLEEP_DEFAULT_CHECK_CNT);
303     oam_info_log0(0, OAM_SF_PWR, "hi_wifi_plat_pm_enable HI_SUCCESS!");
304     return HI_SUCCESS;
305 }
306 
wlan_pm_is_disabling(void)307 hi_u8 wlan_pm_is_disabling(void)
308 {
309     return g_wlan_pm_disabling;
310 }
311 
312 /* ****************************************************************************
313  函 数 名  : hi_wifi_plat_pm_disable
314  功能描述  : 去使能wlan平台低功耗
315  返 回 值  : 初始化返回值,成功或失败原因
316 **************************************************************************** */
wlan_pm_disable_check_wakeup(hi_s32 flag)317 hi_s32 wlan_pm_disable_check_wakeup(hi_s32 flag)
318 {
319     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
320     if (wlan_pm == HI_NULL) {
321         oam_warning_log0(0, OAM_SF_PWR, "wlan_pm_disable_check_wakeup pst_wlan_pm is null!");
322         return HI_SUCCESS;
323     }
324     hcc_handler_stru *hcc_chl = hcc_host_get_handler();
325     if (hcc_chl == HI_NULL) {
326         printk("hcc_chl is null \n");
327         return HI_SUCCESS;
328     }
329     g_wlan_pm_disabling = 1;
330     hcc_tx_transfer_lock(hcc_host_get_handler());
331     if (wlan_pm->wlan_pm_enable == HI_FALSE) {
332         oam_warning_log0(0, OAM_SF_PWR, "hi_wifi_plat_pm_disable already disabled!");
333         hcc_tx_transfer_unlock(hcc_host_get_handler());
334         g_wlan_pm_disabling = 0;
335         return HI_SUCCESS;
336     }
337     if (flag == HI_TRUE) {
338         if (wlan_pm_wakeup_dev() != HI_SUCCESS) {
339             oam_warning_log0(0, OAM_SF_PWR, "pm wake up dev fail!");
340         }
341     }
342     wlan_pm->wlan_pm_enable = HI_FALSE;
343     hcc_tx_transfer_unlock(hcc_host_get_handler());
344     g_wlan_pm_disabling = 0;
345     oal_cancel_work_sync(&wlan_pm->sleep_work);
346     oam_info_log0(0, OAM_SF_PWR, "hi_wifi_plat_pm_disable HI_SUCCESS!");
347     return HI_SUCCESS;
348 }
349 
hi_wifi_plat_pm_disable(hi_void)350 hi_u32 hi_wifi_plat_pm_disable(hi_void)
351 {
352     return (hi_u32)wlan_pm_disable_check_wakeup(HI_TRUE);
353 }
354 /* 投票禁止睡眠 */
wlan_pm_add_vote(wlan_pm_vote_id id)355 hi_void wlan_pm_add_vote(wlan_pm_vote_id id)
356 {
357     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
358     unsigned long ret;
359     oal_spin_lock_stru spin_lock;
360     unsigned long flags;
361     if ((wlan_pm == NULL) || (wlan_pm->bus == NULL) || (id > HI_PM_ID_MAX)) {
362         oam_error_log1(0, OAM_SF_PWR, "wlan_pm_add_vote, para error, id:%u", id);
363         return;
364     }
365     oal_spin_lock_init(&spin_lock);
366     oal_spin_lock_irq_save(&spin_lock, &flags);
367     wlan_pm->vote_status |= (0x1 << (hi_u32)id);
368     oal_spin_unlock_irq_restore(&spin_lock, &flags);
369 
370     oal_cancel_work_sync(&wlan_pm->sleep_work);
371     g_wlan_pm_disabling = 1;
372     hcc_tx_transfer_lock(hcc_host_get_handler());
373     ret = wlan_pm_wakeup_dev();
374     if (ret != HI_SUCCESS) {
375         oam_error_log0(0, 0, "wlan wakeup fail !");
376     }
377     hcc_tx_transfer_unlock(hcc_host_get_handler());
378     g_wlan_pm_disabling = 0;
379 }
380 
381 /* 解除对应id的禁止进入睡眠模式状态 */
wlan_pm_remove_vote(wlan_pm_vote_id id)382 hi_void wlan_pm_remove_vote(wlan_pm_vote_id id)
383 {
384     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
385     oal_spin_lock_stru spin_lock;
386     unsigned long flags;
387     if ((wlan_pm == NULL) || (wlan_pm->bus == NULL) || (id > HI_PM_ID_MAX)) {
388         oam_error_log1(0, OAM_SF_PWR, "wlan_pm_remove_vote, para error, id:%u", id);
389         return;
390     }
391     oal_spin_lock_init(&spin_lock);
392     oal_spin_lock_irq_save(&spin_lock, &flags);
393     wlan_pm->vote_status &= ~(0x1 << (hi_u32)id);
394     oal_spin_unlock_irq_restore(&spin_lock, &flags);
395     wlan_pm_feed_wdg();
396 }
397 
plat_set_device_ready(hi_void * data)398 hi_s32 plat_set_device_ready(hi_void *data)
399 {
400     oal_completion *device_ready = (oal_completion *)data;
401     if (device_ready == HI_NULL) {
402         return HI_FAIL;
403     }
404     OAL_COMPLETE(device_ready);
405     return HI_SUCCESS;
406 }
407 
wlan_pm_open(hi_void)408 hi_u32 wlan_pm_open(hi_void)
409 {
410     hi_u32 ret;
411     hi_u32 i;
412     oal_completion  device_ready;
413     struct BusDev *bus = hcc_host_get_handler()->bus;
414     oal_channel_stru *hi_sdio = (oal_channel_stru *)bus->priData.data;
415 
416     set_device_is_ready(HI_FALSE);
417     OAL_INIT_COMPLETION(&device_ready);
418     oal_bus_message_register(bus, D2H_MSG_WLAN_READY, plat_set_device_ready,
419         &device_ready);
420 
421     if (wlan_power_on() != HI_SUCCESS) {
422         oam_error_log0(0, OAM_SF_PWR, "wlan_pm_open:: wlan_power_on fail!");
423         return HI_FAIL;
424     }
425 
426     /* 主动检查device状态是否ready */
427     for (i = 0; i < (HOST_WAIT_BOTTOM_INIT_TIMEOUT / HOST_WAIT_READY_INTERVAL); i++) {
428         ret = oal_wait_for_completion_timeout(&device_ready, (hi_u32)OAL_MSECS_TO_JIFFIES(HOST_WAIT_READY_INTERVAL));
429         if (ret > 0) {
430             break;
431         }
432 
433         oal_sdio_isr((void *)hi_sdio->func);
434     }
435 
436     if (ret == 0) {
437         oam_error_log0(0, 0, "oal_wait_for_completion_timeout timeout!");
438         return HI_FAIL;
439     }
440 
441     printk("Device is Ready!\r\n");
442     set_device_is_ready(HI_TRUE);
443     struct wlan_pm_info *wlan_pm_info = wlan_pm_init();
444     if (wlan_pm_info == NULL) {
445         oam_error_log0(0, OAM_SF_ANY, "wlan_pm_init fail error\n");
446     }
447     printk("wlan_pm_open SUCCESSFULLY!!\r\n");
448     return HI_SUCCESS;
449 }
450 
451 /* ****************************************************************************
452  功能描述  : close wifi,如果bfgx没有开,下电,否则下命令关WCPU
453  输入参数  : 无
454  输出参数  : 无
455  返 回 值  : 初始化返回值,成功或失败原因
456 **************************************************************************** */
457 #ifdef _PRE_FEATURE_NO_GPIO
wlan_pm_close(hi_void)458 hi_u32 wlan_pm_close(hi_void)
459 {
460     printk("[plat_pm]wifi need always on,do not close!!\n");
461     return HI_SUCCESS;
462 }
463 #endif
464 
465 /* ****************************************************************************
466  功能描述  : debug, 发消息到device,串口输出维测信息
467  输入参数  : 无
468  输出参数  : 无
469  返 回 值  :
470 **************************************************************************** */
wlan_pm_dump_host_info(void)471 void wlan_pm_dump_host_info(void)
472 {
473     oal_channel_stru *hi_sdio = NULL;
474     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
475 
476     if (wlan_pm == NULL || wlan_pm->bus == NULL) {
477         return;
478     }
479     hi_sdio = (oal_channel_stru *)wlan_pm->bus->priData.data;
480 #if (_PRE_FEATURE_SDIO == _PRE_FEATURE_CHANNEL_TYPE)
481     printk("----------wlan_pm_dump_host_info begin-----------\n");
482     printk("wlan power on:%ld, enable:%ld\n", wlan_pm->wlan_power_state, wlan_pm->wlan_pm_enable);
483     printk("dev state:%ld, sleep stage:%d\n", wlan_pm->wlan_dev_state, wlan_pm->slpack);
484     printk("host sleep state:%ld\n", wlan_pm->wlan_host_state);
485     printk("vote state:%x,g_wlan_pm_disabling:%d \n", wlan_pm->vote_status, g_wlan_pm_disabling);
486     printk("open:%d,close:%d\n", wlan_pm->open_cnt, wlan_pm->close_cnt);
487     printk("gpio_intr[no.%lu]:%llu\n", hi_sdio->ul_wlan_irq, hi_sdio->gpio_int_count);
488     printk("data_intr:%llu\n", hi_sdio->data_int_count);
489     printk("sdio_intr:%llu\n", hi_sdio->sdio_int_count);
490     printk("sdio_intr_finish:%llu\n", hi_sdio->data_int_finish_count);
491 
492     printk("sdio_no_int_count:%u\n", hi_sdio->func1_stat.func1_no_int_count);
493     printk("sdio_err_int_count:%u\n", hi_sdio->func1_stat.func1_err_int_count);
494     printk("sdio_msg_int_count:%u\n", hi_sdio->func1_stat.func1_msg_int_count);
495     printk("sdio_data_int_count:%u\n", hi_sdio->func1_stat.func1_data_int_count);
496     printk("sdio_unknow_int_count:%u\n", hi_sdio->func1_stat.func1_unknow_int_count);
497 
498     printk("wakeup_intr:%llu\n", hi_sdio->wakeup_int_count);
499     printk("D2H_MSG_WAKEUP_SUCC:%d\n", hi_sdio->msg[D2H_MSG_WAKEUP_SUCC].count);
500     printk("D2H_MSG_ALLOW_SLEEP:%d\n", hi_sdio->msg[D2H_MSG_ALLOW_SLEEP].count);
501     printk("D2H_MSG_DISALLOW_SLEEP:%d\n", hi_sdio->msg[D2H_MSG_DISALLOW_SLEEP].count);
502 
503     printk("wakeup_dev_wait_ack:%d\n", oal_atomic_read(&g_wakeup_dev_wait_ack));
504     printk("wakeup_succ:%d\n", wlan_pm->wakeup_succ);
505     printk("wakeup_dev_ack:%d\n", wlan_pm->wakeup_dev_ack);
506     printk("wakeup_done_callback:%d\n", wlan_pm->wakeup_done_callback);
507     printk("wakeup_succ_work_submit:%d\n", wlan_pm->wakeup_succ_work_submit);
508     printk("wakeup_fail_wait_sdio:%d\n", wlan_pm->wakeup_fail_wait_sdio);
509     printk("wakeup_fail_timeout:%d\n", wlan_pm->wakeup_fail_timeout);
510     printk("wakeup_fail_set_reg:%d\n", wlan_pm->wakeup_fail_set_reg);
511     printk("wakeup_fail_submit_work:%d\n", wlan_pm->wakeup_fail_submit_work);
512     printk("sleep_succ:%d\n", wlan_pm->sleep_succ);
513     printk("dev_sleep_wait_ack:%d\n", oal_atomic_read(&g_dev_sleep_wait_ack));
514     printk("sleep_msg_send_cnt:%d\n", wlan_pm->sleep_msg_send_cnt);
515     printk("sleep_dev_ack_cnt:%d\n", wlan_pm->sleep_dev_ack_cnt);
516     printk("sleep feed wdg:%d\n", wlan_pm->sleep_feed_wdg_cnt);
517     printk("sleep start wdg timer:%d\n", wlan_pm->sleep_start_wdg_timer_cnt);
518     printk("sleep_fail_request:%d\n", wlan_pm->sleep_fail_request);
519     printk("sleep_fail_set_reg:%d\n", wlan_pm->sleep_fail_set_reg);
520     printk("sleep_fail_wait_timeout:%d\n", wlan_pm->sleep_fail_wait_timeout);
521     printk("sleep_fail_forbid:%d\n", wlan_pm->sleep_fail_forbid);
522     printk("sleep_work_submit:%d\n", wlan_pm->sleep_work_submit);
523     printk("----------wlan_pm_dump_host_info end-----------\n");
524 #endif
525 }
526 
527 /* ****************************************************************************
528  功能描述  : device侧低功耗维测信息,串口输出维测信息
529  输入参数  : 无
530  输出参数  : 无
531  返 回 值  :
532 **************************************************************************** */
wlan_pm_dump_device_pm_info(char * buf,int length)533 void wlan_pm_dump_device_pm_info(char *buf, int length)
534 {
535     hi_device_lpc_info *lpc_info = (hi_device_lpc_info *)buf;
536     if (lpc_info == HI_NULL || length < (int)sizeof(hi_device_lpc_info)) {
537         oam_error_log2(0, 0, "length = %d, %d", length, sizeof(hi_device_lpc_info));
538         return;
539     }
540     printk("----------wlan_pm_dump_device_pm_info begin-----------\n");
541     printk("wakeup_times:%u\n", lpc_info->wakeup_times);
542     printk("sleep_threshold_refuse_times:%u\n", lpc_info->sleep_threshold_refuse_times);
543     printk("sleep_check_refuse_times:%u\n", lpc_info->sleep_check_refuse_times);
544     printk("sleep_times:%u\n", lpc_info->sleep_times);
545     printk("sleep_threshold:%u\n", lpc_info->sleep_threshold);
546     printk("dsleep_fail_times:%u\n", lpc_info->dsleep_fail_times);
547     printk("type:%d\n", lpc_info->type);
548     printk("evt_sts:%x\n", lpc_info->evt_sts);
549     printk("int_sts:%x\n", lpc_info->int_sts);
550     printk("last_time_vote_state:%d\n", lpc_info->last_time_vote_state);
551     printk("timer_ticks:%u\n", lpc_info->timer_ticks);
552     printk("timer_handle:%x\n", lpc_info->timer_handle);
553     printk("timer_handle_arg:%u\n", lpc_info->timer_handle_arg);
554     printk("task_id:%u\n", lpc_info->task_id);
555     printk("task_ticks:%d\n", lpc_info->task_ticks);
556     printk("sleep_ticks:%d\n", lpc_info->sleep_ticks);
557     printk("veto_info:%x\n", lpc_info->veto_info);
558     printk("sdio_busy:%u\n", lpc_info->sdio_busy);
559     printk("host_sleeped:%d\n", lpc_info->host_sleeped);
560     printk("host_allow_dev_sleep:%d\n", lpc_info->host_allow_dev_sleep);
561     printk("sdio_allow_sleep:%d\n", lpc_info->sdio_allow_sleep);
562     printk("refuse_vote_handle:%x\n", lpc_info->refuse_vote_handle);
563     printk("host_allow_device_slp_times:%u\n", lpc_info->host_allow_device_slp_times);
564     printk("sdio_wkup_int_times:%u\n", lpc_info->sdio_wkup_int_times);
565     printk("device_sdio_wkup_ack_times:%u\n", lpc_info->device_sdio_wkup_ack_times);
566     printk("sdio_busy_times:%u\n", lpc_info->sdio_busy_times);
567     printk("host_vote_work_times:%u\n", lpc_info->host_vote_work_times);
568     printk("sdio_vote_work_times:%u\n", lpc_info->sdio_vote_work_times);
569 
570     printk("----------wlan_pm_dump_device_pm_info end-----------\n");
571 }
572 
wlan_pm_dump_device_info(hi_void)573 hi_void wlan_pm_dump_device_info(hi_void)
574 {
575     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
576     if (wlan_pm == HI_NULL) {
577         return;
578     }
579     oal_bus_send_msg(wlan_pm->bus, H2D_MSG_PM_DEBUG);
580 }
581 
582 /* ****************************************************************************
583  功能描述  : 打印低功耗维测信息
584  输入参数  : 1:host,0:device
585  输出参数  : 无
586  返 回 值  :
587 **************************************************************************** */
hi_wlan_dump_pm_info(hi_u8 is_host)588 hi_void hi_wlan_dump_pm_info(hi_u8 is_host)
589 {
590     if (is_host > 1) { /* 大于1为异常参数 */
591         printk("para error, 1 : host, 0 : device;input:%u \n", is_host);
592         return;
593     }
594     if (is_host) {
595         wlan_pm_dump_host_info();
596     } else {
597         wlan_pm_dump_device_info();
598     }
599 }
600 
601 /* ****************************************************************************
602  功能描述  : 唤醒流程reinit chan
603  输入参数  : 无
604  输出参数  : 无
605  返 回 值  : 初始化返回值,成功或失败原因
606 **************************************************************************** */
wlan_pm_chan_reinit(void)607 hi_s32 wlan_pm_chan_reinit(void)
608 {
609 #if (_PRE_FEATURE_SDIO == _PRE_FEATURE_CHANNEL_TYPE)
610     hi_s32 ret = HI_SUCCESS;
611 #ifdef _PRE_WLAN_PM_FEATURE_FORCESLP_RESUME
612     if (wlan_resume_state_get() != 0) { // forceslp resume flow
613 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
614         ret = oal_sdio_func_probe_resume(oal_get_bus_default_handler());
615 #endif
616     }
617 #endif
618     return ret;
619 #else
620     return HI_SUCCESS;
621 #endif
622 }
623 
624 /* ****************************************************************************
625  功能描述  : 唤醒device
626  输入参数  : 无
627  输出参数  : 无
628  返 回 值  : 初始化返回值,成功或失败原因
629 **************************************************************************** */
wlan_pm_wakeup_dev_again(hi_void)630 hi_s32 wlan_pm_wakeup_dev_again(hi_void)
631 {
632     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
633     hi_s32 ret;
634     if (wlan_pm == HI_NULL || wlan_pm->bus == HI_NULL) {
635         oam_warning_log0(0, OAM_SF_PWR, "[pm]HI_NULL!!");
636         return HI_FAIL;
637     }
638     hi_u32 wakeup_times = 0;
639     for (; wakeup_times < WLAN_TRY_WAKEUP_FAIL_TIMES; wakeup_times++) {
640         OAL_INIT_COMPLETION(&wlan_pm->wakeup_done);
641         oal_atomic_set(&g_wakeup_dev_wait_ack, 1);
642         /* 写device sdio寄存器,允许睡眠 */
643         if (wakeup_times) {
644             oal_sdio_sleep_dev(wlan_pm->bus);
645         }
646         /* waitting for dev channel stable */
647         mdelay(10); /* delay 10ms */
648         ret = oal_sdio_wakeup_dev(wlan_pm->bus);
649         if (ret < 0) {
650             wlan_pm->wakeup_fail_wait_sdio++;
651             oam_warning_log1(0, OAM_SF_PWR, "[pm]sdio wake device failed!,  ret:%d!\n", ret);
652             continue;
653         }
654         ret = (hi_s32)oal_wait_for_completion_timeout(&wlan_pm->wakeup_done,
655             (hi_u32)OAL_MSECS_TO_JIFFIES(WLAN_WAKUP_MSG_WAIT_TIMEOUT));
656         if (ret == 0) {
657             wlan_pm->wakeup_fail_timeout++;
658             printk("wlan_pm_wakeup_dev_again wait cor completion timeout[%u]\n", wakeup_times);
659             continue;
660         }
661         return HI_SUCCESS;
662     }
663     printk("[ERROR]wk again fail:[%u] \n", wakeup_times);
664     return HI_FAIL;
665 }
666 
wlan_pm_wakeup_fail_process(hi_void)667 hi_void wlan_pm_wakeup_fail_process(hi_void)
668 {
669     oal_msleep(200); /* sleep 200ms */
670     printk("wakeup device fail, dump host pm msg and notification app layer \r\n");
671     /* 打印host侧pm统计信息 */
672     wlan_pm_dump_host_info();
673 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
674     /* 通知应用层 */
675     wlan_pm_wkfail_send_sig();
676 #elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
677     if (g_wkup_fail_cb != NULL) {
678         g_wkup_fail_cb();
679     } else {
680         printk("wk fail process not register \n");
681     }
682 #endif
683 #if (_PRE_FEATURE_SDIO == _PRE_FEATURE_CHANNEL_TYPE)
684     oal_wakeup_exception();
685 #endif
686 }
687 
wlan_pm_wakeup_dev(hi_void)688 unsigned long wlan_pm_wakeup_dev(hi_void)
689 {
690     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
691     hi_s32 ret;
692     if (wlan_pm == HI_NULL || wlan_pm->bus == HI_NULL) {
693         oam_error_log0(0, OAM_SF_PWR, "[pm]HI_NULL!!");
694         return HI_SUCCESS;
695     }
696     if (wlan_pm->wlan_power_state == POWER_STATE_SHUTDOWN) {
697         return OAL_EFAIL;
698     }
699 
700     if ((wlan_pm->wlan_dev_state == HOST_DISALLOW_TO_SLEEP) || (wlan_pm->wlan_pm_enable == HI_FALSE)) {
701         return HI_SUCCESS;
702     } else if (wlan_pm->wlan_dev_state == HOST_EXCEPTION) {
703         return OAL_EFAIL;
704     }
705     /* wait for sdio wakeup */
706     ret = oal_down_timeout(&g_chan_wake_sema, TIMEOUT_MUTIPLE_6 * OAL_TIME_HZ);
707     if (ret == -ETIME) {
708         wlan_pm->wakeup_fail_wait_sdio++;
709         oam_error_log0(0, OAM_SF_PWR, "[pm]sdio controller is not ready!");
710         goto wakeup_fail;
711     }
712     oal_up(&g_chan_wake_sema);
713 
714 #if (_PRE_FEATURE_SDIO == _PRE_FEATURE_CHANNEL_TYPE)
715     oal_wlan_gpio_intr_enable(wlan_pm->bus, HI_FALSE);
716 #endif
717     wlan_pm->wakeup_gpio_up_cnt++;
718 #ifndef _PRE_FEATURE_NO_GPIO
719     board_set_wlan_h2d_pm_state(WLAN_PM_WKUPDEV_LEVEL);
720 #endif
721 #if (_PRE_FEATURE_SDIO == _PRE_FEATURE_CHANNEL_TYPE)
722     oal_wlan_gpio_intr_enable(wlan_pm->bus, HI_TRUE);
723 #endif
724     wlan_pm_state_set(wlan_pm, HOST_DISALLOW_TO_SLEEP);
725     ret = wlan_pm_wakeup_dev_again();
726     if (ret != HI_SUCCESS) {
727         goto wakeup_fail;
728     }
729     wlan_pm->wakeup_succ++;
730     wlan_pm->wdg_timeout_curr_cnt = 0;
731     wlan_pm->packet_cnt = 0;
732     wlan_pm_feed_wdg();
733     return HI_SUCCESS;
734 wakeup_fail:
735 #ifndef _PRE_FEATURE_NO_GPIO
736     board_set_wlan_h2d_pm_state(WLAN_PM_SLPREQ_LEVEL);
737 #endif
738     wlan_pm_state_set(wlan_pm, HOST_ALLOW_TO_SLEEP);
739     wlan_pm_wakeup_fail_process();
740     return HI_FAIL;
741 }
742 
wlan_pm_wakeup_dev_ack(hi_void)743 hi_void wlan_pm_wakeup_dev_ack(hi_void)
744 {
745     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
746     if (oal_atomic_read(&g_wakeup_dev_wait_ack) != 0) {
747         if (wlan_pm == HI_NULL) {
748             oam_warning_log0(0, OAM_SF_PWR, "wlan_pm_wakeup_dev_ack, dev_info is null \n");
749             return;
750         }
751         OAL_COMPLETE(&wlan_pm->wakeup_done);
752         oal_atomic_set(&g_wakeup_dev_wait_ack, 0);
753     }
754     return;
755 }
756 
757 /* ****************************************************************************
758  功能描述  : device唤醒host
759  输入参数  : 无
760  输出参数  : 无
761  返 回 值  : 初始化返回值,成功或失败原因
762 **************************************************************************** */
wlan_pm_wakeup_host(void)763 unsigned long wlan_pm_wakeup_host(void)
764 {
765     oal_channel_stru *hi_sdio = NULL;
766     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
767 
768     if (wlan_pm == NULL || wlan_pm->bus == NULL) {
769         printk("wlan_pm_wakeup_host pst wlan pm is null \r\n");
770         return HI_SUCCESS;
771     }
772     oal_bus_wake_lock(wlan_pm->bus);
773     if (wlan_pm_work_submit(wlan_pm, &wlan_pm->wakeup_work) != 0) {
774         wlan_pm->wakeup_fail_submit_work++;
775 
776         oal_bus_wake_unlock(wlan_pm->bus);
777         hi_sdio = (oal_channel_stru *)wlan_pm->bus->priData.data;
778         oam_warning_log1(0, OAM_SF_PWR, "wlan_pm_wakeup_host submit work fail, release wakelock %lu!\n",
779                          hi_sdio->st_sdio_wakelock.lock_count);
780     } else {
781         wlan_pm->wakeup_succ_work_submit++;
782     }
783     return HI_SUCCESS;
784 }
785 
786 /* ****************************************************************************
787  功能描述  : device ack处理
788  输入参数  : 无
789  输出参数  : 无
790  返 回 值  :
791 **************************************************************************** */
wlan_pm_ack_handle(hi_s32 ack,hi_void * data)792 hi_void wlan_pm_ack_handle(hi_s32 ack, hi_void *data)
793 {
794     struct wlan_pm_info *wlan_pm = (struct wlan_pm_info *)data;
795     if (wlan_pm == NULL) {
796         oam_info_log0(0, OAM_SF_PWR, "[pm]wlan_pm_ack_handle data is null !\n");
797         return;
798     }
799     wlan_pm->sleep_dev_ack_cnt++;
800     if (oal_atomic_read(&g_dev_sleep_wait_ack) != 0) {
801         wlan_pm->slpack = ack;
802         OAL_COMPLETE(&wlan_pm->sleep_request_ack);
803         oal_atomic_set(&g_dev_sleep_wait_ack, 0);
804     }
805 }
806 
807 /* ****************************************************************************
808  功能描述  : device应答allow_sleep消息处理
809  输入参数  : 无
810  输出参数  : 无
811  返 回 值  :
812 **************************************************************************** */
wlan_pm_allow_sleep_callback(void * data)813 hi_s32 wlan_pm_allow_sleep_callback(void *data)
814 {
815     wlan_pm_ack_handle(SLPACK_DEV_ALLOW, data);
816     return SUCCESS;
817 }
818 
819 /* ****************************************************************************
820  功能描述  : device应答allow_sleep消息处理
821  输入参数  : 无
822  输出参数  : 无
823  返 回 值  :
824 **************************************************************************** */
wlan_pm_disallow_sleep_callback(void * data)825 hi_s32 wlan_pm_disallow_sleep_callback(void *data)
826 {
827     wlan_pm_ack_handle(SLPACK_DEV_DISALLOW, data);
828     return SUCCESS;
829 }
830 
831 /* ****************************************************************************
832  功能描述  : device应答host sleep消息处理
833  输入参数  : 无
834  输出参数  : 无
835  返 回 值  :
836 **************************************************************************** */
wlan_pm_host_sleep_ack_callback(void * data)837 hi_s32 wlan_pm_host_sleep_ack_callback(void *data)
838 {
839     struct wlan_pm_info *wlan_pm = (struct wlan_pm_info *)data;
840     if (wlan_pm == NULL) {
841         oam_info_log0(0, OAM_SF_PWR, "[pm]wlan_pm_ack_handle data is null !\n");
842         return SUCCESS;
843     }
844     OAL_COMPLETE(&wlan_pm->host_sleep_request_ack);
845     return SUCCESS;
846 }
847 
848 /* ****************************************************************************
849  功能描述  : device唤醒host work
850  输入参数  : 无
851  输出参数  : 无
852  返 回 值  : 初始化返回值,成功或失败原因
853 **************************************************************************** */
wlan_pm_wakeup_work(oal_work_stru * worker)854 void wlan_pm_wakeup_work(oal_work_stru *worker)
855 {
856     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
857     unsigned long ret;
858     hi_unref_param(worker);
859     if (wlan_pm == NULL || wlan_pm->bus == NULL) {
860         return;
861     }
862     hcc_tx_transfer_lock(hcc_host_get_handler());
863 
864     ret = wlan_pm_wakeup_dev();
865     if (ret != HI_SUCCESS) {
866         oam_error_log0(0, 0, "wlan wakeup fail !");
867     }
868     hcc_tx_transfer_unlock(hcc_host_get_handler());
869     oal_bus_wake_unlock(wlan_pm->bus);
870     oam_info_log0(0, OAM_SF_PWR, "wlan_d2h_wakeup_succ !\n");
871     return;
872 }
873 
874 /* ****************************************************************************
875  功能描述  : device应答wakeup succ消息处理
876  输入参数  : 无
877  输出参数  : 无
878  返 回 值  :
879 **************************************************************************** */
wlan_pm_wakeup_done_callback(void * data)880 hi_s32 wlan_pm_wakeup_done_callback(void *data)
881 {
882     struct wlan_pm_info *wlan_pm = (struct wlan_pm_info *)data;
883     if (wlan_pm == NULL) {
884         oam_info_log0(0, OAM_SF_PWR, "[pm]wlan_pm_wakeup_done_callback data is null !\n");
885         return SUCCESS;
886     }
887     wlan_pm->wakeup_done_callback++;
888     wlan_pm_wakeup_dev_ack();
889     return SUCCESS;
890 }
891 
892 /* ****************************************************************************
893  功能描述  : dfx时更新dev状态为异常
894  输入参数  : 无
895  输出参数  : 无
896  返 回 值  : 初始化返回值,成功或失败原因
897 **************************************************************************** */
wlan_pm_set_pm_sts_exception(hi_void)898 hi_u32 wlan_pm_set_pm_sts_exception(hi_void)
899 {
900     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
901     if (wlan_pm == HI_NULL) {
902         return HI_FAIL;
903     }
904     wlan_pm_state_set(wlan_pm, HOST_EXCEPTION);
905     return HI_SUCCESS;
906 }
907 
908 /* ****************************************************************************
909  功能描述  : 允许device睡眠
910  输入参数  : 无
911  输出参数  : 无
912  返 回 值  : 成功或失败原因
913 **************************************************************************** */
wlan_pm_sleep_work(oal_work_stru * worker)914 void wlan_pm_sleep_work(oal_work_stru *worker)
915 {
916     hi_unref_param(worker);
917     unsigned long ret;
918     ret = wlan_pm_dev_sleep_request();
919     if (ret != HI_SUCCESS) {
920         oam_info_log0(0, 0, "wlan_pm_sleep_work fail !");
921     }
922 }
923 
924 /* ****************************************************************************
925  功能描述  : host向device发送睡眠请求,表明host想睡
926  输入参数  : true:通知device host要睡眠,false:通知device host不睡
927  输出参数  : 无
928  返 回 值  : HI_SUCCESS/FAIL
929 **************************************************************************** */
hi_wifi_host_request_sleep(bool slp)930 unsigned int hi_wifi_host_request_sleep(bool slp)
931 {
932     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
933     hi_s32 l_ret;
934     hi_u32 ul_ret;
935 
936     if (wlan_pm == HI_NULL || wlan_pm->bus == HI_NULL) {
937         oam_warning_log0(0, OAM_SF_PWR, "[pm]HI_NULL!!");
938         return HI_FAIL;
939     }
940     hcc_tx_transfer_lock(hcc_host_get_handler());
941     if ((wlan_pm->wlan_host_state == HOST_SLEEPED) && slp) {
942         hcc_tx_transfer_unlock(hcc_host_get_handler());
943         return HI_SUCCESS;
944     }
945     if ((wlan_pm->wlan_host_state == HOST_NOT_SLEEP) && (!slp)) {
946         hcc_tx_transfer_unlock(hcc_host_get_handler());
947         return HI_SUCCESS;
948     }
949     if (wlan_pm_wakeup_dev() != HI_SUCCESS) {
950         oam_info_log0(0, OAM_SF_PWR, "[pm]host slp request, wkeup dev fail!");
951         hcc_tx_transfer_unlock(hcc_host_get_handler());
952         return HI_FAIL;
953     }
954     OAL_INIT_COMPLETION(&wlan_pm->host_sleep_request_ack);
955     if (slp) {
956         l_ret = oal_bus_send_msg(wlan_pm->bus, H2D_MSG_HOST_SLEEP);
957     } else {
958         l_ret = oal_bus_send_msg(wlan_pm->bus, H2D_MSG_HOST_DISSLEEP);
959     }
960     if (l_ret != HI_SUCCESS) {
961         oam_error_log0(0, OAM_SF_PWR, "[pm]wlan_pm_sleep_request fail !\n");
962         goto fail_sleep;
963     }
964     ul_ret = oal_wait_for_completion_timeout(&wlan_pm->host_sleep_request_ack,
965         (hi_u32)OAL_MSECS_TO_JIFFIES(WLAN_SLEEP_MSG_WAIT_TIMEOUT));
966     if (ul_ret == 0) {
967         oam_error_log0(0, 0, "wait dev ack timeout !");
968         goto fail_sleep;
969     }
970     wlan_pm->wlan_host_state = slp ? HOST_SLEEPED : HOST_NOT_SLEEP;
971     hcc_tx_transfer_unlock(hcc_host_get_handler());
972     return HI_SUCCESS;
973 fail_sleep:
974     hcc_tx_transfer_unlock(hcc_host_get_handler());
975     oam_error_log0(0, 0, "hi_wifi_host_request_sleep fail !");
976     return HI_FAIL;
977 }
978 
979 
980 /* ****************************************************************************
981  功能描述  : 发送允许device睡眠 请求给device
982  输入参数  : 无
983  输出参数  : 无
984  返 回 值  : HI_SUCCESS/FAIL
985 **************************************************************************** */
wlan_pm_allow_dev_sleep(void)986 hi_s32 wlan_pm_allow_dev_sleep(void)
987 {
988     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
989     hi_s32 ret;
990     if (wlan_pm == HI_NULL || wlan_pm->bus == HI_NULL) {
991         oam_warning_log0(0, OAM_SF_PWR, "[pm]HI_NULL!!");
992         return HI_FAIL;
993     }
994     wlan_pm->slpack = SLPACK_DEV_ALLOW;
995     OAL_INIT_COMPLETION(&wlan_pm->sleep_request_ack);
996     wlan_pm->sleep_msg_send_cnt++;
997 
998     oal_atomic_set(&g_dev_sleep_wait_ack, 1);
999     ret = oal_bus_send_msg(wlan_pm->bus, H2D_MSG_SLEEP_REQ);
1000     if (ret != HI_SUCCESS) {
1001         wlan_pm->sleep_fail_request++;
1002         oal_atomic_set(&g_dev_sleep_wait_ack, 0);
1003         oam_warning_log0(0, OAM_SF_PWR, "[pm]wlan_pm_sleep_request send msg fail !\n");
1004         return OAL_EFAIL;
1005     }
1006     ret = (hi_s32)oal_wait_for_completion_timeout(&wlan_pm->sleep_request_ack,
1007         (hi_u32)OAL_MSECS_TO_JIFFIES(WLAN_SLEEP_MSG_WAIT_TIMEOUT));
1008     if (ret == 0) {
1009         /* 超时处理,拉低gpio通知dev流程完成,再拉高gpio告知dev睡眠失败 */
1010 #ifndef _PRE_FEATURE_NO_GPIO
1011         board_set_wlan_h2d_pm_state(WLAN_PM_SLPREQ_LEVEL);
1012         board_set_wlan_h2d_pm_state(WLAN_PM_WKUPDEV_LEVEL);
1013 #endif
1014         wlan_pm->slpreq_flag = NO_SLPREQ_STATUS;
1015         wlan_pm->sleep_fail_wait_timeout++;
1016         oam_warning_log3(0, OAM_SF_PWR, "[pm]sleep_work timeouts:%u,msg send:%d,ack cnt:%d !\n",
1017             wlan_pm->sleep_fail_wait_timeout, wlan_pm->sleep_msg_send_cnt, wlan_pm->sleep_dev_ack_cnt);
1018         return OAL_EFAIL;
1019     }
1020     if (wlan_pm->slpack == SLPACK_DEV_DISALLOW) {
1021         wlan_pm->sleep_fail_forbid++;
1022         return OAL_EFAIL;
1023     }
1024     return HI_SUCCESS;
1025 }
wlan_pm_dev_sleep_request(void)1026 unsigned long wlan_pm_dev_sleep_request(void)
1027 {
1028     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
1029     hi_s32 ret;
1030     if (wlan_pm == HI_NULL || wlan_pm->bus == HI_NULL) {
1031         oam_error_log0(0, OAM_SF_PWR, "[pm]HI_NULL!!");
1032         return HI_FAIL;
1033     }
1034     wlan_pm->wdg_timeout_curr_cnt = 0;
1035     wlan_pm->packet_cnt = 0;
1036     hcc_tx_transfer_lock(hcc_host_get_handler());
1037     if ((wlan_pm->wlan_pm_enable == HI_FALSE) || (wlan_pm->vote_status)) {
1038         wlan_pm_feed_wdg();
1039         hcc_tx_transfer_unlock(hcc_host_get_handler());
1040         return HI_SUCCESS;
1041     }
1042     if (wlan_pm->wlan_dev_state == HOST_ALLOW_TO_SLEEP) {
1043         hcc_tx_transfer_unlock(hcc_host_get_handler());
1044         return HI_SUCCESS;
1045     } else if (wlan_pm->wlan_dev_state == HOST_EXCEPTION) {
1046         oam_info_log0(0, OAM_SF_PWR, "[pm]host exception, don't sleep!");
1047         hcc_tx_transfer_unlock(hcc_host_get_handler());
1048         return OAL_EFAIL;
1049     }
1050     ret = wlan_pm_allow_dev_sleep();
1051     if (ret != HI_SUCCESS) {
1052         goto fail_sleep;
1053     }
1054 #if (_PRE_FEATURE_SDIO == _PRE_FEATURE_CHANNEL_TYPE)
1055     oal_wlan_gpio_intr_enable(wlan_pm->bus, HI_FALSE);
1056 #endif
1057     wlan_pm->sleep_gpio_low_cnt++;
1058     wlan_pm_state_set(wlan_pm, HOST_ALLOW_TO_SLEEP);
1059     /* 拉低gpio告知dev流程结束并等待dev去读状态 */
1060 #ifndef _PRE_FEATURE_NO_GPIO
1061     board_set_wlan_h2d_pm_state(WLAN_PM_SLPREQ_LEVEL);
1062 #endif
1063 
1064 #if (_PRE_FEATURE_SDIO == _PRE_FEATURE_CHANNEL_TYPE)
1065     /* 等待dev读取gpio状态完毕 */
1066     udelay(100); /* delay 100us */
1067     /* 写device sdio寄存器,允许睡眠 */
1068     oal_sdio_sleep_dev(wlan_pm->bus);
1069     oal_wlan_gpio_intr_enable(wlan_pm->bus, HI_TRUE);
1070 #endif
1071     hcc_tx_transfer_unlock(hcc_host_get_handler());
1072     wlan_pm->sleep_succ++;
1073     return HI_SUCCESS;
1074 fail_sleep:
1075     wlan_pm_feed_wdg();
1076     hcc_tx_transfer_unlock(hcc_host_get_handler());
1077     return HI_FAIL;
1078 }
1079 
1080 #ifdef _PRE_WLAN_PM_FEATURE_FORCESLP_RESUME
1081 
wlan_resume_state_set(hi_u32 ul_state)1082 hi_void wlan_resume_state_set(hi_u32 ul_state)
1083 {
1084 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
1085     if (ul_state == 0) {
1086         g_ul_wlan_resume_state = 0;
1087     } else {
1088         g_ul_wlan_resume_state = 1;
1089 
1090         g_ul_wlan_resume_wifi_init_flag = g_ul_wlan_resume_state;
1091     }
1092 #endif
1093 }
1094 
wlan_resume_state_get(hi_void)1095 hi_u32 wlan_resume_state_get(hi_void)
1096 {
1097 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
1098     return g_ul_wlan_resume_state;
1099 #else
1100     return 0;
1101 #endif
1102 }
1103 #endif
1104 
1105 /* ****************************************************************************
1106  功能描述  : 获取pm的sleep状态
1107  输入参数  :
1108  输出参数  :
1109  返 回 值  : 1:allow to sleep; 0:disallow to sleep
1110 **************************************************************************** */
wlan_pm_state_get(void)1111 unsigned long wlan_pm_state_get(void)
1112 {
1113     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
1114     if (wlan_pm == HI_NULL) {
1115         return DEV_SHUTDOWN;
1116     }
1117     return wlan_pm->wlan_dev_state;
1118 }
1119 
1120 /* ****************************************************************************
1121  功能描述  : 获取pm的sleep状态
1122  输入参数  :
1123  输出参数  :
1124  返 回 值  : 1:allow to sleep; 0:disallow to sleep
1125 **************************************************************************** */
wlan_pm_state_set(struct wlan_pm_info * wlan_pm,unsigned long state)1126 hi_void wlan_pm_state_set(struct wlan_pm_info *wlan_pm, unsigned long state)
1127 {
1128     oal_channel_stru *hi_sdio = (oal_channel_stru *)wlan_pm->bus->priData.data;
1129     unsigned long flag;
1130     if (wlan_pm == HI_NULL) {
1131         oam_error_log0(0, 0, "wlan_pm_state_set pm info is null !");
1132         return;
1133     }
1134     oal_spin_lock_irq_save(&hi_sdio->st_pm_state_lock, &flag);
1135     wlan_pm->wlan_dev_state = state;
1136     oal_spin_unlock_irq_restore(&hi_sdio->st_pm_state_lock, &flag);
1137 }
1138 
1139 /* ****************************************************************************
1140  功能描述  : 睡眠定时器超时时间设置
1141  输入参数  : 无
1142  输出参数  : 无
1143  返 回 值  : 初始化返回值,成功或失败原因
1144 **************************************************************************** */
wlan_pm_set_timeout(hi_u32 timeout)1145 hi_void wlan_pm_set_timeout(hi_u32 timeout)
1146 {
1147     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
1148     if (wlan_pm == HI_NULL) {
1149         oam_error_log0(0, 0, "wlan_pm_set_timeout dev info not init !");
1150         return;
1151     }
1152     oam_info_log1(0, OAM_SF_PWR, "wlan_pm_set_timeout[%d]", timeout);
1153 
1154     wlan_pm->wdg_timeout_cnt = timeout;
1155     wlan_pm->wdg_timeout_curr_cnt = 0;
1156     wlan_pm->packet_cnt = 0;
1157     wlan_pm_feed_wdg();
1158 }
1159 
1160 /* ****************************************************************************
1161  功能描述  : 启动50ms睡眠定时器
1162  输入参数  : 无
1163  输出参数  : 无
1164  返 回 值  : 初始化返回值,成功或失败原因
1165 **************************************************************************** */
wlan_pm_feed_wdg(hi_void)1166 hi_void wlan_pm_feed_wdg(hi_void)
1167 {
1168     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
1169     if (wlan_pm == NULL) {
1170         oam_error_log0(0, 0, "wlan_pm_feed_wdg dev info not init !");
1171         return;
1172     }
1173     wlan_pm->sleep_feed_wdg_cnt++;
1174     if ((wlan_pm->wlan_pm_enable) && (wlan_pm->vote_status == 0)) {
1175         oal_timer_start(&wlan_pm->watchdog_timer, WLAN_SLEEP_TIMER_PERIOD);
1176         wlan_pm->sleep_start_wdg_timer_cnt++;
1177     }
1178 }
1179 
1180 /* ****************************************************************************
1181  功能描述  : 停止50ms睡眠定时器
1182  输入参数  : 无
1183  输出参数  : 无
1184  返 回 值  : 初始化返回值,成功或失败原因
1185 **************************************************************************** */
wlan_pm_stop_wdg(hi_void)1186 hi_s32 wlan_pm_stop_wdg(hi_void)
1187 {
1188     oam_info_log0(0, OAM_SF_PWR, "wlan_pm_stop_wdg \r\n");
1189     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
1190     if (wlan_pm == NULL) {
1191         oam_error_log0(0, 0, "wlan_pm_stop_wdg dev info not init !");
1192         return HI_FAIL;
1193     }
1194     wlan_pm->wdg_timeout_curr_cnt = 0;
1195     wlan_pm->packet_cnt = 0;
1196     if (in_interrupt()) {
1197         return oal_timer_delete(&wlan_pm->watchdog_timer);
1198     } else {
1199         return oal_timer_delete_sync(&wlan_pm->watchdog_timer);
1200     }
1201 }
1202 
wlan_pm_set_packet_cnt(hi_u32 delt)1203 hi_void wlan_pm_set_packet_cnt(hi_u32 delt)
1204 {
1205     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
1206     if (wlan_pm == NULL) {
1207         oam_warning_log0(0, OAM_SF_PWR, "[pm] dev info is null \n");
1208         return;
1209     }
1210     wlan_pm->packet_cnt += delt;
1211 }
1212 
1213 /* ****************************************************************************
1214  功能描述  : 50ms睡眠定时器超时处理,提交一个sleep work
1215  输入参数  : 无
1216  输出参数  : 无
1217  返 回 值  : 初始化返回值,成功或失败原因
1218 **************************************************************************** */
wlan_pm_wdg_timeout(struct wlan_pm_info * wlan_pm)1219 void wlan_pm_wdg_timeout(struct wlan_pm_info *wlan_pm)
1220 {
1221     if (wlan_pm == NULL) {
1222         oam_error_log0(0, 0, "wlan_pm_wdg_timeout dev info is null !");
1223         return;
1224     }
1225     if ((wlan_pm->wlan_pm_enable) && (wlan_pm->vote_status == 0)) {
1226         if (wlan_pm->packet_cnt == 0) {
1227             wlan_pm->wdg_timeout_curr_cnt++;
1228             if ((wlan_pm->wdg_timeout_curr_cnt >= wlan_pm->wdg_timeout_cnt) &&
1229                 (wlan_pm_work_submit(wlan_pm, &wlan_pm->sleep_work) != 0)) {
1230                 oam_warning_log0(0, OAM_SF_PWR, "wlan_pm_sleep_work submit fail,work is running !\n");
1231             } else if (wlan_pm->wdg_timeout_curr_cnt >= wlan_pm->wdg_timeout_cnt) {
1232                 /* 提交了sleep work后,定时器不重启,避免重复提交sleep work */
1233                 wlan_pm->sleep_work_submit++;
1234                 return;
1235             }
1236         } else {
1237             wlan_pm->wdg_timeout_curr_cnt = 0;
1238             wlan_pm->packet_cnt = 0;
1239         }
1240     } else {
1241         wlan_pm->packet_cnt = 0;
1242         return;
1243     }
1244     wlan_pm_feed_wdg();
1245     return;
1246 }
1247 
wlan_pm_before_device_slp_callback(void * data)1248 hi_s32 wlan_pm_before_device_slp_callback(void *data)
1249 {
1250     (void)data;
1251     printk("!");
1252     return SUCCESS;
1253 }
wlan_pm_device_wkup_callback(void * data)1254 hi_s32 wlan_pm_device_wkup_callback(void *data)
1255 {
1256     (void)data;
1257     printk("!@\n");
1258     return SUCCESS;
1259 }
1260 
1261 
1262 /* ****************************************************************************
1263  功能描述  : WLAN PM device状态初始化接口
1264  输入参数  : 无
1265  输出参数  : 无
1266  返 回 值  : 初始化返回值,成功或失败原因
1267 **************************************************************************** */
wlan_pm_init(void)1268 struct wlan_pm_info *wlan_pm_init(void)
1269 {
1270     struct wlan_pm_info *wlan_pm;
1271     oal_channel_stru *hi_sdio = NULL;
1272     struct BusDev *bus = oal_get_bus_default_handler();
1273 
1274     wlan_pm = oal_kzalloc(sizeof(struct wlan_pm_info), OAL_GFP_KERNEL);
1275     if (wlan_pm == NULL) {
1276         oam_error_log0(0, OAM_SF_PWR, "[pm]no mem to allocate wlan_wk_slp_dev !\n");
1277         return NULL;
1278     }
1279     memset_s(wlan_pm, sizeof(struct wlan_pm_info), 0, sizeof(struct wlan_pm_info));
1280     /* work queue初始化 */
1281     wlan_pm->pm_wq = oal_create_singlethread_workqueue("wlan_pm_wq");
1282     if (wlan_pm->pm_wq == HI_NULL) {
1283         oam_error_log0(0, OAM_SF_PWR, "[plat_pm]Failed to create wlan_pm_wq!\n");
1284         oal_free(wlan_pm);
1285         return HI_NULL;
1286     }
1287     /* 默认关低功耗 */
1288     wlan_pm->wlan_pm_enable  = HI_FALSE;
1289     wlan_pm->vote_status  = 0; /* 默认所有投票都允许device睡眠 */
1290     OAL_INIT_WORK(&wlan_pm->sleep_work,  wlan_pm_sleep_work);
1291 
1292     wlan_pm->bus = bus;
1293     if (wlan_pm->bus == HI_NULL) {
1294         oal_free(wlan_pm);
1295         return HI_NULL;
1296     }
1297     hi_sdio = (oal_channel_stru *)wlan_pm->bus->priData.data;
1298     hi_sdio->pst_pm_callback = &g_wlan_pm_callback;
1299 
1300     oal_spin_lock_init(&hi_sdio->st_pm_state_lock);
1301 
1302     wlan_pm->wlan_power_state           = POWER_STATE_OPEN;
1303     wlan_pm->wlan_dev_state             = HOST_DISALLOW_TO_SLEEP;
1304     wlan_pm->slpreq_flag                = NO_SLPREQ_STATUS;
1305     wlan_pm->slpack                     = SLPACK_DEV_DISALLOW;
1306     wlan_pm->wlan_host_state            = HOST_NOT_SLEEP;
1307     /* sleep timer初始化 */
1308     oal_timer_init(&wlan_pm->watchdog_timer, 0, (void *)wlan_pm_wdg_timeout, (unsigned long)(uintptr_t)wlan_pm);
1309     wlan_pm->wdg_timeout_cnt            = WLAN_SLEEP_DEFAULT_CHECK_CNT;
1310     wlan_pm->wdg_timeout_curr_cnt       = 0;
1311     wlan_pm->packet_cnt                 = 0;
1312 
1313     g_gpst_wlan_pm_info = wlan_pm;
1314 
1315     OAL_INIT_COMPLETION(&wlan_pm->wakeup_done);
1316     OAL_INIT_COMPLETION(&wlan_pm->sleep_request_ack);
1317     OAL_INIT_COMPLETION(&wlan_pm->host_sleep_request_ack);
1318 
1319     oal_bus_message_register(wlan_pm->bus, D2H_MSG_WAKEUP_SUCC, wlan_pm_wakeup_done_callback, wlan_pm);
1320     oal_bus_message_register(wlan_pm->bus, D2H_MSG_ALLOW_SLEEP, wlan_pm_allow_sleep_callback, wlan_pm);
1321     oal_bus_message_register(wlan_pm->bus, D2H_MSG_DISALLOW_SLEEP, wlan_pm_disallow_sleep_callback,
1322         wlan_pm);
1323     oal_bus_message_register(wlan_pm->bus, D2H_MSG_HOST_SLEEP_ACK, wlan_pm_host_sleep_ack_callback,
1324         wlan_pm);
1325     oal_bus_message_register(wlan_pm->bus, D2H_MSG_BEFORE_DEV_SLEEP, wlan_pm_before_device_slp_callback,
1326         NULL);
1327     oal_bus_message_register(wlan_pm->bus, D2H_MSG_DEV_WKUP, wlan_pm_device_wkup_callback, NULL);
1328 
1329     return wlan_pm;
1330 }
1331 
1332 /* ****************************************************************************
1333  功能描述  : WLAN pm退出接口
1334  输入参数  : 无
1335  输出参数  : 无
1336  返 回 值  : 初始化返回值,成功或失败原因
1337 **************************************************************************** */
wlan_pm_exit(hi_void)1338 unsigned long wlan_pm_exit(hi_void)
1339 {
1340     oal_channel_stru *hi_sdio = NULL;
1341     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
1342 
1343     if (wlan_pm == HI_NULL || wlan_pm->bus == HI_NULL) {
1344         return HI_SUCCESS;
1345     }
1346     hi_wifi_plat_pm_disable();
1347     hi_s32 ret = wlan_pm_stop_wdg();
1348     if (ret != HI_SUCCESS) {
1349         oam_error_log0(0, OAM_SF_PWR, "wlan_pm_stop_wdg fail\r\n");
1350     }
1351     oal_sdio_sleep_dev(wlan_pm->bus);
1352     if (wlan_pm->bus != HI_NULL && wlan_pm->bus->priData.data != NULL) {
1353         hi_sdio = (oal_channel_stru *)wlan_pm->bus->priData.data;
1354         hi_sdio->pst_pm_callback = NULL;
1355     }
1356     oal_bus_message_unregister(wlan_pm->bus, D2H_MSG_WAKEUP_SUCC);
1357     oal_bus_message_unregister(wlan_pm->bus, D2H_MSG_ALLOW_SLEEP);
1358     oal_bus_message_unregister(wlan_pm->bus, D2H_MSG_DISALLOW_SLEEP);
1359     oal_bus_message_unregister(wlan_pm->bus, D2H_MSG_HOST_SLEEP_ACK);
1360     oal_bus_message_unregister(wlan_pm->bus, D2H_MSG_WLAN_READY);
1361     oal_bus_message_unregister(wlan_pm->bus, D2H_MSG_BEFORE_DEV_SLEEP);
1362     oal_bus_message_unregister(wlan_pm->bus, D2H_MSG_DEV_WKUP);
1363 
1364     oal_destroy_workqueue(wlan_pm->pm_wq);
1365     kfree(wlan_pm);
1366     g_gpst_wlan_pm_info = HI_NULL;
1367     printk("[plat_pm]wlan_pm_exit SUCCESSFULLY\r\n");
1368     return HI_SUCCESS;
1369 }
1370 
wlan_pm_info_clean(void)1371 void wlan_pm_info_clean(void)
1372 {
1373     oal_channel_stru *hi_sdio = NULL;
1374     struct wlan_pm_info *wlan_pm = wlan_pm_get_drv();
1375     if (wlan_pm == NULL || wlan_pm->bus == NULL) {
1376         return;
1377     }
1378 #if (_PRE_FEATURE_SDIO == _PRE_FEATURE_CHANNEL_TYPE)
1379     hi_sdio = (oal_channel_stru *)wlan_pm->bus->priData.data;
1380     hi_sdio->data_int_count                   = 0;
1381     hi_sdio->wakeup_int_count                 = 0;
1382     hi_sdio->gpio_int_count                   = 0;
1383     hi_sdio->sdio_int_count                   = 0;
1384     hi_sdio->data_int_finish_count            = 0;
1385     hi_sdio->func1_stat.func1_no_int_count    = 0;
1386     hi_sdio->func1_stat.func1_err_int_count   = 0;
1387     hi_sdio->func1_stat.func1_msg_int_count   = 0;
1388     hi_sdio->func1_stat.func1_data_int_count  = 0;
1389     hi_sdio->func1_stat.func1_unknow_int_count = 0;
1390 
1391     hi_sdio->msg[D2H_MSG_WAKEUP_SUCC].count = 0;
1392     hi_sdio->msg[D2H_MSG_ALLOW_SLEEP].count = 0;
1393     hi_sdio->msg[D2H_MSG_DISALLOW_SLEEP].count = 0;
1394     hi_sdio->msg[D2H_MSG_DEVICE_PANIC].count = 0;
1395 
1396     hi_sdio->ul_sdio_suspend               = 0;
1397     hi_sdio->ul_sdio_resume                = 0;
1398 #endif
1399     wlan_pm->wakeup_succ = 0;
1400     wlan_pm->wakeup_dev_ack = 0;
1401     wlan_pm->wakeup_done_callback = 0;
1402     wlan_pm->wakeup_succ_work_submit = 0;
1403     wlan_pm->wakeup_gpio_up_cnt = 0;
1404     wlan_pm->wakeup_fail_wait_sdio = 0;
1405     wlan_pm->wakeup_fail_timeout = 0;
1406     wlan_pm->wakeup_fail_set_reg = 0;
1407     wlan_pm->wakeup_fail_submit_work = 0;
1408 
1409     wlan_pm->sleep_succ = 0;
1410     wlan_pm->sleep_feed_wdg_cnt = 0;
1411     wlan_pm->wakeup_done_callback = 0;
1412     wlan_pm->sleep_fail_set_reg = 0;
1413     wlan_pm->sleep_fail_wait_timeout = 0;
1414     wlan_pm->sleep_fail_forbid = 0;
1415     wlan_pm->sleep_work_submit = 0;
1416     wlan_pm->sleep_msg_send_cnt = 0;
1417     wlan_pm->sleep_gpio_low_cnt = 0;
1418     return;
1419 }
1420