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