1 /******************************************************************************
2 *
3 * Copyright(c) 2019 - 2020 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #include "phl_headers.h"
16
17 #ifdef CONFIG_FSM
18 /*
19 * SER stands for System Error Recovery
20 */
21
22 #define SER_FW_TIMEOUT 1000 /* ms */
23 #define SER_POLLING_INTERVAL 10 /* ms */
24 #define SER_USB_POLLING_INTERVAL_IDL 1000 /* ms */
25 #define SER_USB_POLLING_INTERVAL_ACT 10 /* ms */
26
27 #define SER_POLL_IO_TIMES 200
28 #define SER_USB_POLL_IO_TIMES 300
29 #define SER_POLL_BULK_TIMES 100
30
31 #define SER_L0 0x00000001
32 #define SER_L1 0x00000002
33 #define SER_L2 0x00000004
34
35 struct ser_obj {
36 struct fsm_main *fsm;
37 struct phl_info_t *phl_info;
38 struct fsm_obj *fsm_obj;
39
40 int poll_io_times;
41 int poll_bulk_times;
42 bool trigger_l2_reset;
43 bool trigger_l1_reset;
44 bool dynamicThredRunning;
45 _os_lock state_lock;
46 };
47
48 enum SER_STATE_ST {
49 SER_ST_IDLE,
50 SER_ST_L1_PAUSE_TRX,
51 SER_ST_L1_DO_HCI,
52 SER_ST_L1_RESUME_TRX,
53 SER_ST_L2
54 };
55
56 enum SER_EV_ID {
57 SER_EV_L1_START,
58 //SER_EV_L2_START,
59 //SER_EV_M1_PAUSE_TRX,
60 SER_EV_M3_DO_RECOVERY,
61 SER_EV_M5_READY,
62 SER_EV_M9_L2_RESET,
63 SER_EV_FW_TIMER_EXPIRE,
64 SER_EV_POLL_IO_EXPIRE,
65 SER_EV_POLL_BULK_EXPIRE,
66 SER_EV_POLL_USB_INT_EXPIRE,
67 SER_EV_CHK_SER_EVENT,
68 SER_EV_MAX
69 };
70
71 static int ser_idle_st_hdl(void *obj, u16 event, void *param);
72 static int ser_usb_idle_st_hdl(void *obj, u16 event, void *param);
73 static int ser_pci_l1_pause_trx_st_hdl(void *obj, u16 event, void *param);
74 static int ser_usb_l1_pause_trx_st_hdl(void *obj, u16 event, void *param);
75 static int ser_sdio_l1_pause_trx_st_hdl(void *obj, u16 event, void *param);
76 static int ser_pci_l1_do_hci_st_hdl(void *obj, u16 event, void *param);
77 static int ser_usb_l1_do_hci_st_hdl(void *obj, u16 event, void *param);
78 static int ser_sdio_l1_do_hci_st_hdl(void *obj, u16 event, void *param);
79 static int ser_l1_resume_trx_st_hdl(void *obj, u16 event, void *param);
80 static int ser_l2_st_hdl(void *obj, u16 event, void *param);
81
82 /* PCIE STATE table */
83 static struct fsm_state_ent ser_pci_state_tbl[] = {
84 ST_ENT(SER_ST_IDLE, ser_idle_st_hdl),
85 ST_ENT(SER_ST_L1_PAUSE_TRX, ser_pci_l1_pause_trx_st_hdl),
86 ST_ENT(SER_ST_L1_DO_HCI, ser_pci_l1_do_hci_st_hdl),
87 ST_ENT(SER_ST_L1_RESUME_TRX, ser_l1_resume_trx_st_hdl),
88 ST_ENT(SER_ST_L2, ser_l2_st_hdl)
89 };
90
91 /* USB STATE table */
92 static struct fsm_state_ent ser_usb_state_tbl[] = {
93 ST_ENT(SER_ST_IDLE, ser_usb_idle_st_hdl),
94 ST_ENT(SER_ST_L1_PAUSE_TRX, ser_usb_l1_pause_trx_st_hdl),
95 ST_ENT(SER_ST_L1_DO_HCI, ser_usb_l1_do_hci_st_hdl),
96 ST_ENT(SER_ST_L1_RESUME_TRX, ser_l1_resume_trx_st_hdl),
97 ST_ENT(SER_ST_L2, ser_l2_st_hdl)
98 };
99
100 /* SDIO STATE table */
101 static struct fsm_state_ent ser_sdio_state_tbl[] = {
102 ST_ENT(SER_ST_IDLE, ser_idle_st_hdl),
103 ST_ENT(SER_ST_L1_PAUSE_TRX, ser_sdio_l1_pause_trx_st_hdl),
104 ST_ENT(SER_ST_L1_DO_HCI, ser_sdio_l1_do_hci_st_hdl),
105 ST_ENT(SER_ST_L1_RESUME_TRX, ser_l1_resume_trx_st_hdl),
106 ST_ENT(SER_ST_L2, ser_l2_st_hdl)
107 };
108
109
110 /* EVENT table */
111 static struct fsm_event_ent ser_event_tbl[] = {
112 EV_ENT(SER_EV_L1_START),
113 //EV_ENT(SER_EV_L2_START),
114 //EV_ENT(SER_EV_M1_PAUSE_TRX),
115 EV_ENT(SER_EV_M3_DO_RECOVERY),
116 EV_ENT(SER_EV_M5_READY),
117 EV_ENT(SER_EV_M9_L2_RESET),
118 EV_ENT(SER_EV_FW_TIMER_EXPIRE),
119 EV_ENT(SER_EV_POLL_IO_EXPIRE),
120 EV_ENT(SER_EV_POLL_BULK_EXPIRE),
121 EV_DBG(SER_EV_POLL_USB_INT_EXPIRE),
122 EV_ENT(SER_EV_CHK_SER_EVENT),
123 EV_ENT(SER_EV_MAX) /* EV_MAX for fsm safety checking */
124 };
125
_ser_event_notify(void * phl,u8 * p_ntfy)126 static enum rtw_phl_status _ser_event_notify(void *phl, u8* p_ntfy)
127 {
128 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
129 struct ser_obj *pser = phl_info->ser_obj;
130 struct phl_msg msg = {0};
131 enum RTW_PHL_SER_NOTIFY_EVENT notify = RTW_PHL_SER_L2_RESET;
132 u32 err = 0;
133
134 notify = rtw_hal_ser_get_error_status(pser->phl_info->hal, &err);
135
136 if (p_ntfy != NULL)
137 *p_ntfy = notify;
138
139 phl_info->phl_com->phl_stats.ser_event[notify]++;
140
141 PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "_ser_event_notify, error 0x%x, notify 0x%x\n", err, notify);
142
143 if (notify == RTW_PHL_SER_L0_RESET) {
144 PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "_ser_event_notify, hit L0 Reset\n");
145 return RTW_PHL_STATUS_SUCCESS;
146 }
147
148 if (notify == RTW_PHL_SER_LOG_ONLY) {
149 PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "_ser_event_notify, RTW_PHL_SER_LOG_ONLY\n");
150 return RTW_PHL_STATUS_SUCCESS;
151 }
152
153 if (notify == RTW_PHL_SER_DUMP_FW_LOG) {
154 PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "_ser_event_notify, RTW_PHL_SER_DUMP_FW_LOG\n");
155
156 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_MDL_PHY_MGNT);
157 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_DUMP_PLE_BUFFER);
158 phl_msg_hub_send(phl_info, NULL, &msg);
159
160 return RTW_PHL_STATUS_SUCCESS;
161 }
162
163 return phl_ser_send_msg(phl, notify);
164 }
165
166
167 /*
168 * SER sub function
169 */
ser_pcie_pause_dma_io(struct ser_obj * pser)170 void ser_pcie_pause_dma_io(struct ser_obj *pser)
171 {
172 FSM_DBG(pser->fsm, "%s: %s\n",
173 phl_fsm_obj_name(pser->fsm_obj), __func__);
174 }
175
ser_polling_io_state(struct ser_obj * pser)176 int ser_polling_io_state(struct ser_obj *pser)
177 {
178 FSM_DBG(pser->fsm, "%s: %s\n",
179 phl_fsm_obj_name(pser->fsm_obj), __func__);
180 return 0; /* success */
181 }
182
ser_return_all_tcb_and_mem(struct ser_obj * pser)183 void ser_return_all_tcb_and_mem(struct ser_obj *pser)
184 {
185 FSM_DBG(pser->fsm, "%s: %s\n",
186 phl_fsm_obj_name(pser->fsm_obj), __func__);
187 }
188
ser_send_l0_handle_method_event(struct ser_obj * pser,enum RTW_PHL_SER_RCVY_STEP event)189 void ser_send_l0_handle_method_event(struct ser_obj *pser, enum RTW_PHL_SER_RCVY_STEP event)
190 {
191 FSM_DBG(pser->fsm, "%s: %s with event = 0x%04X\n",
192 phl_fsm_obj_name(pser->fsm_obj), __func__, event);
193
194 /*
195 * Default use notify only RTW_PHL_SER_L0_CFG_NOTIFY
196 * if need do l0 debug, set RTW_PHL_SER_L0_CFG_HANDSHAKE when init.
197 * 1. after receive L0 notify within h2c, dump some Crs for debug.
198 * 2. set RTW_PHL_SER_L0_RCVY_EN
199 */
200 phl_ser_event_to_fw(pser->phl_info, event);
201 }
202
ser_send_l0_do_rcvy_event(struct ser_obj * pser)203 void ser_send_l0_do_rcvy_event(struct ser_obj *pser)
204 {
205 FSM_DBG(pser->fsm, "%s: %s\n",
206 phl_fsm_obj_name(pser->fsm_obj), __func__);
207
208 /*Default use notify only RTW_PHL_SER_L0_CFG_NOTIFY*/
209 phl_ser_event_to_fw(pser->phl_info, RTW_PHL_SER_L0_RCVY_EN);
210 }
211
212
ser_send_m2_event(struct ser_obj * pser)213 void ser_send_m2_event(struct ser_obj *pser)
214 {
215 FSM_DBG(pser->fsm, "%s: %s\n",
216 phl_fsm_obj_name(pser->fsm_obj), __func__);
217
218 phl_ser_event_to_fw(pser->phl_info, RTW_PHL_SER_L1_DISABLE_EN);
219 }
220
ser_send_m4_event(struct ser_obj * pser)221 void ser_send_m4_event(struct ser_obj *pser)
222 {
223 FSM_DBG(pser->fsm, "%s: %s\n",
224 phl_fsm_obj_name(pser->fsm_obj), __func__);
225 phl_ser_event_to_fw(pser->phl_info, RTW_PHL_SER_L1_RCVY_EN);
226 }
227
ser_usb_trx_disable_cr(struct ser_obj * pser)228 void ser_usb_trx_disable_cr(struct ser_obj *pser)
229 {
230 FSM_DBG(pser->fsm, "%s: %s\n",
231 phl_fsm_obj_name(pser->fsm_obj), __func__);
232 }
233
ser_usb_wait_all_bulk_complete(struct ser_obj * pser)234 int ser_usb_wait_all_bulk_complete(struct ser_obj *pser)
235 {
236 FSM_DBG(pser->fsm, "%s: %s\n",
237 phl_fsm_obj_name(pser->fsm_obj), __func__);
238 return 0; /* success */
239 }
240
ser_pci_clear_rw_pointer(struct ser_obj * pser)241 void ser_pci_clear_rw_pointer(struct ser_obj *pser)
242 {
243 FSM_DBG(pser->fsm, "%s: %s\n",
244 phl_fsm_obj_name(pser->fsm_obj), __func__);
245 }
246
ser_pci_assert_dessert_dma_reset(struct ser_obj * pser)247 void ser_pci_assert_dessert_dma_reset(struct ser_obj *pser)
248 {
249 FSM_DBG(pser->fsm, "%s: %s\n",
250 phl_fsm_obj_name(pser->fsm_obj), __func__);
251 }
252
ser_pci_reset_bdram(struct ser_obj * pser)253 void ser_pci_reset_bdram(struct ser_obj *pser)
254 {
255 FSM_DBG(pser->fsm, "%s: %s\n",
256 phl_fsm_obj_name(pser->fsm_obj), __func__);
257 }
258
ser_pci_enable_dma_io(struct ser_obj * pser)259 void ser_pci_enable_dma_io(struct ser_obj *pser)
260 {
261 FSM_DBG(pser->fsm, "%s: %s\n",
262 phl_fsm_obj_name(pser->fsm_obj), __func__);
263 }
264
ser_usb_enable_bulk_IO(struct ser_obj * pser)265 void ser_usb_enable_bulk_IO(struct ser_obj *pser)
266 {
267 FSM_DBG(pser->fsm, "%s: %s\n",
268 phl_fsm_obj_name(pser->fsm_obj), __func__);
269 }
ser_resume_trx_process(struct ser_obj * pser,u8 type)270 void ser_resume_trx_process(struct ser_obj *pser, u8 type)
271 {
272 struct phl_hci_trx_ops *ops = pser->phl_info->hci_trx_ops;
273
274 FSM_DBG(pser->fsm, "%s: %s\n",
275 phl_fsm_obj_name(pser->fsm_obj), __func__);
276
277 ops->trx_resume(pser->phl_info, type);
278 }
279
280 #ifdef RTW_WKARD_SER_USB_POLLING_EVENT
281 extern bool rtw_phl_recognize_interrupt(void *phl);
282 extern enum rtw_phl_status rtw_phl_interrupt_handler(void *phl);
ser_usb_chk_int_event(struct ser_obj * pser)283 static void ser_usb_chk_int_event(struct ser_obj *pser)
284 {
285 if (true == rtw_phl_recognize_interrupt(pser->phl_info))
286 rtw_phl_interrupt_handler(pser->phl_info);
287 }
288 #endif
289
290 /*
291 * SER state handler
292 */
rtw_phl_ser_inprogress(void * phl)293 u8 rtw_phl_ser_inprogress(void *phl)
294 {
295 return phl_ser_inprogress(phl);
296 }
297
rtw_phl_ser_clear_status(void * phl,u32 serstatus)298 void rtw_phl_ser_clear_status(void *phl, u32 serstatus)
299 {
300 phl_ser_clear_status(phl, serstatus);
301 }
302
303 /*
304 * ser idle handler
305 */
ser_idle_st_hdl(void * obj,u16 event,void * param)306 static int ser_idle_st_hdl(void *obj, u16 event, void *param)
307 {
308 struct ser_obj *pser = (struct ser_obj *)obj;
309 u8 notify;
310
311 switch (event) {
312 case FSM_EV_STATE_IN:
313 break;
314
315 case SER_EV_CHK_SER_EVENT:
316 if (true == rtw_hal_recognize_halt_c2h_interrupt(pser->phl_info->hal)) {
317 _ser_event_notify(pser->phl_info, ¬ify);
318 if ((notify == RTW_PHL_SER_L0_RESET) || (notify == RTW_PHL_SER_L2_RESET))
319 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
320 }
321 else {
322 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
323 }
324
325 break;
326
327 case SER_EV_L1_START:
328 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L1_PAUSE_TRX);
329 break;
330 #if 0
331 case SER_EV_L2_START:
332 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
333 break;
334 #endif
335
336 case SER_EV_M9_L2_RESET:
337 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
338 break;
339
340 case FSM_EV_STATE_OUT:
341 break;
342
343 default:
344 break;
345 }
346 return 0;
347 }
348
ser_usb_idle_st_hdl(void * obj,u16 event,void * param)349 static int ser_usb_idle_st_hdl(void *obj, u16 event, void *param)
350 {
351 struct ser_obj *pser = (struct ser_obj *)obj;
352
353 switch (event) {
354 case FSM_EV_SWITCH_IN:
355 #if 1
356 /* Disable L0 Reset Notify from FW to driver */
357 ser_send_l0_handle_method_event(pser, RTW_PHL_SER_L0_CFG_DIS_NOTIFY);
358 #endif
359 /* fallthrough */
360 case FSM_EV_STATE_IN:
361
362 #if defined(RTW_WKARD_SER_USB_POLLING_EVENT) && !defined(CONFIG_PHL_CMD_SER)
363 phl_fsm_set_alarm_ext(pser->fsm_obj,
364 SER_USB_POLLING_INTERVAL_IDL, SER_EV_POLL_USB_INT_EXPIRE, 1, NULL);
365 #endif
366
367 break;
368
369 #ifdef RTW_WKARD_SER_USB_POLLING_EVENT
370 case SER_EV_POLL_USB_INT_EXPIRE:
371 ser_usb_chk_int_event(pser);
372
373 phl_fsm_set_alarm_ext(pser->fsm_obj,
374 SER_USB_POLLING_INTERVAL_IDL, SER_EV_POLL_USB_INT_EXPIRE, 1, NULL);
375 break;
376 #endif
377
378 case SER_EV_L1_START:
379 #ifndef RTW_WKARD_SER_USB_DISABLE_L1_RCVY_FLOW
380 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L1_PAUSE_TRX);
381 #endif
382 break;
383
384 #if 0
385 case SER_EV_L2_START:
386 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
387 break;
388 #endif
389
390 case SER_EV_M9_L2_RESET:
391 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
392 break;
393
394 case FSM_EV_STATE_OUT:
395 phl_fsm_cancel_alarm_ext(pser->fsm_obj, 1);
396 break;
397
398 default:
399 break;
400 }
401 return 0;
402 }
403
ser_pci_l1_pause_trx_st_hdl(void * obj,u16 event,void * param)404 static int ser_pci_l1_pause_trx_st_hdl(void *obj, u16 event, void *param)
405 {
406 struct ser_obj *pser = (struct ser_obj *)obj;
407 struct phl_hci_trx_ops *ops = pser->phl_info->hci_trx_ops;
408 struct phl_msg msg = {0};
409 enum rtw_hal_status status = RTW_HAL_STATUS_FAILURE;
410
411 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_MDL_SER);
412 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SER_L1);
413
414 switch (event) {
415 case FSM_EV_STATE_IN:
416
417 phl_ser_set_status(pser, SER_L1);
418
419 //send msg to core
420 phl_msg_hub_send(pser->phl_info, NULL, &msg);
421
422 ops->req_tx_stop(pser->phl_info);
423 rtw_phl_tx_req_notify(pser->phl_info);
424
425 if(rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_RCVY_STEP_1)
426 != RTW_HAL_STATUS_SUCCESS){
427 ser_resume_trx_process(pser, PHL_CTRL_TX);
428 rtw_phl_tx_req_notify(pser->phl_info);
429 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
430 break;
431 }
432
433 ops->req_rx_stop(pser->phl_info);
434 rtw_phl_start_rx_process(pser->phl_info);
435
436 if (false == ops->is_tx_pause(pser->phl_info) ||
437 false == ops->is_rx_pause(pser->phl_info)) {
438 /* pci: polling fail; wait for a while */
439 phl_fsm_set_alarm(pser->fsm_obj,
440 SER_POLLING_INTERVAL, SER_EV_POLL_IO_EXPIRE);
441
442 /* prevent infinite polling */
443 pser->poll_io_times = SER_POLL_IO_TIMES;
444 break;
445 }
446
447 ops->trx_reset(pser->phl_info, PHL_CTRL_TX|PHL_CTRL_RX);
448
449 /* pci: send M2 event */
450 ser_send_m2_event(pser);
451
452 /* pci: wait M3 */
453 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
454 SER_EV_FW_TIMER_EXPIRE);
455 break;
456
457 case SER_EV_M3_DO_RECOVERY:
458 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L1_DO_HCI);
459 break;
460
461 case SER_EV_FW_TIMER_EXPIRE:
462 /*phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);*/
463 status = rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_SER_RCVY_STEP_2);
464
465 ser_resume_trx_process(pser, PHL_CTRL_RX);
466 rtw_phl_start_rx_process(pser->phl_info);
467 ser_resume_trx_process(pser, PHL_CTRL_TX);
468 rtw_phl_tx_req_notify(pser->phl_info);
469
470 if (status != RTW_HAL_STATUS_SUCCESS) {
471 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
472 } else {
473 phl_ser_clear_status(pser, SER_L1);
474 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
475 }
476
477 break;
478
479 case SER_EV_M9_L2_RESET:
480
481 ser_resume_trx_process(pser, PHL_CTRL_RX);
482 rtw_phl_start_rx_process(pser->phl_info);
483 ser_resume_trx_process(pser, PHL_CTRL_TX);
484 rtw_phl_tx_req_notify(pser->phl_info);
485
486 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
487
488 break;
489
490 case SER_EV_POLL_IO_EXPIRE:
491
492 if (pser->poll_io_times-- <= 0) {
493 #ifdef RTW_WKARD_SER_L1_EXPIRE
494
495 ops->trx_reset(pser->phl_info, PHL_CTRL_TX|PHL_CTRL_RX);
496
497 /* pci: send M2 event */
498 ser_send_m2_event(pser);
499
500 /* pci: wait M3 */
501 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
502 SER_EV_FW_TIMER_EXPIRE);
503
504 #else
505 ser_resume_trx_process(pser, PHL_CTRL_RX);
506 rtw_phl_start_rx_process(pser->phl_info);
507 ser_resume_trx_process(pser, PHL_CTRL_TX);
508 rtw_phl_tx_req_notify(pser->phl_info);
509 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
510 #endif
511 break;
512 }
513
514 /*send msg to core*/
515 /*phl_msg_hub_send(pser->phl_info, &msg);*/
516
517 if (false == ops->is_tx_pause(pser->phl_info) ||
518 false == ops->is_rx_pause(pser->phl_info) ) {
519 /* pci: polling fail; wait for a while */
520 phl_fsm_set_alarm(pser->fsm_obj,
521 SER_POLLING_INTERVAL, SER_EV_POLL_IO_EXPIRE);
522 break;
523 }
524 /*
525 if(rtw_hal_lv1_rcvy(hal_info, RTW_PHL_SER_LV1_RCVY_STEP_1) != RTW_HAL_STATUS_SUCCESS){
526 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
527 break;
528 }
529 */
530 ops->trx_reset(pser->phl_info, PHL_CTRL_TX|PHL_CTRL_RX);
531
532 /* pci: send M2 event */
533 ser_send_m2_event(pser);
534
535 /* pci: wait M3 */
536 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
537 SER_EV_FW_TIMER_EXPIRE);
538 break;
539
540 case FSM_EV_CANCEL:
541 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
542 break;
543
544 case FSM_EV_STATE_OUT:
545 phl_fsm_cancel_alarm(pser->fsm_obj);
546 break;
547
548 default:
549 break;
550 }
551 return 0;
552 }
553
ser_usb_l1_pause_trx_done(struct ser_obj * pser)554 static void ser_usb_l1_pause_trx_done(struct ser_obj *pser)
555 {
556 rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_RCVY_STEP_1);
557
558 ser_send_m2_event(pser);
559 }
560
ser_usb_l1_pause_trx_st_hdl(void * obj,u16 event,void * param)561 static int ser_usb_l1_pause_trx_st_hdl(void *obj, u16 event, void *param)
562 {
563 struct ser_obj *pser = (struct ser_obj *)obj;
564 struct phl_hci_trx_ops *ops = pser->phl_info->hci_trx_ops;
565 struct phl_msg msg = {0};
566 enum rtw_hal_status status = RTW_HAL_STATUS_FAILURE;
567
568 switch (event) {
569 case FSM_EV_STATE_IN:
570 phl_ser_set_status(pser, SER_L1);
571
572 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_MDL_SER);
573 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SER_L1);
574 phl_msg_hub_send(pser->phl_info, NULL, &msg);
575
576 ops->req_tx_stop(pser->phl_info);
577 rtw_phl_tx_req_notify(pser->phl_info);
578
579 #if 0
580 /* not request pause PHL Rx in USB data path */
581 ops->req_rx_stop(pser->phl_info);
582 rtw_phl_start_rx_process(pser->phl_info);
583 #endif
584
585 if (false == ops->is_tx_pause(pser->phl_info)
586 #if 0
587 || false == ops->is_rx_pause(pser->phl_info)
588 #endif
589 ) {
590 phl_fsm_set_alarm(pser->fsm_obj,
591 SER_USB_POLLING_INTERVAL_ACT, SER_EV_POLL_IO_EXPIRE);
592
593 pser->poll_io_times = SER_USB_POLL_IO_TIMES;
594 break;
595 }
596
597 ser_usb_l1_pause_trx_done(pser);
598
599 #ifdef RTW_WKARD_SER_USB_POLLING_EVENT
600 phl_fsm_set_alarm_ext(pser->fsm_obj,
601 SER_USB_POLLING_INTERVAL_ACT, SER_EV_POLL_USB_INT_EXPIRE, 1, NULL);
602 #endif
603
604 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
605 SER_EV_FW_TIMER_EXPIRE);
606
607 break;
608
609 #ifdef RTW_WKARD_SER_USB_POLLING_EVENT
610 case SER_EV_POLL_USB_INT_EXPIRE:
611 ser_usb_chk_int_event(pser);
612
613 phl_fsm_set_alarm_ext(pser->fsm_obj,
614 SER_USB_POLLING_INTERVAL_ACT, SER_EV_POLL_USB_INT_EXPIRE, 1, NULL);
615 break;
616 #endif
617
618 case SER_EV_M3_DO_RECOVERY:
619 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L1_DO_HCI);
620 break;
621
622 case SER_EV_FW_TIMER_EXPIRE:
623 status = rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_SER_RCVY_STEP_2);
624 ser_resume_trx_process(pser, PHL_CTRL_TX);
625 rtw_phl_tx_req_notify(pser->phl_info);
626
627 if (status != RTW_HAL_STATUS_SUCCESS)
628 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
629 else
630 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
631
632 break;
633
634 case SER_EV_M9_L2_RESET:
635 ser_resume_trx_process(pser, PHL_CTRL_TX);
636 rtw_phl_tx_req_notify(pser->phl_info);
637 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
638 break;
639
640 case SER_EV_POLL_IO_EXPIRE:
641
642 if (pser->poll_io_times-- <= 0) {
643 #ifdef RTW_WKARD_SER_L1_EXPIRE
644 ser_usb_l1_pause_trx_done(pser);
645
646 phl_fsm_set_alarm_ext(pser->fsm_obj,
647 SER_USB_POLLING_INTERVAL_ACT, SER_EV_POLL_USB_INT_EXPIRE, 1, NULL);
648
649 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
650 SER_EV_FW_TIMER_EXPIRE);
651 #else
652 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
653 #endif
654 break;
655 }
656
657 if (false == ops->is_tx_pause(pser->phl_info)
658 #if 0
659 || false == ops->is_rx_pause(pser->phl_info)
660 #endif
661 ) {
662 phl_fsm_set_alarm(pser->fsm_obj,
663 SER_USB_POLLING_INTERVAL_ACT, SER_EV_POLL_IO_EXPIRE);
664 break;
665 }
666
667 ser_usb_l1_pause_trx_done(pser);
668
669 phl_fsm_set_alarm_ext(pser->fsm_obj,
670 SER_USB_POLLING_INTERVAL_ACT, SER_EV_POLL_USB_INT_EXPIRE, 1, NULL);
671
672 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
673 SER_EV_FW_TIMER_EXPIRE);
674
675 break;
676
677 case FSM_EV_CANCEL:
678 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
679 break;
680
681 case FSM_EV_STATE_OUT:
682 phl_fsm_cancel_alarm(pser->fsm_obj);
683 phl_fsm_cancel_alarm_ext(pser->fsm_obj, 1);
684 break;
685
686 default:
687 break;
688 }
689 return 0;
690 }
691
ser_sdio_l1_pause_trx_st_hdl(void * obj,u16 event,void * param)692 static int ser_sdio_l1_pause_trx_st_hdl(void *obj, u16 event, void *param)
693 {
694 struct ser_obj *pser = (struct ser_obj *)obj;
695 struct phl_hci_trx_ops *ops = pser->phl_info->hci_trx_ops;
696 struct phl_msg msg = {0};
697 enum rtw_hal_status status = RTW_HAL_STATUS_FAILURE;
698
699 switch (event) {
700 case FSM_EV_STATE_IN:
701 phl_ser_set_status(pser, BIT1);
702
703 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_MDL_SER);
704 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SER_L1);
705 phl_msg_hub_send(pser->phl_info, NULL, &msg);
706
707 ops->req_tx_stop(pser->phl_info);
708 rtw_phl_tx_req_notify(pser->phl_info);
709
710 ops->req_rx_stop(pser->phl_info);
711 rtw_phl_start_rx_process(pser->phl_info);
712
713 if (false == ops->is_tx_pause(pser->phl_info)
714 || false == ops->is_rx_pause(pser->phl_info)) {
715 phl_fsm_set_alarm(pser->fsm_obj,
716 SER_POLLING_INTERVAL, SER_EV_POLL_IO_EXPIRE);
717
718 pser->poll_io_times = SER_POLL_IO_TIMES;
719 break;
720 }
721
722 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_DIS_HCI_INT);
723
724 if (rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_RCVY_STEP_1)
725 != RTW_HAL_STATUS_SUCCESS) {
726 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
727 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
728 break;
729 }
730
731 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_SER_HANDSHAKE_MODE);
732
733 ser_send_m2_event(pser);
734
735 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
736 SER_EV_FW_TIMER_EXPIRE);
737
738 break;
739
740 case SER_EV_CHK_SER_EVENT:
741 if (true == rtw_hal_recognize_halt_c2h_interrupt(pser->phl_info->hal))
742 _ser_event_notify(pser->phl_info, NULL);
743
744 break;
745
746 case SER_EV_M3_DO_RECOVERY:
747 rtw_hal_clear_interrupt(pser->phl_info->hal);
748 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L1_DO_HCI);
749 break;
750
751 case SER_EV_FW_TIMER_EXPIRE:
752 status = rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_SER_RCVY_STEP_2);
753
754 ser_resume_trx_process(pser, PHL_CTRL_RX);
755 rtw_phl_start_rx_process(pser->phl_info);
756 ser_resume_trx_process(pser, PHL_CTRL_TX);
757 rtw_phl_tx_req_notify(pser->phl_info);
758
759 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
760
761 if (status != RTW_HAL_STATUS_SUCCESS) {
762 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
763 } else {
764 phl_ser_clear_status(pser, BIT1);
765 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
766 }
767
768 break;
769
770 case SER_EV_M9_L2_RESET:
771 ser_resume_trx_process(pser, PHL_CTRL_RX);
772 rtw_phl_start_rx_process(pser->phl_info);
773 ser_resume_trx_process(pser, PHL_CTRL_TX);
774 rtw_phl_tx_req_notify(pser->phl_info);
775
776 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
777
778 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
779 break;
780
781 case SER_EV_POLL_IO_EXPIRE:
782
783 if (pser->poll_io_times-- <= 0) {
784 #ifdef RTW_WKARD_SER_L1_EXPIRE
785
786 if (rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_RCVY_STEP_1)
787 != RTW_HAL_STATUS_SUCCESS) {
788 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
789 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
790 break;
791 }
792
793 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_SER_HANDSHAKE_MODE);
794
795 ser_send_m2_event(pser);
796
797 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
798 SER_EV_FW_TIMER_EXPIRE);
799
800 #else
801 ser_resume_trx_process(pser, PHL_CTRL_RX);
802 rtw_phl_start_rx_process(pser->phl_info);
803 ser_resume_trx_process(pser, PHL_CTRL_TX);
804 rtw_phl_tx_req_notify(pser->phl_info);
805
806 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
807
808 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
809 #endif
810 break;
811 }
812
813 if (false == ops->is_tx_pause(pser->phl_info) ||
814 false == ops->is_rx_pause(pser->phl_info)) {
815 phl_fsm_set_alarm(pser->fsm_obj,
816 SER_POLLING_INTERVAL, SER_EV_POLL_IO_EXPIRE);
817 break;
818 }
819
820 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_DIS_HCI_INT);
821
822 if (rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_RCVY_STEP_1)
823 != RTW_HAL_STATUS_SUCCESS) {
824 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
825 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
826 break;
827 }
828
829 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_SER_HANDSHAKE_MODE);
830
831 ser_send_m2_event(pser);
832
833 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
834 SER_EV_FW_TIMER_EXPIRE);
835 break;
836
837 case FSM_EV_CANCEL:
838 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
839 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
840 break;
841
842 case FSM_EV_STATE_OUT:
843 phl_fsm_cancel_alarm(pser->fsm_obj);
844 break;
845
846 default:
847 break;
848 }
849 return 0;
850 }
851
ser_pci_l1_do_hci_st_hdl(void * obj,u16 event,void * param)852 static int ser_pci_l1_do_hci_st_hdl(void *obj, u16 event, void *param)
853 {
854 struct ser_obj *pser = (struct ser_obj *)obj;
855
856 switch (event) {
857 case FSM_EV_STATE_IN:
858
859 if(rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_SER_RCVY_STEP_2)
860 != RTW_HAL_STATUS_SUCCESS){
861 ser_resume_trx_process(pser, PHL_CTRL_RX);
862 rtw_phl_start_rx_process(pser->phl_info);
863 ser_resume_trx_process(pser, PHL_CTRL_TX);
864 rtw_phl_tx_req_notify(pser->phl_info);
865 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
866 break;
867 }
868 ser_resume_trx_process(pser, PHL_CTRL_RX);
869 rtw_phl_start_rx_process(pser->phl_info);
870
871 /* pci: send M4 event */
872 ser_send_m4_event(pser);
873
874 /* pci: set timeout to wait M5 */
875 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
876 SER_EV_FW_TIMER_EXPIRE);
877 break;
878
879 case SER_EV_M5_READY:
880 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L1_RESUME_TRX);
881 break;
882
883
884 case SER_EV_FW_TIMER_EXPIRE:
885 /* PHL_INFO("ser_pci_l1_do_hci_st_hdl(): SER_EV_FW_TIMER_EXPIRE \n"); */
886 /* _ser_event_notify(pser->phl_info, NULL); */
887 /* phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2); */
888 ser_resume_trx_process(pser, PHL_CTRL_TX);
889 rtw_phl_tx_req_notify(pser->phl_info);
890 phl_ser_clear_status(pser, SER_L1);
891 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
892 break;
893
894 case SER_EV_M9_L2_RESET:
895
896 ser_resume_trx_process(pser, PHL_CTRL_TX);
897 rtw_phl_tx_req_notify(pser->phl_info);
898 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
899
900 break;
901
902 case FSM_EV_CANCEL:
903 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
904 break;
905
906 case FSM_EV_STATE_OUT:
907 phl_fsm_cancel_alarm(pser->fsm_obj);
908 break;
909
910 default:
911 break;
912 }
913 return 0;
914 }
915
ser_usb_l1_do_hci_st_hdl(void * obj,u16 event,void * param)916 static int ser_usb_l1_do_hci_st_hdl(void *obj, u16 event, void *param)
917 {
918 struct ser_obj *pser = (struct ser_obj *)obj;
919
920 switch (event) {
921 case FSM_EV_STATE_IN:
922 if (rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_SER_RCVY_STEP_2)
923 != RTW_HAL_STATUS_SUCCESS) {
924 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
925 break;
926 }
927 ser_resume_trx_process(pser, PHL_CTRL_RX);
928 rtw_phl_start_rx_process(pser->phl_info);
929
930 ser_send_m4_event(pser);
931
932 #ifdef RTW_WKARD_SER_USB_POLLING_EVENT
933 phl_fsm_set_alarm_ext(pser->fsm_obj,
934 SER_USB_POLLING_INTERVAL_ACT, SER_EV_POLL_USB_INT_EXPIRE, 1, NULL);
935 #endif
936
937 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
938 SER_EV_FW_TIMER_EXPIRE);
939 break;
940
941 #ifdef RTW_WKARD_SER_USB_POLLING_EVENT
942 case SER_EV_POLL_USB_INT_EXPIRE:
943 ser_usb_chk_int_event(pser);
944
945 phl_fsm_set_alarm_ext(pser->fsm_obj,
946 SER_USB_POLLING_INTERVAL_ACT, SER_EV_POLL_USB_INT_EXPIRE, 1, NULL);
947 break;
948 #endif
949
950 case SER_EV_M5_READY:
951 case SER_EV_FW_TIMER_EXPIRE:
952 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L1_RESUME_TRX);
953 break;
954
955 case SER_EV_M9_L2_RESET:
956 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
957 break;
958
959 case FSM_EV_CANCEL:
960 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
961 break;
962
963 case FSM_EV_STATE_OUT:
964 phl_fsm_cancel_alarm(pser->fsm_obj);
965 phl_fsm_cancel_alarm_ext(pser->fsm_obj, 1);
966 break;
967
968 default:
969 break;
970 }
971 return 0;
972 }
973
ser_sdio_l1_do_hci_st_hdl(void * obj,u16 event,void * param)974 static int ser_sdio_l1_do_hci_st_hdl(void *obj, u16 event, void *param)
975 {
976 struct ser_obj *pser = (struct ser_obj *)obj;
977
978 switch (event) {
979 case FSM_EV_STATE_IN:
980
981 if (rtw_hal_lv1_rcvy(pser->phl_info->hal, RTW_PHL_SER_LV1_SER_RCVY_STEP_2)
982 != RTW_HAL_STATUS_SUCCESS) {
983 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
984 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
985 break;
986 }
987 ser_resume_trx_process(pser, PHL_CTRL_RX);
988 rtw_phl_start_rx_process(pser->phl_info);
989
990 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_SER_HANDSHAKE_MODE);
991
992 ser_send_m4_event(pser);
993
994 phl_fsm_set_alarm(pser->fsm_obj, SER_FW_TIMEOUT,
995 SER_EV_FW_TIMER_EXPIRE);
996 break;
997
998 case SER_EV_CHK_SER_EVENT:
999 if (true == rtw_hal_recognize_halt_c2h_interrupt(pser->phl_info->hal))
1000 _ser_event_notify(pser->phl_info, NULL);
1001
1002 break;
1003
1004 case SER_EV_M5_READY:
1005 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
1006 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L1_RESUME_TRX);
1007 break;
1008
1009 case SER_EV_FW_TIMER_EXPIRE:
1010 ser_resume_trx_process(pser, PHL_CTRL_TX);
1011 rtw_phl_tx_req_notify(pser->phl_info);
1012 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
1013 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
1014 break;
1015
1016 case SER_EV_M9_L2_RESET:
1017 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
1018 phl_fsm_state_goto(pser->fsm_obj, SER_ST_L2);
1019 break;
1020
1021 case FSM_EV_CANCEL:
1022 rtw_hal_config_interrupt(pser->phl_info->hal, RTW_PHL_EN_HCI_INT);
1023 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
1024 break;
1025
1026 case FSM_EV_STATE_OUT:
1027 phl_fsm_cancel_alarm(pser->fsm_obj);
1028 break;
1029
1030 default:
1031 break;
1032 }
1033 return 0;
1034 }
1035
ser_l1_resume_trx_st_hdl(void * obj,u16 event,void * param)1036 static int ser_l1_resume_trx_st_hdl(void *obj, u16 event, void *param)
1037 {
1038 struct ser_obj *pser = (struct ser_obj *)obj;
1039
1040
1041 switch (event) {
1042 case FSM_EV_STATE_IN:
1043
1044 /* TODO resume TRX process */
1045 ser_resume_trx_process(pser, PHL_CTRL_TX);
1046 rtw_phl_tx_req_notify(pser->phl_info);
1047 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
1048 break;
1049
1050 case FSM_EV_CANCEL:
1051 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
1052 break;
1053
1054 case FSM_EV_STATE_OUT:
1055 phl_fsm_cancel_alarm(pser->fsm_obj);
1056 phl_ser_clear_status(pser, SER_L1);
1057 break;
1058
1059 default:
1060 break;
1061 }
1062 return 0;
1063 }
1064
ser_l2_st_hdl(void * obj,u16 event,void * param)1065 static int ser_l2_st_hdl(void *obj, u16 event, void *param)
1066 {
1067 struct ser_obj *pser = (struct ser_obj *)obj;
1068 struct phl_msg msg = {0};
1069
1070 switch (event) {
1071 case FSM_EV_STATE_IN:
1072
1073 /*To avoid fw watchdog intr trigger periodically*/
1074 rtw_hal_ser_reset_wdt_intr(pser->phl_info->hal);
1075
1076 /* TODO do something */
1077 phl_ser_clear_status(pser, SER_L1);
1078 phl_ser_set_status(pser, SER_L2);
1079
1080 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_MDL_SER);
1081 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SER_L2);
1082 phl_msg_hub_send(pser->phl_info, NULL, &msg);
1083
1084 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
1085 break;
1086
1087 case FSM_EV_TIMER_EXPIRE:
1088 break;
1089
1090 case FSM_EV_CANCEL:
1091 phl_fsm_state_goto(pser->fsm_obj, SER_ST_IDLE);
1092 break;
1093
1094 case FSM_EV_STATE_OUT:
1095 phl_fsm_cancel_alarm(pser->fsm_obj);
1096 break;
1097
1098 default:
1099 break;
1100 }
1101 return 0;
1102 }
1103
ser_dump_obj(void * obj,char * s,int * sz)1104 static void ser_dump_obj(void *obj, char *s, int *sz)
1105 {
1106 /* nothing to do for now */
1107 }
1108
ser_dump_fsm(void * fsm,char * s,int * sz)1109 static void ser_dump_fsm(void *fsm, char *s, int *sz)
1110 {
1111 /* nothing to do for now */
1112 }
1113
1114 /* For EXTERNAL application to create a ser FSM */
1115 /* @root: FSM root structure
1116 * @phl_info: private data structure to invoke hal/phl function
1117 *
1118 * return
1119 * fsm_main: FSM main structure (Do NOT expose)
1120 */
phl_ser_new_fsm(struct fsm_root * root,struct phl_info_t * phl_info)1121 struct fsm_main *phl_ser_new_fsm(struct fsm_root *root,
1122 struct phl_info_t *phl_info)
1123 {
1124 void *d = phl_to_drvpriv(phl_info);
1125 struct fsm_main *fsm = NULL;
1126 struct rtw_phl_fsm_tb tb;
1127
1128 _os_mem_set(d, &tb, 0, sizeof(tb));
1129
1130 if (phl_info->phl_com->hci_type == RTW_HCI_PCIE)
1131 tb.state_tbl = ser_pci_state_tbl;
1132 else if (phl_info->phl_com->hci_type == RTW_HCI_USB)
1133 tb.state_tbl = ser_usb_state_tbl;
1134 else if (phl_info->phl_com->hci_type == RTW_HCI_SDIO)
1135 tb.state_tbl = ser_sdio_state_tbl;
1136 else
1137 return NULL;
1138
1139 tb.max_state = sizeof(ser_pci_state_tbl)/sizeof(ser_pci_state_tbl[0]);
1140 tb.max_event = sizeof(ser_event_tbl)/sizeof(ser_event_tbl[0]);
1141 tb.evt_tbl = ser_event_tbl;
1142 tb.dump_obj = ser_dump_obj;
1143 tb.dump_obj = ser_dump_fsm;
1144 tb.dbg_level = FSM_DBG_INFO;
1145 tb.evt_level = FSM_DBG_INFO;
1146
1147 fsm = phl_fsm_init_fsm(root, "ser", phl_info, &tb);
1148
1149 return fsm;
1150 }
1151
1152 /* For EXTERNAL application to destory ser fsm */
1153 /* @fsm: see fsm_main
1154 */
phl_ser_destory_fsm(struct fsm_main * fsm)1155 void phl_ser_destory_fsm(struct fsm_main *fsm)
1156 {
1157 if (fsm == NULL)
1158 return;
1159
1160 /* deinit fsm local variable if has */
1161
1162 /* call FSM Framewro to deinit fsm */
1163 phl_fsm_deinit_fsm(fsm);
1164 }
1165
1166 /* For EXTERNAL application to create SER object */
1167 /* @fsm: FSM main structure which created by phl_ser_new_fsm()
1168 * @phl_info: private data structure to invoke hal/phl function
1169 *
1170 * return
1171 * ser_obj: structure of SER object (Do NOT expose)
1172 */
phl_ser_new_obj(struct fsm_main * fsm,struct phl_info_t * phl_info)1173 struct ser_obj *phl_ser_new_obj(struct fsm_main *fsm,
1174 struct phl_info_t *phl_info)
1175 {
1176 void *d = phl_to_drvpriv(phl_info);
1177 struct fsm_obj *obj;
1178 struct ser_obj *pser;
1179
1180
1181 pser = phl_fsm_new_obj(fsm, (void **)&obj, sizeof(*pser));
1182
1183 if (pser == NULL) {
1184 /* TODO free fsm; currently will be freed in deinit process */
1185 FSM_ERR(fsm, "ser: malloc obj fail\n");
1186 return NULL;
1187 }
1188 pser->fsm = fsm;
1189 pser->fsm_obj = obj;
1190 pser->phl_info = phl_info;
1191
1192 /* init local use variable */
1193 _os_spinlock_init(d, &pser->state_lock);
1194
1195 return pser;
1196 }
1197
1198 /* For EXTERNAL application to destory ser object */
1199 /* @pser: local created command object
1200 *
1201 */
phl_ser_destory_obj(struct ser_obj * pser)1202 void phl_ser_destory_obj(struct ser_obj *pser)
1203 {
1204 void *d;
1205
1206 if (pser == NULL)
1207 return;
1208
1209 d = phl_to_drvpriv(pser->phl_info);
1210
1211 /* deinit obj local variable if has */
1212 _os_spinlock_free(d, &pser->state_lock);
1213
1214 /* inform FSM framewory to recycle fsm_obj */
1215 phl_fsm_destory_obj(pser->fsm_obj);
1216 }
1217
1218 /* For EXTERNAL application to stop ser service (expose) */
1219 /* @pser: ser job will be cancelled
1220 */
phl_ser_cancel(void * phl)1221 enum rtw_phl_status phl_ser_cancel(void *phl)
1222 {
1223 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1224 struct ser_obj *pser = phl_info->ser_obj;
1225
1226 return phl_fsm_gen_msg(phl, pser->fsm_obj, NULL, 0, FSM_EV_CANCEL);
1227 }
1228
1229 /* For EXTERNAL interrupt handler to send event into ser fsm (expose) */
phl_ser_event_to_fw(void * phl,u32 err)1230 enum rtw_phl_status phl_ser_event_to_fw(void *phl, u32 err)
1231 {
1232 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1233 enum rtw_hal_status status;
1234
1235 status = rtw_hal_ser_set_error_status(phl_info->hal ,err);
1236 PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "phl_ser_event_to_fw err %d, status 0x%x\n", err, status);
1237 return status;
1238 }
1239
1240 /* For EXTERNAL interrupt handler and dump fw ple (expose) */
rtw_phl_ser_dump_ple_buffer(void * phl)1241 enum rtw_phl_status rtw_phl_ser_dump_ple_buffer(void *phl)
1242 {
1243 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1244
1245 PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "rtw_phl_ser_dump_ple_buffer\n");
1246
1247 rtw_hal_dump_fw_rsvd_ple(phl_info->hal);
1248
1249 return RTW_PHL_STATUS_SUCCESS;
1250 }
1251
1252 /* For EXTERNAL interrupt handler and dump fw ple (expose) */
phl_fw_watchdog_timeout_notify(void * phl)1253 enum rtw_phl_status phl_fw_watchdog_timeout_notify(void *phl)
1254 {
1255 enum RTW_PHL_SER_NOTIFY_EVENT notify = RTW_PHL_SER_L2_RESET;
1256 PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "phl_fw_watchdog_timeout_notify triggle L2 Reset !!!\n");
1257
1258 return phl_ser_send_msg(phl, notify);
1259 }
1260
rtw_phl_ser_l2_notify(struct rtw_phl_com_t * phl_com)1261 enum rtw_phl_status rtw_phl_ser_l2_notify(struct rtw_phl_com_t *phl_com)
1262 {
1263 enum RTW_PHL_SER_NOTIFY_EVENT notify = RTW_PHL_SER_L2_RESET;
1264 PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "rtw_phl_ser_l2_notify triggle L2 Reset !!!\n");
1265
1266 return phl_ser_send_msg(phl_com->phl_priv, notify);
1267 }
1268
1269 /* @phl: phl_info_t
1270 * @notify: event to ser fsm
1271 */
1272
1273 #ifndef CONFIG_PHL_CMD_SER
phl_ser_send_msg(void * phl,enum RTW_PHL_SER_NOTIFY_EVENT notify)1274 enum rtw_phl_status phl_ser_send_msg(void *phl,
1275 enum RTW_PHL_SER_NOTIFY_EVENT notify)
1276 {
1277 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1278 struct ser_obj *pser = phl_info->ser_obj;
1279 u16 event;
1280
1281 switch (notify) {
1282 case RTW_PHL_SER_PAUSE_TRX: /* M1 */
1283 event = SER_EV_L1_START;
1284 break;
1285 case RTW_PHL_SER_DO_RECOVERY: /* M3 */
1286 event = SER_EV_M3_DO_RECOVERY;
1287 break;
1288 case RTW_PHL_SER_READY: /* M5 */
1289 event = SER_EV_M5_READY;
1290 break;
1291 case RTW_PHL_SER_L2_RESET: /* M9 */
1292 event = SER_EV_M9_L2_RESET;
1293 break;
1294 case RTW_PHL_SER_EVENT_CHK:
1295 event = SER_EV_CHK_SER_EVENT;
1296 break;
1297 case RTW_PHL_SER_L0_RESET:
1298 PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "phl_ser_send_msg(): Unsupported case:%d, please check it\n",
1299 notify);
1300 return RTW_PHL_STATUS_FAILURE;
1301 default:
1302 PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "phl_ser_send_msg(): Unrecognize case:%d, please check it\n",
1303 notify);
1304 return RTW_PHL_STATUS_FAILURE;
1305 }
1306 PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "phl_ser_send_msg event %d\n", event);
1307
1308 return phl_fsm_gen_msg(phl, pser->fsm_obj, NULL, 0, event);
1309 }
1310
1311
1312 /* For EXTERNAL application to do L2 reset (expose) */
1313 /* @pser: ser job will be cancelled
1314 */
phl_ser_inprogress(void * phl)1315 u8 phl_ser_inprogress(void *phl)
1316 {
1317 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1318 struct ser_obj *pser = phl_info->ser_obj;
1319 u8 reset_type = 0;
1320 void *d = phl_to_drvpriv(phl_info);
1321
1322 _os_spinlock(d, &pser->state_lock, _bh, NULL);
1323
1324 if(pser->trigger_l1_reset == true) {
1325 reset_type |= SER_L1;
1326 //pser->trigger_l2_reset = false;
1327 }
1328 if(pser->trigger_l2_reset == true) {
1329 reset_type |= SER_L2;
1330 }
1331
1332 _os_spinunlock(d, &pser->state_lock, _bh, NULL);
1333 return reset_type;
1334 }
1335 #endif
1336
1337 /* For EXTERNAL application to do L2 reset (expose) */
1338 /* @pser: ser job will be cancelled
1339 */
phl_ser_clear_status(struct ser_obj * pser,u32 serstatus)1340 void phl_ser_clear_status(struct ser_obj *pser, u32 serstatus)
1341 {
1342 void *d = phl_to_drvpriv(pser->phl_info);
1343
1344 _os_spinlock(d, &pser->state_lock, _bh, NULL);
1345
1346 if(serstatus & SER_L1) {
1347 pser->trigger_l1_reset = false;
1348 }
1349 if(serstatus & SER_L2) {
1350 pser->trigger_l2_reset = false;
1351 }
1352
1353 _os_spinunlock(d, &pser->state_lock, _bh, NULL);
1354 }
1355
phl_ser_set_status(struct ser_obj * pser,u32 serstatus)1356 void phl_ser_set_status(struct ser_obj *pser, u32 serstatus)
1357 {
1358 void *d = phl_to_drvpriv(pser->phl_info);
1359
1360 _os_spinlock(d, &pser->state_lock, _bh, NULL);
1361
1362 if(serstatus & SER_L1) {
1363 pser->trigger_l1_reset = true;
1364 }
1365 if(serstatus & SER_L2) {
1366 pser->trigger_l2_reset = true;
1367 }
1368
1369 _os_spinunlock(d, &pser->state_lock, _bh, NULL);
1370 }
1371
1372
1373 /* For EXTERNAL application notify from upper layer*/
phl_ser_notify_from_upper_watchdog_status(void * phl,bool inprogress)1374 void phl_ser_notify_from_upper_watchdog_status(void *phl, bool inprogress)
1375 {
1376 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1377 struct ser_obj *pser = phl_info->ser_obj;
1378
1379 pser->dynamicThredRunning = inprogress;
1380 }
1381
rtw_phl_notify_watchdog_status(void * phl,bool inprogress)1382 void rtw_phl_notify_watchdog_status(void *phl, bool inprogress)
1383 {
1384 phl_ser_notify_from_upper_watchdog_status(phl, inprogress);
1385 }
1386 #endif /*CONFIG_FSM*/
1387
1388