xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/phl/hal_g6/hal_wow.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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->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->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