1 /******************************************************************************
2 *
3 * Copyright(c) 2019 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _HAL_WOW_C_
16 #include "hal_headers.h"
17
18 #ifdef CONFIG_WOWLAN
19
20 #define case_rsn(rsn) \
21 case MAC_AX_WOW_##rsn: return RTW_WOW_RSN_##rsn
22
_trans_wake_rsn(u8 mac_rsn)23 u8 _trans_wake_rsn(u8 mac_rsn)
24 {
25 switch (mac_rsn) {
26 case_rsn(RX_PAIRWISEKEY);
27 case_rsn(RX_GTK);
28 case_rsn(RX_FOURWAY_HANDSHAKE);
29 case_rsn(RX_DISASSOC);
30 case_rsn(RX_DEAUTH);
31 case_rsn(RX_ARP_REQUEST);
32 case_rsn(RX_NS);
33 case_rsn(RX_EAPREQ_IDENTIFY);
34 case_rsn(FW_DECISION_DISCONNECT);
35 case_rsn(RX_MAGIC_PKT);
36 case_rsn(RX_UNICAST_PKT);
37 case_rsn(RX_PATTERN_PKT);
38 case_rsn(RTD3_SSID_MATCH);
39 case_rsn(RX_DATA_PKT);
40 case_rsn(RX_SSDP_MATCH);
41 case_rsn(RX_WSD_MATCH);
42 case_rsn(RX_SLP_MATCH);
43 case_rsn(RX_LLTD_MATCH);
44 case_rsn(RX_MDNS_MATCH);
45 case_rsn(RX_REALWOW_V2_WAKEUP_PKT);
46 case_rsn(RX_REALWOW_V2_ACK_LOST);
47 case_rsn(RX_REALWOW_V2_TX_KAPKT);
48 case_rsn(ENABLE_FAIL_DMA_IDLE);
49 case_rsn(ENABLE_FAIL_DMA_PAUSE);
50 case_rsn(RTIME_FAIL_DMA_IDLE);
51 case_rsn(RTIME_FAIL_DMA_PAUSE);
52 case_rsn(RX_SNMP_MISMATCHED_PKT);
53 case_rsn(RX_DESIGNATED_MAC_PKT);
54 case_rsn(NLO_SSID_MACH);
55 case_rsn(AP_OFFLOAD_WAKEUP);
56 case_rsn(DMAC_ERROR_OCCURRED);
57 case_rsn(EXCEPTION_OCCURRED);
58 case_rsn(L0_TO_L1_ERROR_OCCURRED);
59 case_rsn(ASSERT_OCCURRED);
60 case_rsn(L2_ERROR_OCCURRED);
61 case_rsn(WDT_TIMEOUT_WAKE);
62 case_rsn(RX_ACTION);
63 case_rsn(CLK_32K_UNLOCK);
64 case_rsn(CLK_32K_LOCK);
65 default:
66 return RTW_WOW_RSN_MAX;
67 }
68 }
69
70 #define MAX_POLLING_WOW_FW_STS_CNT 1000 /* 50ms */
71
_hal_check_wow_fw_ready(void * hal,u8 func_en)72 static enum rtw_hal_status _hal_check_wow_fw_ready(void *hal, u8 func_en)
73 {
74 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
75 enum rtw_hal_status hstats = RTW_HAL_STATUS_FAILURE;
76 void* drv_priv = hal_to_drvpriv(hal_info);
77 u8 fw_status = 0;
78 u32 poll_cnt = 0;
79
80 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : start polling... (func_en %d)\n", __func__, func_en);
81
82 /* polling fw status */
83 while (1) {
84
85 if (poll_cnt >= MAX_POLLING_WOW_FW_STS_CNT) {
86 PHL_ERR("%s polling fw status timeout !!!\n", __func__);
87 hstats = RTW_HAL_STATUS_FAILURE;
88 break;
89 }
90
91 hstats = rtw_hal_mac_get_wow_fw_status(hal_info, &fw_status,
92 func_en);
93
94 if (RTW_HAL_STATUS_SUCCESS != hstats) {
95
96 PHL_ERR("%s : status %u\n", __func__, fw_status);
97 break;
98 }
99
100 if (fw_status) {
101 hstats = RTW_HAL_STATUS_SUCCESS;
102
103 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_,
104 "%s : polling count %u\n", __func__, poll_cnt);
105 break;
106 } else {
107
108 _os_delay_us(drv_priv, 50);
109
110 }
111 poll_cnt++;
112
113 }
114
115 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : finish polling... (func_en %d)\n", __func__, func_en);
116
117 return hstats;
118 }
119
rtw_hal_get_wake_rsn(void * hal,enum rtw_wow_wake_reason * wake_rsn,u8 * reset)120 enum rtw_hal_status rtw_hal_get_wake_rsn(void *hal, enum rtw_wow_wake_reason *wake_rsn, u8 *reset)
121 {
122 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
123 enum rtw_hal_status hstats = RTW_HAL_STATUS_FAILURE;
124 u8 mac_rsn = 0;
125
126 hstats = rtw_hal_mac_get_wake_rsn(hal_info, &mac_rsn, reset);
127 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "%s : wake rsn from mac in hex 0x%x (reset %d).\n",
128 __func__, mac_rsn, *reset);
129
130 if (RTW_HAL_STATUS_SUCCESS != hstats) {
131 PHL_ERR("%s : rtw_hal_mac_get_wake_rsn failed.\n", __func__);
132 } else {
133 *wake_rsn = (mac_rsn == 0) ? RTW_WOW_RSN_UNKNOWN : _trans_wake_rsn(mac_rsn) ;
134 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "%s : wake reason %u.\n", __func__, *wake_rsn);
135 }
136
137 return hstats;
138 }
139
rtw_hal_cfg_wow_sleep(void * hal,u8 sleep)140 enum rtw_hal_status rtw_hal_cfg_wow_sleep(void *hal, u8 sleep)
141 {
142 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
143 enum rtw_hal_status hstats = RTW_HAL_STATUS_FAILURE;
144
145 hstats = rtw_hal_mac_cfg_wow_sleep(hal_info, sleep);
146
147 if (RTW_HAL_STATUS_SUCCESS != hstats)
148 PHL_ERR("%s : sleep %u\n", __func__, sleep);
149
150 return hstats;
151 }
152
rtw_hal_get_wow_aoac_rpt(void * hal,struct rtw_aoac_report * aoac_info,u8 rx_ready)153 enum rtw_hal_status rtw_hal_get_wow_aoac_rpt(void *hal, struct rtw_aoac_report *aoac_info, u8 rx_ready)
154 {
155 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
156 enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
157
158 FUNCIN();
159
160 /* get aoac report */
161 hstatus = rtw_hal_mac_get_aoac_rpt(hal_info, aoac_info, rx_ready);
162
163 if (RTW_HAL_STATUS_SUCCESS != hstatus)
164 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s(): failed with status(%u)\n", __func__, hstatus);
165
166 FUNCOUT();
167
168 return hstatus;
169 }
170
171
rtw_hal_reset_pkt_ofld_state(void * hal)172 enum rtw_hal_status rtw_hal_reset_pkt_ofld_state(void *hal)
173 {
174
175 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
176 enum rtw_hal_status hstats = RTW_HAL_STATUS_FAILURE;
177
178 hstats = rtw_hal_mac_reset_pkt_ofld_state(hal_info);
179
180 if (RTW_HAL_STATUS_SUCCESS != hstats)
181 PHL_ERR("%s : failed \n", __func__);
182
183 return hstats;
184 }
185
186 #ifdef CONFIG_PCI_HCI
rtw_hal_wow_cfg_txdma(void * hal,u8 en)187 enum rtw_hal_status rtw_hal_wow_cfg_txdma(void *hal, u8 en)
188 {
189 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
190 struct hal_trx_ops *trx_ops = hal_info->trx_ops;
191
192 PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "%s : enable %d.\n", __func__, en);
193
194 trx_ops->cfg_wow_txdma(hal_info, en);
195
196 return RTW_HAL_STATUS_SUCCESS;
197 }
198 #endif
199
200 enum rtw_hal_status
rtw_hal_wow_cfg_nlo(void * hal,enum SCAN_OFLD_OP op,u16 mac_id,u8 hw_band,u8 hw_port,struct rtw_nlo_info * cfg)201 rtw_hal_wow_cfg_nlo(void *hal, enum SCAN_OFLD_OP op, u16 mac_id,
202 u8 hw_band, u8 hw_port, struct rtw_nlo_info *cfg)
203 {
204 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
205 enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
206 struct scan_ofld_info info = {0};
207 u64 tsf;
208 u32 tsf_h = 0, tsf_l = 0;
209
210 if (cfg->delay != 0) {
211 hstatus = rtw_hal_mac_get_tsf(hal, &hw_port, &tsf_h, &tsf_l);
212 if (hstatus == RTW_HAL_STATUS_SUCCESS) {
213 tsf = ((u64)tsf_h << 32) | tsf_l;
214 tsf += cfg->delay * 1000;
215 tsf_h = tsf >> 32;
216 tsf_l = (u32)tsf;
217 info.tsf_high = tsf_h;
218 info.tsf_low = tsf_l;
219 } else {
220 PHL_WARN("%s Getting TSF failed \n", __func__);
221 }
222
223 }
224 /* configure scan offload */
225 info.operation = op;
226 info.probe_req_pkt_id = cfg->probe_req_id;
227 info.period = cfg->period;
228 info.slow_period = cfg->slow_period;
229 info.cycle = cfg->cycle;
230
231 if (info.period == 0 && info.slow_period == 0) {
232 info.mode = SCAN_OFLD_MD_ONCE;
233 } else if (info.period == 0) {
234 info.mode = SCAN_OFLD_MD_SEEMLESS;
235 } else if (info.slow_period == 0) {
236 info.mode = SCAN_OFLD_MD_PD;
237 } else {
238 info.mode = SCAN_OFLD_MD_PD_SLOW;
239 }
240
241 hstatus = rtw_hal_mac_scan_ofld(hal_info, (u8)mac_id,
242 hw_band, hw_port, &info);
243
244 if (hstatus != RTW_HAL_STATUS_SUCCESS)
245 return hstatus;
246
247 return hstatus;
248 }
249
250 enum rtw_hal_status
rtw_hal_wow_cfg_nlo_chnl_list(void * hal,struct rtw_nlo_info * cfg)251 rtw_hal_wow_cfg_nlo_chnl_list(void *hal, struct rtw_nlo_info *cfg)
252 {
253 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
254 enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
255 u8 i = 0;
256
257 if (cfg->channel_num == 0)
258 return RTW_HAL_STATUS_FAILURE;
259
260 for (i = 0; i < cfg->channel_num; i++) {
261 /* set channel to mac */
262 hstatus = rtw_hal_mac_scan_ofld_add_ch(hal_info,
263 &cfg->channel_list[i],
264 i == (cfg->channel_num-1) ? true : false);
265 if (hstatus != RTW_HAL_STATUS_SUCCESS)
266 return hstatus;
267 }
268
269 return hstatus;
270 }
271
rtw_hal_wow_init(struct rtw_phl_com_t * phl_com,void * hal,struct rtw_phl_stainfo_t * sta)272 enum rtw_hal_status rtw_hal_wow_init(struct rtw_phl_com_t *phl_com, void *hal,
273 struct rtw_phl_stainfo_t *sta)
274 {
275 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
276 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
277 struct hal_ops_t *hal_ops = hal_get_ops(hal_info);
278
279 FUNCIN_WSTS(hal_status);
280
281 /* download wowlan fw and do related tasks needed after redownload fw */
282 hal_status = hal_ops->hal_wow_init(phl_com, hal_info, sta);
283 if (hal_status != RTW_HAL_STATUS_SUCCESS)
284 return hal_status;
285
286 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "%s successfully done.\n", __func__);
287
288 FUNCOUT_WSTS(hal_status);
289
290 return hal_status;
291 }
292
rtw_hal_wow_deinit(struct rtw_phl_com_t * phl_com,void * hal,struct rtw_phl_stainfo_t * sta)293 enum rtw_hal_status rtw_hal_wow_deinit(struct rtw_phl_com_t *phl_com, void *hal,
294 struct rtw_phl_stainfo_t *sta)
295 {
296 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
297 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
298 struct hal_ops_t *hal_ops = hal_get_ops(hal_info);
299
300 FUNCIN_WSTS(hal_status);
301
302 /* download wowlan fw and do related tasks needed after redownload fw */
303 hal_status = hal_ops->hal_wow_deinit(phl_com, hal_info, sta);
304 if (hal_status != RTW_HAL_STATUS_SUCCESS)
305 return hal_status;
306
307 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "%s successfully done.\n", __func__);
308
309 FUNCOUT_WSTS(hal_status);
310
311 return hal_status;
312 }
313
314 enum rtw_hal_status
rtw_hal_wow_func_en(struct rtw_phl_com_t * phl_com,void * hal,u16 macid,struct rtw_hal_wow_cfg * cfg)315 rtw_hal_wow_func_en(struct rtw_phl_com_t *phl_com, void *hal, u16 macid,
316 struct rtw_hal_wow_cfg *cfg)
317 {
318
319 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
320 enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
321
322 FUNCIN();
323
324 do {
325 /* config wow cam : pattern match */
326 #ifndef RTW_WKARD_WOW_SKIP_WOW_CAM_CONFIG
327 hstatus = rtw_hal_mac_cfg_wow_cam(hal_info, macid, true, cfg->pattern_match_info);
328 if (RTW_HAL_STATUS_SUCCESS != hstatus)
329 break;
330 #endif
331 /* gtk offload */
332 if (cfg->gtk_ofld_cfg->gtk_en) {
333 hstatus = rtw_hal_mac_cfg_gtk_ofld(hal_info, macid, true,
334 cfg->gtk_ofld_cfg);
335 if (RTW_HAL_STATUS_SUCCESS != hstatus)
336 break;
337 }
338 /* arp offload */
339 if (cfg->arp_ofld_cfg->arp_en) {
340 hstatus = rtw_hal_mac_cfg_arp_ofld(hal_info, macid, true,
341 cfg->arp_ofld_cfg);
342 if (RTW_HAL_STATUS_SUCCESS != hstatus)
343 break;
344 }
345 /* ndp offload */
346 if (cfg->ndp_ofld_cfg->ndp_en) {
347 hstatus = rtw_hal_mac_cfg_ndp_ofld(hal_info, macid, true,
348 cfg->ndp_ofld_cfg);
349 if (RTW_HAL_STATUS_SUCCESS != hstatus)
350 break;
351 }
352 /* config keep alive */
353 if (cfg->keep_alive_cfg->keep_alive_en) {
354 hstatus = rtw_hal_mac_cfg_keep_alive(hal_info, macid, true,
355 cfg->keep_alive_cfg);
356 if (RTW_HAL_STATUS_SUCCESS != hstatus)
357 break;
358 }
359 /* config disconnect detection */
360 if (cfg->disc_det_cfg->disc_det_en) {
361 hstatus = rtw_hal_mac_cfg_disc_dec(hal_info, macid, true,
362 cfg->disc_det_cfg);
363 if (RTW_HAL_STATUS_SUCCESS != hstatus)
364 break;
365 }
366 /* realwow offload */
367 if (cfg->realwow_cfg->realwow_en) {
368 hstatus = rtw_hal_mac_cfg_realwow(hal_info, macid, true,
369 cfg->realwow_cfg);
370 if (RTW_HAL_STATUS_SUCCESS != hstatus)
371 break;
372 }
373 /* config gpio */
374 if (cfg->wow_gpio->d2h_gpio_info.dev2hst_gpio_en) {
375 hstatus = rtw_hal_mac_cfg_dev2hst_gpio(hal_info, true, cfg->wow_gpio);
376 if (RTW_HAL_STATUS_SUCCESS != hstatus)
377 break;
378 }
379 /* network list offload */
380 if (cfg->nlo_cfg->nlo_en) {
381 hstatus = rtw_hal_mac_cfg_nlo(hal_info, macid, true, cfg->nlo_cfg);
382 if (RTW_HAL_STATUS_SUCCESS != hstatus)
383 break;
384 }
385 } while(0);
386
387 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s status(%u).\n", __func__, hstatus);
388
389 FUNCOUT();
390
391 return hstatus;
392 }
393
394 enum rtw_hal_status
rtw_hal_wow_func_dis(struct rtw_phl_com_t * phl_com,void * hal,u16 macid,struct rtw_hal_wow_cfg * cfg)395 rtw_hal_wow_func_dis(struct rtw_phl_com_t *phl_com, void *hal, u16 macid,
396 struct rtw_hal_wow_cfg *cfg)
397 {
398
399 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
400 enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
401
402 FUNCIN();
403
404 /* cancel pattern match */
405 #ifndef RTW_WKARD_WOW_SKIP_WOW_CAM_CONFIG
406 hstatus = rtw_hal_mac_cfg_wow_cam(hal_info, macid, false, NULL);
407 if (RTW_HAL_STATUS_SUCCESS != hstatus)
408 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_wow_cam failed \n");
409 #endif
410 /* cancel gtk offload */
411 if (cfg->gtk_ofld_cfg->gtk_en) {
412 hstatus = rtw_hal_mac_cfg_gtk_ofld(hal_info, macid, false, NULL);
413 if (RTW_HAL_STATUS_SUCCESS != hstatus)
414 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_gtk_ofld failed \n");
415 }
416 /* cancel arp offload */
417 if (cfg->arp_ofld_cfg->arp_en) {
418 hstatus = rtw_hal_mac_cfg_arp_ofld(hal_info, macid, false, NULL);
419 if (RTW_HAL_STATUS_SUCCESS != hstatus)
420 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_arp_ofld failed \n");
421 }
422 /* cancel ndp offload */
423 if (cfg->ndp_ofld_cfg->ndp_en) {
424 hstatus = rtw_hal_mac_cfg_ndp_ofld(hal_info, macid, false, NULL);
425 if (RTW_HAL_STATUS_SUCCESS != hstatus)
426 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_ndp_ofld failed \n");
427 }
428 /* disable keep alive */
429 if (cfg->keep_alive_cfg->keep_alive_en) {
430 hstatus = rtw_hal_mac_cfg_keep_alive(hal_info, macid, false, NULL);
431 if (RTW_HAL_STATUS_SUCCESS != hstatus)
432 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_keep_alive failed \n");
433 }
434 /* disable disconect detection */
435 if (cfg->disc_det_cfg->disc_det_en) {
436 hstatus = rtw_hal_mac_cfg_disc_dec(hal_info, macid, false, NULL);
437 if (RTW_HAL_STATUS_SUCCESS != hstatus)
438 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_disc_dec failed \n");
439 }
440 /* realwow offload */
441 if (cfg->realwow_cfg->realwow_en) {
442 hstatus = rtw_hal_mac_cfg_realwow(hal_info, macid, false, NULL);
443 if (RTW_HAL_STATUS_SUCCESS != hstatus)
444 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_realwow_ofld failed \n");
445 }
446 /* config gpio */
447 if (cfg->wow_gpio->d2h_gpio_info.dev2hst_gpio_en) {
448 hstatus = rtw_hal_mac_cfg_dev2hst_gpio(hal_info, false, NULL);
449 if (RTW_HAL_STATUS_SUCCESS != hstatus)
450 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_dev2hst_gpio failed \n");
451 }
452 /* nlo */
453 if (cfg->nlo_cfg->nlo_en) {
454 hstatus = rtw_hal_mac_cfg_nlo(hal_info, macid, false, NULL);
455 if (RTW_HAL_STATUS_SUCCESS != hstatus)
456 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_nlo failed \n");
457 }
458 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s status(%u).\n", __func__, hstatus);
459
460 FUNCOUT();
461
462 return RTW_HAL_STATUS_SUCCESS;
463 }
464
rtw_hal_wow_func_start(struct rtw_phl_com_t * phl_com,void * hal,u16 macid,struct rtw_hal_wow_cfg * cfg)465 enum rtw_hal_status rtw_hal_wow_func_start(struct rtw_phl_com_t *phl_com, void *hal, u16 macid, struct rtw_hal_wow_cfg *cfg)
466 {
467 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
468 enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
469
470 do {
471 hstatus = rtw_hal_mac_cfg_wow_wake(hal_info, macid, true, cfg->wow_wake_cfg);
472 if (RTW_HAL_STATUS_SUCCESS != hstatus)
473 break;
474 /* poll fw status */
475 hstatus = _hal_check_wow_fw_ready(hal_info, 1);
476 if (RTW_HAL_STATUS_SUCCESS != hstatus)
477 break;
478 } while(0);
479
480 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s status(%u).\n", __func__, hstatus);
481
482 return hstatus;
483 }
484
rtw_hal_wow_func_stop(struct rtw_phl_com_t * phl_com,void * hal,u16 macid)485 enum rtw_hal_status rtw_hal_wow_func_stop(struct rtw_phl_com_t *phl_com, void *hal, u16 macid)
486 {
487 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
488 enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
489
490 /* config wow ctrl */
491 hstatus = rtw_hal_mac_cfg_wow_wake(hal_info, macid, false, NULL);
492 if (RTW_HAL_STATUS_SUCCESS != hstatus)
493 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rtw_hal_mac_cfg_wow_wake failed \n");
494
495 hstatus = _hal_check_wow_fw_ready(hal_info, 0);
496 if (RTW_HAL_STATUS_SUCCESS != hstatus)
497 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] _hal_poll_wow_fw_status failed \n");
498
499 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s status(%u).\n", __func__, hstatus);
500
501 return hstatus;
502 }
503
rtw_hal_set_wowlan(struct rtw_phl_com_t * phl_com,void * hal,u8 enter)504 enum rtw_hal_status rtw_hal_set_wowlan(struct rtw_phl_com_t *phl_com, void *hal, u8 enter)
505 {
506 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
507 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
508 hal_status = rtw_hal_mac_set_wowlan(hal_info, enter);
509
510 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "%s : status(%u).\n", __func__, hal_status);
511
512 return hal_status;
513 }
514
_wow_chk_txq_empty(struct hal_info_t * hal_info,u8 * empty)515 static enum rtw_hal_status _wow_chk_txq_empty(struct hal_info_t *hal_info, u8 *empty)
516 {
517 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
518
519 hal_status = rtw_hal_mac_wow_chk_txq_empty(hal_info, empty);
520
521 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "%s : status(%u).\n", __func__, hal_status);
522
523 return hal_status;
524 }
525
_wow_wde_drop(struct hal_info_t * hal_info,u8 band)526 static enum rtw_hal_status _wow_wde_drop(struct hal_info_t *hal_info, u8 band)
527 {
528 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
529
530 hal_status = rtw_hal_mac_wow_wde_drop(hal_info, band);
531
532 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "%s : status(%u).\n", __func__, hal_status);
533
534 return hal_status;
535 }
536
537 #define MAX_WOW_DROP_HWTX_TRYCNT 3
rtw_hal_wow_drop_tx(void * hal,u8 band)538 enum rtw_hal_status rtw_hal_wow_drop_tx(void *hal, u8 band)
539 {
540 enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
541 struct hal_info_t *hal_info = (struct hal_info_t *)hal;
542 u8 empty = 0;
543 u8 i = 0;
544
545 for (i = 0; i < MAX_WOW_DROP_HWTX_TRYCNT; i++) {
546
547 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : chk/drop for the %d time\n", __func__, i + 1);
548
549 if (RTW_HAL_STATUS_SUCCESS != _wow_chk_txq_empty(hal_info, &empty))
550 PHL_WARN("[wow] _wow_chk_txq_empty failed.\n");
551
552 /* force drop wde if txq is not empty */
553 if (!empty)
554 _wow_wde_drop(hal_info, band);
555 else
556 break;
557 }
558
559 if (!empty) {
560 PHL_WARN("[wow] %s : chk/drop fail!\n", __func__);
561 } else {
562 PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : chk/drop ok.\n", __func__);
563 hal_status = RTW_HAL_STATUS_SUCCESS;
564 }
565
566 return hal_status;
567 }
568
569 #endif /* CONFIG_WOWLAN */
570