• 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 头文件包含
21 **************************************************************************** */
22 #include <linux/delay.h>
23 #include <linux/rtc.h>
24 
25 #include "plat_pm.h"
26 #include "plat_pm_wlan.h"
27 #include "exception_rst.h"
28 #include "plat_firmware.h"
29 #include "oal_file.h"
30 #include "oal_sdio_host_if.h"
31 #include "hcc_host.h"
32 #include "oam_ext_if.h"
33 #include "oal_chr.h"
34 
35 /* ****************************************************************************
36   3 全局变量定义
37 **************************************************************************** */
38 struct st_exception_info *g_pst_exception_info = HI_NULL;
39 
40 static hi_u8 g_dev_pannic = HI_FALSE;
41 
oal_wakeup_exception(void)42 void oal_wakeup_exception(void)
43 {
44     unsigned long flags;
45 
46     if (g_pst_exception_info == HI_NULL) {
47         printk("[E]%s, g_pst_exception_info is null\n", __FUNCTION__);
48         return;
49     }
50 
51     oal_spin_lock_irq_save(&(g_pst_exception_info->excp_lock), &flags);
52     if (work_busy(&(g_pst_exception_info->excp_worker))) {
53         oal_spin_unlock_irq_restore(&g_pst_exception_info->excp_lock, &flags);
54         return;
55     }
56 
57     g_pst_exception_info->excetion_type = TRANS_FAIL;
58     schedule_work(&(g_pst_exception_info->excp_worker));
59     oal_spin_unlock_irq_restore(&(g_pst_exception_info->excp_lock), &flags);
60 }
61 
oal_exception_submit(hi_s32 excep_type)62 void oal_exception_submit(hi_s32 excep_type)
63 {
64     unsigned long flags;
65 
66     if (g_pst_exception_info == NULL) {
67         printk("[E]%s, g_pst_exception_info is null\n", __FUNCTION__);
68         return;
69     }
70 
71     if (wlan_pm_is_shutdown()) {
72         return;
73     }
74 
75     if (HOST_ALLOW_TO_SLEEP == wlan_pm_state_get()) {
76         return;
77     }
78     wlan_pm_set_pm_sts_exception();
79     oal_spin_lock_irq_save(&(g_pst_exception_info->excp_lock), &flags);
80     if (work_busy(&(g_pst_exception_info->excp_worker))) {
81         printk("excep %d block, exception %d is working\n", excep_type, g_pst_exception_info->excetion_type);
82         oal_spin_unlock_irq_restore(&g_pst_exception_info->excp_lock, &flags);
83         return;
84     }
85 
86     g_pst_exception_info->excetion_type = excep_type;
87     schedule_work(&(g_pst_exception_info->excp_worker));
88     oal_spin_unlock_irq_restore(&(g_pst_exception_info->excp_lock), &flags);
89 }
90 
oal_exception_is_busy(void)91 hi_s32 oal_exception_is_busy(void)
92 {
93     if (oal_unlikely(g_pst_exception_info == NULL)) {
94         return HI_FALSE;
95     }
96 
97     if (work_busy(&(g_pst_exception_info->excp_worker))) {
98         /* sdio mem dump is processing, can't power off or submit repeat */
99         return HI_TRUE;
100     }
101 
102     return HI_FALSE;
103 }
104 
oal_trigger_exception(hi_s32 is_sync)105 hi_s32 oal_trigger_exception(hi_s32 is_sync)
106 {
107     unsigned long timeout_jiffies;
108     struct BusDev *bus = oal_get_bus_default_handler();
109     if (oal_exception_is_busy() == HI_TRUE) {
110         return HI_TRUE;
111     }
112     printk("oal_trigger_exception start\n");
113     /* trigger device panic */
114     if (oal_bus_send_msg(bus, H2D_MSG_TEST) != HI_SUCCESS) {
115         printk("send sdio panic message failed!\n");
116         return HI_FALSE;
117     }
118 
119     if (is_sync != HI_TRUE) {
120         printk("sdio exception is doing...\n");
121         return HI_TRUE;
122     }
123 
124     /* wait device panic */
125     timeout_jiffies = OAL_TIME_JIFFY + OAL_MSECS_TO_JIFFIES(2000); /* jiffies 2000 */
126     for (;;) {
127         if (oal_exception_is_busy() == HI_TRUE) {
128             break;
129         }
130 
131         if (oal_time_after(OAL_TIME_JIFFY, timeout_jiffies) > 0) {
132             printk("wait panic message timeout!\n");
133             return HI_FALSE;
134         }
135 
136         oal_msleep(OAL_JIFFIES_TO_MSECS(1));
137     }
138 
139     printk("trigger sdio exception manually sucuess\n");
140     return HI_TRUE;
141 }
142 
143 /* Try to dump device mem, controlled by flag sdio_dump_mem_flag */
oal_try_to_dump_device_mem(hi_s32 is_sync)144 void oal_try_to_dump_device_mem(hi_s32 is_sync)
145 {
146     hi_s32 ret;
147     if ((g_pst_exception_info->dump_mem_flag) == NOT_DUMP_MEM) {
148         printk("sdio_dump_mem_flag is NOT_DUMP_MEM\r\n");
149         return;
150     }
151 
152     printk("Try to dump device mem!\n");
153     ret = oal_trigger_exception(is_sync);
154     if (ret != HI_TRUE) {
155         printk("call oal_trigger_exception fail!\n");
156     }
157 }
158 
oal_set_dev_panic(hi_void)159 hi_void oal_set_dev_panic(hi_void)
160 {
161     g_dev_pannic = HI_TRUE;
162 }
163 
oal_clear_dev_panic(hi_void)164 hi_void oal_clear_dev_panic(hi_void)
165 {
166     g_dev_pannic = HI_FALSE;
167 }
168 
oal_dev_is_panic(hi_void)169 hi_u8 oal_dev_is_panic(hi_void)
170 {
171     return g_dev_pannic;
172 }
173 
oal_device_panic_callback(void * data)174 hi_s32 oal_device_panic_callback(void *data)
175 {
176     hi_unref_param(data);
177     oam_error_log0(0, 0, "=======device_panic=========\n");
178     oal_set_dev_panic();
179     oal_exception_submit(DEVICE_PANIC);
180     if (hisi_sched_event(DEV_PANIC) != HI_SUCCESS) {
181         printk("DEV_PANIC event notification failed\n");
182     }
183     return HI_SUCCESS;
184 }
185 
oal_frw_exception_report(hi_void)186 hi_void oal_frw_exception_report(hi_void)
187 {
188     if (hisi_sched_event(DRIVER_HUNG) != HI_SUCCESS) {
189         printk("FRW_ENQUEUE_FAIL event notification failed\n");
190     }
191 }
192