xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/phl_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 _PHL_WOW_C_
16 #include "phl_headers.h"
17 
phl_wow_mdl_init(struct phl_info_t * phl_info)18 enum rtw_phl_status phl_wow_mdl_init(struct phl_info_t* phl_info)
19 {
20 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
21 #ifdef CONFIG_WOWLAN
22 	struct phl_wow_info *info = phl_to_wow_info(phl_info);
23 
24 	info->phl_info = phl_info;
25 	_os_spinlock_init(phl_to_drvpriv(phl_info), &info->wow_lock);
26 #endif /* CONFIG_WOWLAN */
27 
28 	return pstatus;
29 }
30 
phl_wow_mdl_deinit(struct phl_info_t * phl_info)31 void phl_wow_mdl_deinit(struct phl_info_t* phl_info)
32 {
33 #ifdef CONFIG_WOWLAN
34 	struct phl_wow_info *info = phl_to_wow_info(phl_info);
35 
36 	_os_spinlock_free(phl_to_drvpriv(phl_info), &info->wow_lock);
37 #endif /* CONFIG_WOWLAN */
38 }
39 
40 #ifdef CONFIG_WOWLAN
41 
42 /* TO-DO: Confirm the enum strcut of the algo */
_phl_query_iv_len(u8 algo)43 u8 _phl_query_iv_len(u8 algo)
44 {
45 	u8 len = 0;
46 
47 	switch(algo) {
48 	case RTW_ENC_WEP40:
49 		len = 4;
50 		break;
51 	case RTW_ENC_TKIP:
52 	case RTW_ENC_CCMP:
53 	case RTW_ENC_GCMP256:
54 		len = 8;
55 		break;
56 	default:
57 		len = 0;
58 		break;
59 	}
60 
61 	return len;
62 }
63 
_phl_query_key_desc_ver(struct phl_wow_info * wow_info,u8 algo)64 u8 _phl_query_key_desc_ver(struct phl_wow_info *wow_info, u8 algo)
65 {
66 	u8 akm_type = wow_info->gtk_ofld_info.akmtype_byte3;
67 
68 	if (algo == RTW_ENC_TKIP)
69 		return EAPOLKEY_KEYDESC_VER_1;
70 
71 	if (akm_type == 1 || akm_type == 2) {
72 		return EAPOLKEY_KEYDESC_VER_2;
73 	} else if (akm_type > 2 && akm_type < 7) {
74 		return EAPOLKEY_KEYDESC_VER_3;
75 	} else {
76 		return 0;
77 	}
78 }
79 
_phl_cfg_pkt_ofld_null_info(struct phl_wow_info * wow_info,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_null_info * null_info)80 static void _phl_cfg_pkt_ofld_null_info(
81 	struct phl_wow_info *wow_info,
82 	struct rtw_phl_stainfo_t *phl_sta,
83 	struct rtw_pkt_ofld_null_info *null_info)
84 {
85 	void *drv_priv = phl_to_drvpriv(wow_info->phl_info);
86 
87 	_os_mem_cpy(drv_priv, &(null_info->a1[0]), &(phl_sta->mac_addr[0]), MAC_ADDRESS_LENGTH);
88 	_os_mem_cpy(drv_priv, &(null_info->a2[0]), &(phl_sta->wrole->mac_addr[0]), MAC_ADDRESS_LENGTH);
89 	_os_mem_cpy(drv_priv, &(null_info->a3[0]), &(phl_sta->mac_addr[0]), MAC_ADDRESS_LENGTH);
90 
91 }
92 
_phl_cfg_pkt_ofld_probe_req_info(struct phl_wow_info * wow_info,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_probe_req_info * probe_req_info)93 static void _phl_cfg_pkt_ofld_probe_req_info(
94 	struct phl_wow_info *wow_info,
95 	struct rtw_phl_stainfo_t *phl_sta,
96 	struct rtw_pkt_ofld_probe_req_info *probe_req_info)
97 {
98 	void *drv_priv = phl_to_drvpriv(wow_info->phl_info);
99 
100 	if (wow_info->nlo_info.construct_pbreq == NULL) {
101 		_os_mem_cpy(drv_priv, &(probe_req_info->a2[0]),
102 			&(phl_sta->wrole->mac_addr[0]), MAC_ADDRESS_LENGTH);
103 	} else {
104 		probe_req_info->construct_pbreq = wow_info->nlo_info.construct_pbreq;
105 	}
106 }
107 
_phl_cfg_pkt_ofld_arp_rsp_info(struct phl_wow_info * wow_info,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_arp_rsp_info * arp_rsp_info)108 static void _phl_cfg_pkt_ofld_arp_rsp_info(struct phl_wow_info *wow_info, struct rtw_phl_stainfo_t *phl_sta,
109 						struct rtw_pkt_ofld_arp_rsp_info *arp_rsp_info)
110 {
111 	void *drv_priv = phl_to_drvpriv(wow_info->phl_info);
112 	u8 pairwise_algo = get_wow_pairwise_algo_type(wow_info);
113 
114 	_os_mem_cpy(drv_priv, &(arp_rsp_info->a1[0]), &(phl_sta->mac_addr[0]), MAC_ADDRESS_LENGTH);
115 	_os_mem_cpy(drv_priv, &(arp_rsp_info->a2[0]), &(phl_sta->wrole->mac_addr[0]), MAC_ADDRESS_LENGTH);
116 	_os_mem_cpy(drv_priv, &(arp_rsp_info->a3[0]), &(phl_sta->mac_addr[0]), MAC_ADDRESS_LENGTH);
117 	_os_mem_cpy(drv_priv, &(arp_rsp_info->host_ipv4_addr[0]),
118 		&(wow_info->arp_ofld_info.arp_ofld_content.host_ipv4_addr[0]),
119 		IPV4_ADDRESS_LENGTH);
120 	_os_mem_cpy(drv_priv, &(arp_rsp_info->remote_ipv4_addr[0]),
121 		&(wow_info->arp_ofld_info.arp_ofld_content.remote_ipv4_addr[0]),
122 		IPV4_ADDRESS_LENGTH);
123 
124 	arp_rsp_info->sec_hdr = _phl_query_iv_len(pairwise_algo);
125 }
126 
_phl_cfg_pkt_ofld_na_info(struct phl_wow_info * wow_info,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_na_info * na_info)127 static void _phl_cfg_pkt_ofld_na_info(struct phl_wow_info *wow_info, struct rtw_phl_stainfo_t *phl_sta,
128 					struct rtw_pkt_ofld_na_info *na_info)
129 {
130 	void *drv_priv = phl_to_drvpriv(wow_info->phl_info);
131 	u8 pairwise_algo = get_wow_pairwise_algo_type(wow_info);
132 
133 	_os_mem_cpy(drv_priv, &(na_info->a1[0]), &(phl_sta->mac_addr[0]), MAC_ADDRESS_LENGTH);
134 	_os_mem_cpy(drv_priv, &(na_info->a2[0]), &(phl_sta->wrole->mac_addr[0]), MAC_ADDRESS_LENGTH);
135 	_os_mem_cpy(drv_priv, &(na_info->a3[0]), &(phl_sta->mac_addr[0]), MAC_ADDRESS_LENGTH);
136 
137 	na_info->sec_hdr = _phl_query_iv_len(pairwise_algo);
138 
139 }
140 
_phl_cfg_pkt_ofld_eapol_key_info(struct phl_wow_info * wow_info,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_eapol_key_info * eapol_key_info)141 static void _phl_cfg_pkt_ofld_eapol_key_info(
142 	struct phl_wow_info *wow_info,
143 	struct rtw_phl_stainfo_t *phl_sta,
144 	struct rtw_pkt_ofld_eapol_key_info *eapol_key_info)
145 {
146 	void *drv_priv = phl_to_drvpriv(wow_info->phl_info);
147 	struct rtw_gtk_ofld_info *gtk_ofld_info = &wow_info->gtk_ofld_info;
148 
149 	u8 pairwise_algo = get_wow_pairwise_algo_type(wow_info);
150 
151 	_os_mem_cpy(drv_priv, &(eapol_key_info->a1[0]), &(phl_sta->mac_addr[0]),
152 		MAC_ADDRESS_LENGTH);
153 
154 	_os_mem_cpy(drv_priv, &(eapol_key_info->a2[0]), &(phl_sta->wrole->mac_addr[0]),
155 			MAC_ADDRESS_LENGTH);
156 
157 	_os_mem_cpy(drv_priv, &(eapol_key_info->a3[0]), &(phl_sta->mac_addr[0]),
158 			MAC_ADDRESS_LENGTH);
159 
160 	eapol_key_info->sec_hdr = _phl_query_iv_len(pairwise_algo);
161 	eapol_key_info->key_desc_ver = _phl_query_key_desc_ver(wow_info, pairwise_algo);
162 	_os_mem_cpy(drv_priv, eapol_key_info->replay_cnt,
163 				gtk_ofld_info->gtk_ofld_content.replay_cnt, 8);
164 }
165 
_phl_cfg_pkt_ofld_sa_query_info(struct phl_wow_info * wow_info,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_sa_query_info * sa_query_info)166 static void _phl_cfg_pkt_ofld_sa_query_info(
167 	struct phl_wow_info *wow_info,
168 	struct rtw_phl_stainfo_t *phl_sta,
169 	struct rtw_pkt_ofld_sa_query_info *sa_query_info)
170 {
171 	void *drv_priv = phl_to_drvpriv(wow_info->phl_info);
172 	u8 pairwise_algo = get_wow_pairwise_algo_type(wow_info);
173 
174 	_os_mem_cpy(drv_priv, &(sa_query_info->a1[0]), &(phl_sta->mac_addr[0]),
175 			MAC_ADDRESS_LENGTH);
176 
177 	_os_mem_cpy(drv_priv, &(sa_query_info->a2[0]), &(phl_sta->wrole->mac_addr[0]),
178 			MAC_ADDRESS_LENGTH);
179 
180 	_os_mem_cpy(drv_priv, &(sa_query_info->a3[0]), &(phl_sta->mac_addr[0]),
181 			MAC_ADDRESS_LENGTH);
182 
183 	sa_query_info->sec_hdr = _phl_query_iv_len(pairwise_algo);
184 }
185 
_phl_cfg_pkt_ofld_realwow_kapkt_info(struct phl_wow_info * wow_info,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_realwow_kapkt_info * kapkt_info)186 static void _phl_cfg_pkt_ofld_realwow_kapkt_info(
187 	struct phl_wow_info *wow_info,
188 	struct rtw_phl_stainfo_t *phl_sta,
189 	struct rtw_pkt_ofld_realwow_kapkt_info *kapkt_info)
190 {
191 	void *drv_priv = phl_to_drvpriv(wow_info->phl_info);
192 
193 	_os_mem_cpy(drv_priv, &(kapkt_info->keep_alive_pkt_ptrn[0]),
194 		&(wow_info->realwow_info.realwow_ofld_content.keep_alive_pkt_ptrn[0]),
195 		wow_info->realwow_info.realwow_ofld_content.keep_alive_pkt_size);
196 
197 	kapkt_info->keep_alive_pkt_size =
198 				wow_info->realwow_info.realwow_ofld_content.keep_alive_pkt_size;
199 }
200 
_phl_cfg_pkt_ofld_realwow_ack_info(struct phl_wow_info * wow_info,struct rtw_pkt_ofld_realwow_ack_info * ack_info)201 static void _phl_cfg_pkt_ofld_realwow_ack_info(
202 	struct phl_wow_info *wow_info,
203 	struct rtw_pkt_ofld_realwow_ack_info *ack_info)
204 {
205 	void *drv_priv = phl_to_drvpriv(wow_info->phl_info);
206 
207 	_os_mem_cpy(drv_priv, &(ack_info->ack_ptrn[0]),
208 		&(wow_info->realwow_info.realwow_ofld_content.ack_ptrn[0]),
209 		wow_info->realwow_info.realwow_ofld_content.ack_ptrn_size);
210 
211 	ack_info->ack_ptrn_size = wow_info->realwow_info.realwow_ofld_content.ack_ptrn_size;
212 }
213 
_phl_cfg_pkt_ofld_realwow_wp_info(struct phl_wow_info * wow_info,struct rtw_pkt_ofld_realwow_wp_info * wp_info)214 static void _phl_cfg_pkt_ofld_realwow_wp_info(
215 	struct phl_wow_info *wow_info,
216 	struct rtw_pkt_ofld_realwow_wp_info *wp_info)
217 {
218 	void *drv_priv = phl_to_drvpriv(wow_info->phl_info);
219 
220 	_os_mem_cpy(drv_priv, &(wp_info->wakeup_ptrn[0]),
221 		&(wow_info->realwow_info.realwow_ofld_content.wakeup_ptrn[0]),
222 		wow_info->realwow_info.realwow_ofld_content.wakeup_ptrn_size);
223 
224 	wp_info->wakeup_ptrn_size = wow_info->realwow_info.realwow_ofld_content.wakeup_ptrn_size;
225 }
226 
rtw_phl_cfg_keep_alive_info(void * phl,struct rtw_keep_alive_info * info)227 enum rtw_phl_status rtw_phl_cfg_keep_alive_info(void *phl, struct rtw_keep_alive_info *info)
228 {
229 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
230 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
231 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
232 	struct rtw_keep_alive_info *keep_alive_info = &wow_info->keep_alive_info;
233 
234 	FUNCIN();
235 
236 	keep_alive_info->keep_alive_en = info->keep_alive_en;
237 	keep_alive_info->keep_alive_period = info->keep_alive_period;
238 
239 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] keep_alive_en %d\n", keep_alive_info->keep_alive_en);
240 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] keep_alive_period %d\n", keep_alive_info->keep_alive_period);
241 
242 	return phl_status;
243 }
244 
rtw_phl_cfg_disc_det_info(void * phl,struct rtw_disc_det_info * info)245 enum rtw_phl_status rtw_phl_cfg_disc_det_info(void *phl, struct rtw_disc_det_info *info)
246 {
247 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
248 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
249 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
250 	struct rtw_disc_det_info *disc_det_info = &wow_info->disc_det_info;
251 
252 	FUNCIN();
253 
254 	disc_det_info->disc_det_en = info->disc_det_en;
255 	disc_det_info->disc_wake_en = info->disc_wake_en;
256 	disc_det_info->try_pkt_count = info->try_pkt_count;
257 	disc_det_info->check_period = info->check_period;
258 	disc_det_info->cnt_bcn_lost_en = info->cnt_bcn_lost_en;
259 	disc_det_info->cnt_bcn_lost_limit = info->cnt_bcn_lost_limit;
260 
261 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] disc_det_en %d\n", disc_det_info->disc_det_en);
262 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] disc_wake_en %d\n", disc_det_info->disc_wake_en);
263 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] try_pkt_count %d\n", disc_det_info->try_pkt_count);
264 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] check_period %d\n", disc_det_info->check_period);
265 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] cnt_bcn_lost_en %d\n", disc_det_info->cnt_bcn_lost_en);
266 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] cnt_bcn_lost_limit %d\n", disc_det_info->cnt_bcn_lost_limit);
267 
268 	return phl_status;
269 }
270 
271 static void
_phl_show_nlo_info(struct rtw_nlo_info * info)272 _phl_show_nlo_info(struct rtw_nlo_info *info)
273 {
274 	u32 i = 0;
275 
276 	if (info->num_of_networks == 0)
277 		return;
278 
279 	for (i = 0; i < info->num_of_networks; i++) {
280 
281 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_,
282 			"[wow][nlo] #%u ssid/len/cipher = %s/%u/%#x \n",
283 			i, (char *)info->ssid[i], info->ssidlen[i], info->chipertype[i]);
284 	}
285 
286 	for (i = 0; i < info->channel_num; i++) {
287 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_,
288 			"[wow][nlo] channel #%u: %u \n", i, info->channel_list[i].chan);
289 	}
290 
291 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_,
292 		"[wow][nlo] num of hidden ap %u \n", info->num_of_hidden_ap);
293 
294 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_,
295 		"[wow][nlo] delyms/cycle/period/slow_period = %u/%u/%u/%u \n",
296 		info->delay, info->cycle, info->period, info->slow_period);
297 
298 }
299 
rtw_phl_cfg_nlo_info(void * phl,struct rtw_nlo_info * info)300 void rtw_phl_cfg_nlo_info(void *phl, struct rtw_nlo_info *info)
301 {
302 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
303 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
304 	struct rtw_nlo_info *nlo_info = &wow_info->nlo_info;
305 	void *drv_priv = phl_to_drvpriv(phl_info);
306 
307 	FUNCIN();
308 
309 	nlo_info->nlo_en = info->nlo_en;
310 	nlo_info->num_of_networks = info->num_of_networks;
311 	_os_mem_cpy(drv_priv, nlo_info->ssid, info->ssid,
312 		info->num_of_networks * MAX_SSID_LEN);
313 	_os_mem_cpy(drv_priv, nlo_info->ssidlen,
314 		info->ssidlen, info->num_of_networks);
315 	_os_mem_cpy(drv_priv, nlo_info->chipertype,
316 		info->chipertype, info->num_of_networks);
317 	nlo_info->num_of_hidden_ap = info->num_of_hidden_ap;
318 	nlo_info->channel_num = info->channel_num;
319 	_os_mem_cpy(drv_priv, nlo_info->channel_list, info->channel_list,
320 		info->channel_num * sizeof(struct scan_ofld_ch_info));
321 	nlo_info->period = info->period;
322 	nlo_info->cycle = info->cycle;
323 	nlo_info->slow_period = info->slow_period;
324 	nlo_info->delay = info->delay;
325 	nlo_info->construct_pbreq = info->construct_pbreq;
326 
327 	_phl_show_nlo_info(nlo_info);
328 }
329 
rtw_phl_cfg_arp_ofld_info(void * phl,struct rtw_arp_ofld_info * info)330 void rtw_phl_cfg_arp_ofld_info(void *phl, struct rtw_arp_ofld_info *info)
331 {
332 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
333 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
334 	struct rtw_arp_ofld_info *arp_ofld_info = &wow_info->arp_ofld_info;
335 	void *drv_priv = phl_to_drvpriv(phl_info);
336 
337 	FUNCIN();
338 
339 
340 	arp_ofld_info->arp_en = info->arp_en;
341 
342 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] arp_en %u\n",
343 			arp_ofld_info->arp_en);
344 
345 	/* If not enabled, the following actions are not necessary */
346 	if (false == arp_ofld_info->arp_en)
347 		return;
348 
349 	arp_ofld_info->arp_action = info->arp_action;
350 
351 	_os_mem_cpy(drv_priv,
352 		&(arp_ofld_info->arp_ofld_content.remote_ipv4_addr[0]),
353 		&(info->arp_ofld_content.remote_ipv4_addr[0]),
354 		IPV4_ADDRESS_LENGTH);
355 
356 	_os_mem_cpy(drv_priv,
357 		&(arp_ofld_info->arp_ofld_content.host_ipv4_addr[0]),
358 		&(info->arp_ofld_content.host_ipv4_addr[0]),
359 		IPV4_ADDRESS_LENGTH);
360 
361 	_os_mem_cpy(drv_priv,
362 		&(arp_ofld_info->arp_ofld_content.mac_addr[0]),
363 		&(info->arp_ofld_content.mac_addr[0]),
364 		MAC_ADDRESS_LENGTH);
365 
366 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] arp_action %u\n",
367 			arp_ofld_info->arp_action);
368 
369 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] arp_remote_ipv4  %u:%u:%u:%u\n",
370 			arp_ofld_info->arp_ofld_content.remote_ipv4_addr[0],
371 			arp_ofld_info->arp_ofld_content.remote_ipv4_addr[1],
372 			arp_ofld_info->arp_ofld_content.remote_ipv4_addr[2],
373 			arp_ofld_info->arp_ofld_content.remote_ipv4_addr[3]);
374 
375 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] arp_host_ipv4  %u:%u:%u:%u\n",
376 			arp_ofld_info->arp_ofld_content.host_ipv4_addr[0],
377 			arp_ofld_info->arp_ofld_content.host_ipv4_addr[1],
378 			arp_ofld_info->arp_ofld_content.host_ipv4_addr[2],
379 			arp_ofld_info->arp_ofld_content.host_ipv4_addr[3]);
380 
381 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] arp_mac_addr  %02x:%02x:%02x:%02x:%02x:%02x \n",
382 			arp_ofld_info->arp_ofld_content.mac_addr[0],
383 			arp_ofld_info->arp_ofld_content.mac_addr[1],
384 			arp_ofld_info->arp_ofld_content.mac_addr[2],
385 			arp_ofld_info->arp_ofld_content.mac_addr[3],
386 			arp_ofld_info->arp_ofld_content.mac_addr[4],
387 			arp_ofld_info->arp_ofld_content.mac_addr[5]);
388 
389 }
390 
rtw_phl_cfg_ndp_ofld_info(void * phl,struct rtw_ndp_ofld_info * info)391 void rtw_phl_cfg_ndp_ofld_info(void *phl, struct rtw_ndp_ofld_info *info)
392 {
393 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
394 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
395 	struct rtw_ndp_ofld_info *ndp_ofld_info = &wow_info->ndp_ofld_info;
396 	struct rtw_ndp_ofld_content *pcontent;
397 	void *drv_priv = phl_to_drvpriv(phl_info);
398 	u8 idx = 0;
399 
400 	FUNCIN();
401 
402 	ndp_ofld_info->ndp_en = info->ndp_en;
403 
404 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] ndp_en %u\n",
405 			ndp_ofld_info->ndp_en);
406 
407 	/* If not enabled, the following actions are not necessary */
408 	if (false == ndp_ofld_info->ndp_en)
409 		return;
410 
411 	for (idx = 0; idx < 2; idx++) {
412 
413 		pcontent = &ndp_ofld_info->ndp_ofld_content[idx];
414 		pcontent->ndp_en = info->ndp_ofld_content[idx].ndp_en;
415 
416 		pcontent->chk_remote_ip =
417 			info->ndp_ofld_content[idx].chk_remote_ip;
418 		pcontent->num_target_ip =
419 			info->ndp_ofld_content[idx].num_target_ip;
420 
421 		_os_mem_cpy(drv_priv, &(pcontent->mac_addr[0]),
422 			&(info->ndp_ofld_content[idx].mac_addr[0]),
423 			MAC_ADDRESS_LENGTH);
424 		_os_mem_cpy(drv_priv, &(pcontent->remote_ipv6_addr[0]),
425 			&(info->ndp_ofld_content[idx].remote_ipv6_addr[0]),
426 			IPV6_ADDRESS_LENGTH);
427 		_os_mem_cpy(drv_priv, &(pcontent->target_ipv6_addr[0][0]),
428 			&(info->ndp_ofld_content[idx].target_ipv6_addr[0][0]),
429 			IPV6_ADDRESS_LENGTH*2);
430 
431 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] ndp_chk_remote_ip %u\n",
432 			pcontent->chk_remote_ip);
433 
434 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] ndp_num_target_ip %u\n",
435 			pcontent->num_target_ip);
436 
437 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] ndp_mac_addr  %02x:%02x:%02x:%02x:%02x:%02x \n",
438 			pcontent->mac_addr[0],
439 			pcontent->mac_addr[1],
440 			pcontent->mac_addr[2],
441 			pcontent->mac_addr[3],
442 			pcontent->mac_addr[4],
443 			pcontent->mac_addr[5]);
444 
445 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_,
446 			"[wow] ndp_remote_ipv6  %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x \n",
447 			pcontent->remote_ipv6_addr[0],
448 			pcontent->remote_ipv6_addr[1],
449 			pcontent->remote_ipv6_addr[2],
450 			pcontent->remote_ipv6_addr[3],
451 			pcontent->remote_ipv6_addr[4],
452 			pcontent->remote_ipv6_addr[5],
453 			pcontent->remote_ipv6_addr[6],
454 			pcontent->remote_ipv6_addr[7],
455 			pcontent->remote_ipv6_addr[8],
456 			pcontent->remote_ipv6_addr[9],
457 			pcontent->remote_ipv6_addr[10],
458 			pcontent->remote_ipv6_addr[11],
459 			pcontent->remote_ipv6_addr[12],
460 			pcontent->remote_ipv6_addr[13],
461 			pcontent->remote_ipv6_addr[14],
462 			pcontent->remote_ipv6_addr[15]);
463 
464 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_,
465 			"[wow] ndp_target_ipv6_addr  %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x \n",
466 			pcontent->target_ipv6_addr[0][0],
467 			pcontent->target_ipv6_addr[0][1],
468 			pcontent->target_ipv6_addr[0][2],
469 			pcontent->target_ipv6_addr[0][3],
470 			pcontent->target_ipv6_addr[0][4],
471 			pcontent->target_ipv6_addr[0][5],
472 			pcontent->target_ipv6_addr[0][6],
473 			pcontent->target_ipv6_addr[0][7],
474 			pcontent->target_ipv6_addr[0][8],
475 			pcontent->target_ipv6_addr[0][9],
476 			pcontent->target_ipv6_addr[0][10],
477 			pcontent->target_ipv6_addr[0][11],
478 			pcontent->target_ipv6_addr[0][12],
479 			pcontent->target_ipv6_addr[0][13],
480 			pcontent->target_ipv6_addr[0][14],
481 			pcontent->target_ipv6_addr[0][15]);
482 
483 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_,
484 			"[wow] ndp_target_ipv6_addr  %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x \n",
485 			pcontent->target_ipv6_addr[1][0],
486 			pcontent->target_ipv6_addr[1][1],
487 			pcontent->target_ipv6_addr[1][2],
488 			pcontent->target_ipv6_addr[1][3],
489 			pcontent->target_ipv6_addr[1][4],
490 			pcontent->target_ipv6_addr[1][5],
491 			pcontent->target_ipv6_addr[1][6],
492 			pcontent->target_ipv6_addr[1][7],
493 			pcontent->target_ipv6_addr[1][8],
494 			pcontent->target_ipv6_addr[1][9],
495 			pcontent->target_ipv6_addr[1][10],
496 			pcontent->target_ipv6_addr[1][11],
497 			pcontent->target_ipv6_addr[1][12],
498 			pcontent->target_ipv6_addr[1][13],
499 			pcontent->target_ipv6_addr[1][14],
500 			pcontent->target_ipv6_addr[1][15]);
501 
502 	}
503 
504 }
505 
_phl_query_free_cam_entry_idx(struct rtw_pattern_match_info * pattern_match_info)506 u8 _phl_query_free_cam_entry_idx(struct rtw_pattern_match_info *pattern_match_info)
507 {
508 	struct rtw_wowcam_upd_info *wowcam_info = pattern_match_info->wowcam_info;
509 	u8 i = 0;
510 
511 	for (i = 0; i < MAX_WOW_CAM_NUM; ++i)
512 		if (wowcam_info[i].valid == 0)
513 			break;
514 
515 	return i;
516 }
517 
_phl_cal_crc16(u8 data,u16 crc)518 u16 _phl_cal_crc16(u8 data, u16 crc)
519 {
520 	u8 shift_in, data_bit;
521 	u8 crc_bit4, crc_bit11, crc_bit15;
522 	u16 crc_result;
523 	int index;
524 
525 	for (index = 0; index < 8; index++) {
526 		crc_bit15 = ((crc & BIT15) ? 1 : 0);
527 		data_bit = (data & (BIT0 << index) ? 1 : 0);
528 		shift_in = crc_bit15 ^ data_bit;
529 		/*printf("crc_bit15=%d, DataBit=%d, shift_in=%d\n",
530 		 * crc_bit15, data_bit, shift_in);*/
531 
532 		crc_result = crc << 1;
533 
534 		if (shift_in == 0)
535 			crc_result &= (~BIT0);
536 		else
537 			crc_result |= BIT0;
538 		/*printf("CRC =%x\n",CRC_Result);*/
539 
540 		crc_bit11 = ((crc & BIT11) ? 1 : 0) ^ shift_in;
541 
542 		if (crc_bit11 == 0)
543 			crc_result &= (~BIT12);
544 		else
545 			crc_result |= BIT12;
546 
547 		/*printf("bit12 CRC =%x\n",CRC_Result);*/
548 
549 		crc_bit4 = ((crc & BIT4) ? 1 : 0) ^ shift_in;
550 
551 		if (crc_bit4 == 0)
552 			crc_result &= (~BIT5);
553 		else
554 			crc_result |= BIT5;
555 
556 		/* printf("bit5 CRC =%x\n",CRC_Result); */
557 		crc = crc_result;
558 	}
559 	return crc;
560 }
561 
_phl_cal_wow_ptrn_crc(u8 * pattern,u32 length)562 u16 _phl_cal_wow_ptrn_crc(u8 *pattern, u32 length)
563 {
564 	u16 crc = 0xffff;
565 	u32 i;
566 
567 	for (i = 0; i < length; i++)
568 		crc = _phl_cal_crc16(pattern[i], crc);
569 	crc = ~crc;
570 
571 	return crc;
572 }
573 /*
574  * To get the wake up pattern from the mask.
575  * We do not count first 12 bits which means
576  * DA[6] and SA[6] in the pattern to match HW design.
577  */
_phl_get_ptrn_after_mask(struct rtw_wowcam_upd_info * wowcam_info,u8 * ptrn_after_mask)578 u32 _phl_get_ptrn_after_mask(struct rtw_wowcam_upd_info *wowcam_info, u8 *ptrn_after_mask)
579 {
580 	u32 ptrn_len_after_mask = 0;
581 	u32 i;
582 	u8 da_sa_offset = 12;
583 
584 	for (i = da_sa_offset; i < wowcam_info->ptrn_len; i++) {
585 		if (wowcam_info->mask[i / 8] >> (i % 8) & 0x01) {
586 			ptrn_after_mask[ptrn_len_after_mask] = wowcam_info->ptrn[i];
587 			ptrn_len_after_mask++;
588 		}
589 	}
590 
591 	return ptrn_len_after_mask;
592 }
593 
594 /*
595  * translate mask from os to mask for hw
596  *
597  * pattern from OS uses 'ethenet frame', like this:
598  *	|    6   |    6   |   2  |     20    |  Variable  |  4  |
599  *	|--------+--------+------+-----------+------------+-----|
600  *	|    802.3 Mac Header    | IP Header | TCP Packet | FCS |
601  *	|   DA   |   SA   | Type |
602  *
603  * BUT, packet catched by our HW is in '802.11 frame', begin from LLC,
604  *	|     24 or 30      |    6   |   2  |     20    |  Variable  |  4  |
605  *	|-------------------+--------+------+-----------+------------+-----|
606  *	| 802.11 MAC Header |       LLC     | IP Header | TCP Packet | FCS |
607  *			    | Others | Type |
608  *
609  * Therefore, we need to translate mask_from_OS to mask_to_hw.
610  * We should left-shift mask_from_os by 6 bits to omit 'DA',
611  * to make it correspond to 'LLC' of mask_to_hw.
612  * Our HW packet begins from LLC, mask_to_hw[5:0] is part of LLC,
613  * but mask_from_os[5:0] is 'SA' after left-shift.
614  * They just don't match, so we need to set first 5 bits to 0.
615 */
616 
_phl_to_hw_wake_mask(struct rtw_wowcam_upd_info * wowcam_info)617 void _phl_to_hw_wake_mask(struct rtw_wowcam_upd_info *wowcam_info)
618 {
619 	u8 mask_hw[MAX_WOW_PATTERN_SIZE_BYTE] = {0};
620 	u32 mask_len = _os_div_round_up(wowcam_info->ptrn_len, 8);
621 	u32 i;
622 	u8 sa_offset = 6;
623 
624 	for (i = 0; i < mask_len - 1; i++) {
625 		mask_hw[i] = wowcam_info->mask[i] >> sa_offset;
626 		mask_hw[i] |= (wowcam_info->mask[i + 1] & 0x3F) << 2;
627 	}
628 	mask_hw[i] = (wowcam_info->mask[i] >> sa_offset) & 0x3F;
629 	mask_hw[0] &= 0xC0;
630 
631 	for (i = 0; i < MAX_WOW_PATTERN_SIZE_DWORD; i++) {
632 		wowcam_info->wake_mask[i] = mask_hw[i * 4];
633 		wowcam_info->wake_mask[i] |= (mask_hw[i * 4 + 1] << 8);
634 		wowcam_info->wake_mask[i] |= (mask_hw[i * 4 + 2] << 16);
635 		wowcam_info->wake_mask[i] |= (mask_hw[i * 4 + 3] << 24);
636 	}
637 }
638 
rtw_phl_remove_wow_ptrn_info(void * phl,u8 wowcam_id)639 enum rtw_phl_status rtw_phl_remove_wow_ptrn_info(void *phl, u8 wowcam_id)
640 {
641 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
642 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
643 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
644 	struct rtw_pattern_match_info *pattern_match_info = &wow_info->pattern_match_info;
645 	struct rtw_wowcam_upd_info *wowcam_info = &(pattern_match_info->wowcam_info[wowcam_id]);
646 
647 	if (wowcam_id < MAX_WOW_CAM_NUM) {
648 		wowcam_info->valid = 0;
649 		phl_status = RTW_PHL_STATUS_SUCCESS;
650 	} else {
651 		PHL_TRACE(COMP_PHL_WOW, _PHL_WARNING_, "[wow] %s(): Invalid wowcam id(%u), Fail.\n",
652 						__func__, wowcam_id);
653 		phl_status = RTW_PHL_STATUS_FAILURE;
654 	}
655 
656 	return phl_status;
657 }
658 
rtw_phl_add_wow_ptrn_info(void * phl,struct rtw_wowcam_upd_info * info,u8 * wowcam_id)659 enum rtw_phl_status rtw_phl_add_wow_ptrn_info(void *phl, struct rtw_wowcam_upd_info *info, u8 *wowcam_id)
660 {
661 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
662 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
663 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
664 	struct rtw_pattern_match_info *pattern_match_info = &wow_info->pattern_match_info;
665 	struct rtw_wowcam_upd_info *wowcam_info = NULL;
666 	void *d = phl_to_drvpriv(phl_info);
667 	u8 ptrn_after_mask[MAX_WOW_PATTERN_SIZE_BIT] = {0};
668 	u32 ptrn_len_after_mask = 0;
669 
670 	*wowcam_id = _phl_query_free_cam_entry_idx(pattern_match_info);
671 
672 	if (*wowcam_id < MAX_WOW_CAM_NUM) {
673 		wowcam_info = &(pattern_match_info->wowcam_info[*wowcam_id]);
674 
675 		_os_mem_set(d, wowcam_info, 0, sizeof(struct rtw_wowcam_upd_info));
676 		_os_mem_cpy(d, wowcam_info, info, sizeof(struct rtw_wowcam_upd_info));
677 
678 		ptrn_len_after_mask = _phl_get_ptrn_after_mask(wowcam_info, ptrn_after_mask);
679 		wowcam_info->match_crc = _phl_cal_wow_ptrn_crc(ptrn_after_mask, ptrn_len_after_mask);
680 
681 		_phl_to_hw_wake_mask(wowcam_info);
682 
683 		/* fill in phl */
684 		wowcam_info->wow_cam_idx = *wowcam_id;
685 		wowcam_info->rw = 1;
686 		wowcam_info->is_negative_pattern_match = 0;
687 		wowcam_info->skip_mac_hdr = 1;
688 		wowcam_info->valid = 1;
689 
690 		phl_status = RTW_PHL_STATUS_SUCCESS;
691 	} else {
692 		PHL_TRACE(COMP_PHL_WOW, _PHL_WARNING_, "[wow] no free cam entry can be used.\n");
693 		phl_status = RTW_PHL_STATUS_RESOURCE;
694 	}
695 
696 	return phl_status;
697 }
698 
rtw_phl_cfg_gtk_ofld_info(void * phl,struct rtw_gtk_ofld_info * info)699 enum rtw_phl_status rtw_phl_cfg_gtk_ofld_info(void *phl, struct rtw_gtk_ofld_info *info)
700 {
701 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
702 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
703 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
704 	struct rtw_gtk_ofld_info *gtk_ofld_info = &wow_info->gtk_ofld_info;
705 	void *d = phl_to_drvpriv(phl_info);
706 
707 	FUNCIN();
708 
709 	if (info == NULL || gtk_ofld_info == NULL) {
710 		PHL_TRACE(COMP_PHL_WOW, _PHL_WARNING_, "[wow] %s(): some ptr is NULL\n", __func__);
711 		phl_status = RTW_PHL_STATUS_FAILURE;
712 
713 	} else {
714 		_os_mem_set(d, gtk_ofld_info, 0, sizeof(struct rtw_gtk_ofld_info));
715 
716 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gtk_en(%u), continue to gtk_ofld.\n", info->gtk_en);
717 
718 		if (info->gtk_en) {
719 			_os_mem_cpy(d, gtk_ofld_info, info, sizeof(struct rtw_gtk_ofld_info));
720 
721 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gtk_ofld_info:\n");
722 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - gtk_en          = %u\n", gtk_ofld_info->gtk_en);
723 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - tkip_en         = %u\n", gtk_ofld_info->tkip_en);
724 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - ieee80211w_en   = %u\n", gtk_ofld_info->ieee80211w_en);
725 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - pairwise_wakeup = %u\n", gtk_ofld_info->pairwise_wakeup);
726 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - bip_sec_algo    = %u\n", gtk_ofld_info->bip_sec_algo);
727 
728 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gtk_ofld_content:\n");
729 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - akmtype_byte3   = %u\n", gtk_ofld_info->akmtype_byte3);
730 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - kck_len         = %u\n", gtk_ofld_info->gtk_ofld_content.kck_len);
731 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - kek_len         = %u\n", gtk_ofld_info->gtk_ofld_content.kek_len);
732 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - replay_cnt      = 0x%x%x\n",
733 						*((u32 *)(gtk_ofld_info->gtk_ofld_content.replay_cnt)+1),
734 						*((u32 *)(gtk_ofld_info->gtk_ofld_content.replay_cnt)));
735 
736 			if(info->ieee80211w_en) {
737 				gtk_ofld_info->hw_11w_en = true;
738 				PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - igtk_keyid      = 0x%x\n",
739 								*((u32 *)(gtk_ofld_info->gtk_ofld_content.igtk_keyid)));
740 				PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - ipn             = 0x%x%x\n",
741 								*((u32 *)(gtk_ofld_info->gtk_ofld_content.ipn)+1),
742 								*((u32 *)(gtk_ofld_info->gtk_ofld_content.ipn)));
743 				PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - igtk_len        = %u\n", gtk_ofld_info->gtk_ofld_content.igtk_len);
744 				PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - psk_len         = %u\n", gtk_ofld_info->gtk_ofld_content.psk_len);
745 			}
746 		} else {
747 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gtk_ofld_info:\n");
748 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - gtk_en          = %u\n", gtk_ofld_info->gtk_en);
749 		}
750 	}
751 
752 	FUNCOUT();
753 
754 	return phl_status;
755 }
756 
rtw_phl_cfg_realwow_info(void * phl,struct rtw_realwow_info * info)757 enum rtw_phl_status rtw_phl_cfg_realwow_info(void *phl, struct rtw_realwow_info *info)
758 {
759 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
760 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
761 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
762 	struct rtw_realwow_info *realwow_info = &wow_info->realwow_info;
763 	void *d = phl_to_drvpriv(phl_info);
764 
765 	if (info == NULL || realwow_info == NULL) {
766 		PHL_TRACE(COMP_PHL_WOW, _PHL_WARNING_, "[wow] %s(): some ptr is NULL\n", __func__);
767 		phl_status = RTW_PHL_STATUS_FAILURE;
768 
769 	} else {
770 		_os_mem_set(d, realwow_info, 0, sizeof(struct rtw_realwow_info));
771 
772 		PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] realwow_en(%u), continue to realwow_ofld.\n",
773 					info->realwow_en);
774 
775 		if (info->realwow_en) {
776 			_os_mem_cpy(d, realwow_info, info, sizeof(struct rtw_realwow_info));
777 
778 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] realwow_ofld_info:\n");
779 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - realwow_en 		= %u\n",
780 						realwow_info->realwow_en);
781 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - tkip_en			= %u\n",
782 						realwow_info->auto_wakeup);
783 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - interval			= %u\n",
784 						realwow_info->realwow_ofld_content.interval);
785 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - kapktsize			= %u\n",
786 						realwow_info->realwow_ofld_content.keep_alive_pkt_size);
787 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - acklostlimit		= %u\n",
788 						realwow_info->realwow_ofld_content.ack_lost_limit);
789 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - ackpatternsize		= %u\n",
790 						realwow_info->realwow_ofld_content.ack_ptrn_size);
791 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - wakeuppatternsize	= %u\n",
792 						realwow_info->realwow_ofld_content.wakeup_ptrn_size);
793 		} else {
794 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] realwow_ofld_info:\n");
795 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] - realwow_en		= %u\n",
796 						realwow_info->realwow_en);
797 		}
798 	}
799 
800 	return phl_status;
801 }
802 
rtw_phl_cfg_wow_wake(void * phl,struct rtw_wow_wake_info * info)803 enum rtw_phl_status rtw_phl_cfg_wow_wake(void *phl, struct rtw_wow_wake_info *info)
804 {
805 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
806 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
807 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
808 	void *d = phl_to_drvpriv(phl_info);
809 
810 	struct rtw_wow_wake_info *wow_wake_info = &wow_info->wow_wake_info;
811 
812 	FUNCIN();
813 
814 	wow_wake_info->wow_en = info->wow_en;
815 	wow_wake_info->drop_all_pkt = info->drop_all_pkt;
816 	wow_wake_info->rx_parse_after_wake = info->rx_parse_after_wake;
817 	wow_wake_info->pairwise_sec_algo = info->pairwise_sec_algo;
818 	wow_wake_info->group_sec_algo = info->group_sec_algo;
819 	wow_wake_info->pattern_match_en = info->pattern_match_en;
820 	wow_wake_info->magic_pkt_en = info->magic_pkt_en;
821 	wow_wake_info->hw_unicast_en = info->hw_unicast_en;
822 	wow_wake_info->fw_unicast_en = info->fw_unicast_en;
823 	wow_wake_info->deauth_wakeup = info->deauth_wakeup;
824 	wow_wake_info->rekey_wakeup = info->rekey_wakeup;
825 	wow_wake_info->eap_wakeup = info->eap_wakeup;
826 	wow_wake_info->all_data_wakeup = info->all_data_wakeup;
827 	_os_mem_cpy(d, &wow_wake_info->remote_wake_ctrl_info,
828 		&info->remote_wake_ctrl_info, sizeof(struct rtw_remote_wake_ctrl_info));
829 
830 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] wow_en %d\n", wow_wake_info->wow_en);
831 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] drop_all_pkt %d\n", wow_wake_info->drop_all_pkt);
832 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rx_parse_after_wake %d\n", wow_wake_info->rx_parse_after_wake);
833 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] pairwise_sec_algo %d\n", wow_wake_info->pairwise_sec_algo);
834 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] group_sec_algo %d\n", wow_wake_info->group_sec_algo);
835 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] bip_sec_algo %d\n", wow_wake_info->bip_sec_algo);
836 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] pattern_match_en %d\n", wow_wake_info->pattern_match_en);
837 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] magic_pkt_en %d\n", wow_wake_info->magic_pkt_en);
838 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] hw_unicast_en %d\n", wow_wake_info->hw_unicast_en);
839 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] fw_unicast_en %d\n", wow_wake_info->fw_unicast_en);
840 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] deauth_wakeup %d\n", wow_wake_info->deauth_wakeup);
841 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rekey_wakeup %d\n", wow_wake_info->rekey_wakeup);
842 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] eap_wakeup %d\n", wow_wake_info->eap_wakeup);
843 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] all_data_wakeup %d\n", wow_wake_info->all_data_wakeup);
844 
845 	return phl_status;
846 }
847 
rtw_phl_cfg_gpio_wake_pulse(void * phl,struct rtw_wow_gpio_info * info)848 enum rtw_phl_status rtw_phl_cfg_gpio_wake_pulse(void *phl, struct rtw_wow_gpio_info *info)
849 {
850 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
851 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
852 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
853 	struct rtw_wow_gpio_info *wow_gpio = &wow_info->wow_gpio;
854 	void *drv_priv = phl_to_drvpriv(phl_info);
855 	struct rtw_dev2hst_gpio_info *d2h_gpio_info = &wow_gpio->d2h_gpio_info;
856 
857 	FUNCIN();
858 
859 	_os_mem_cpy(drv_priv, d2h_gpio_info, &info->d2h_gpio_info,
860 		    sizeof(struct rtw_dev2hst_gpio_info));
861 	wow_gpio->dev2hst_gpio_mode = info->dev2hst_gpio_mode;
862 	wow_gpio->dev2hst_gpio = info->dev2hst_gpio;
863 	wow_gpio->dev2hst_high = info->dev2hst_high;
864 
865 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] dev2hst_gpio_en %d\n", d2h_gpio_info->dev2hst_gpio_en);
866 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] disable_inband %d\n", d2h_gpio_info->disable_inband);
867 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_output_input %d\n", d2h_gpio_info->gpio_output_input);
868 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_active %d\n", d2h_gpio_info->gpio_active);
869 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] toggle_pulse %d\n", d2h_gpio_info->toggle_pulse);
870 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] data_pin_wakeup %d\n", d2h_gpio_info->data_pin_wakeup);
871 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_nonstop %d\n", d2h_gpio_info->gpio_pulse_nonstop);
872 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_time_unit %d\n", d2h_gpio_info->gpio_time_unit);
873 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_num %d\n", d2h_gpio_info->gpio_num);
874 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_dura %d\n", d2h_gpio_info->gpio_pulse_dura);
875 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_period %d\n", d2h_gpio_info->gpio_pulse_period);
876 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_count %d\n", d2h_gpio_info->gpio_pulse_count);
877 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] customer_id %d\n", d2h_gpio_info->customer_id);
878 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rsn_a_en %d\n", d2h_gpio_info->rsn_a_en);
879 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rsn_a_time_unit %d\n", d2h_gpio_info->rsn_a_time_unit);
880 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rsn_a_pulse_nonstop %d\n", d2h_gpio_info->rsn_a_pulse_nonstop);
881 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rsn_a %d\n", d2h_gpio_info->rsn_a);
882 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rsn_a_pulse_duration %d\n", d2h_gpio_info->rsn_a_pulse_duration);
883 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] rsn_a_pulse_count %d\n", d2h_gpio_info->rsn_a_pulse_count);
884 
885 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] dev2hst_gpio_mode %d\n", wow_gpio->dev2hst_gpio_mode);
886 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] dev2hst_gpio %d\n", wow_gpio->dev2hst_gpio);
887 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] dev2hst_high %d\n", wow_gpio->dev2hst_high);
888 
889 	return phl_status;
890 }
891 
phl_record_wow_stat(struct phl_wow_info * wow_info)892 void phl_record_wow_stat(struct phl_wow_info *wow_info)
893 {
894 	struct phl_wow_stat *wow_stat = &wow_info->wow_stat;
895 
896 	/* init */
897 	wow_stat->func_en = wow_info->func_en;
898 	wow_stat->op_mode = wow_info->op_mode;
899 	wow_stat->keep_alive_en = wow_info->keep_alive_info.keep_alive_en;
900 	wow_stat->disc_det_en = wow_info->disc_det_info.disc_det_en;
901 	wow_stat->arp_en = wow_info->arp_ofld_info.arp_en;
902 	wow_stat->ndp_en = wow_info->ndp_ofld_info.ndp_en;
903 	wow_stat->gtk_en = wow_info->gtk_ofld_info.gtk_en;
904 	wow_stat->dot11w_en = wow_info->gtk_ofld_info.ieee80211w_en;
905 	wow_stat->err.init = wow_info->err.init;
906 	/* deinit */
907 	wow_stat->mac_pwr = wow_info->mac_pwr;
908 	wow_stat->wake_rsn = wow_info->wake_rsn;
909 	wow_stat->err.deinit = wow_info->err.deinit;
910 
911 	if (wow_info->aoac_info.rpt_fail)
912 		++wow_stat->aoac_rpt_fail_cnt;
913 }
914 
915 #ifdef CONFIG_PCI_HCI
_init_precfg(struct phl_info_t * phl_info,u8 band)916 enum rtw_phl_status _init_precfg(struct phl_info_t *phl_info, u8 band)
917 {
918 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
919 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
920 	u8 status = false;
921 
922 	do {
923 		/* 1. stop Tx DMA */
924 		rtw_hal_wow_cfg_txdma(phl_info->hal, false);
925 
926 		/* 2. stop HW Tx */
927 		hstatus = rtw_hal_wow_drop_tx(phl_info->hal, band);
928 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
929 			PHL_ERR("[wow] rtw_hal_wow_drop_tx fail!\n");
930 			break;
931 		}
932 
933 		/* 3. poll dma idle */
934 		status = rtw_hal_poll_txdma_idle(phl_info->hal);
935 		if (!status) {
936 			PHL_ERR("[wow] rtw_hal_poll_txdma_idle fail!\n");
937 			break;
938 		}
939 
940 	} while (0);
941 
942 	if (RTW_HAL_STATUS_SUCCESS != hstatus)
943 		pstatus = RTW_PHL_STATUS_FAILURE;
944 	else
945 		pstatus = RTW_PHL_STATUS_SUCCESS;
946 
947 	FUNCOUT_WSTS(pstatus);
948 
949 	return pstatus;
950 }
_init_postcfg(struct phl_info_t * phl_info)951 enum rtw_phl_status _init_postcfg(struct phl_info_t *phl_info)
952 {
953 	/* stop tx/rx hci */
954 	rtw_hal_cfg_txhci(phl_info->hal, false);
955 	rtw_hal_cfg_rxhci(phl_info->hal, false);
956 
957 	rtw_hal_poll_txdma_idle(phl_info->hal);
958 
959 	return RTW_PHL_STATUS_SUCCESS;
960 }
961 #elif defined(CONFIG_USB_HCI)
_init_precfg(struct phl_info_t * phl_info,u8 band)962 enum rtw_phl_status _init_precfg(struct phl_info_t *phl_info, u8 band)
963 {
964 	return RTW_PHL_STATUS_SUCCESS;
965 }
_init_postcfg(struct phl_info_t * phl_info)966 enum rtw_phl_status _init_postcfg(struct phl_info_t *phl_info)
967 {
968 	return RTW_PHL_STATUS_SUCCESS;
969 }
970 
971 #elif defined(CONFIG_SDIO_HCI)
_init_precfg(struct phl_info_t * phl_info,u8 band)972 enum rtw_phl_status _init_precfg(struct phl_info_t *phl_info, u8 band)
973 {
974 	return RTW_PHL_STATUS_SUCCESS;
975 }
_init_postcfg(struct phl_info_t * phl_info)976 enum rtw_phl_status _init_postcfg(struct phl_info_t *phl_info)
977 {
978 	return RTW_PHL_STATUS_SUCCESS;
979 }
980 
981 #endif
982 
_init_precfg_set_rxfltr(struct phl_info_t * phl_info)983 static enum rtw_phl_status _init_precfg_set_rxfltr(struct phl_info_t *phl_info)
984 {
985 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
986 
987 	do {
988 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_DATA, 0);
989 	 	if (RTW_HAL_STATUS_SUCCESS != hstatus) {
990 			PHL_ERR("[wow] set rx filter data drop fail, status(%u)\n", hstatus);
991 			break;
992 		}
993 
994 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_MGNT, 0);
995 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
996 			PHL_ERR("[wow] set rx filter mgnt drop fail, status(%u)\n", hstatus);
997 			break;
998 		}
999 
1000 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_CTRL, 0);
1001 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1002 			PHL_ERR("[wow] set rx filter ctrl drop fail, status(%u)\n", hstatus);
1003 			break;
1004 		}
1005 	} while (0);
1006 
1007 	return (hstatus == RTW_HAL_STATUS_SUCCESS) ?
1008 			RTW_PHL_STATUS_SUCCESS : RTW_PHL_STATUS_FAILURE;
1009 }
1010 
_init_postcfg_set_rxfltr(struct phl_info_t * phl_info)1011 static enum rtw_phl_status _init_postcfg_set_rxfltr(struct phl_info_t *phl_info)
1012 {
1013 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1014 
1015 	do {
1016 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_DATA, 1);
1017 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1018 			PHL_ERR("[wow] set rx filter data to host fail, status(%u)\n", hstatus);
1019 			break;
1020 		}
1021 
1022 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_MGNT, 1);
1023 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1024 			PHL_ERR("[wow] set rx filter mgnt to host fail, status(%u)\n", hstatus);
1025 			break;
1026 		}
1027 
1028 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_CTRL, 1);
1029 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1030 			PHL_ERR("[wow] set rx filter ctrl to host fail, status(%u)\n", hstatus);
1031 			break;
1032 		}
1033 	} while (0);
1034 
1035 	return (hstatus == RTW_HAL_STATUS_SUCCESS) ?
1036 			RTW_PHL_STATUS_SUCCESS : RTW_PHL_STATUS_FAILURE;
1037 }
1038 
1039 #define MAX_POLLING_TRX_STOP 2000 /* us */
phl_wow_init_precfg(struct phl_wow_info * wow_info)1040 enum rtw_phl_status phl_wow_init_precfg(struct phl_wow_info *wow_info)
1041 {
1042 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1043 	struct phl_info_t *phl_info = wow_info->phl_info;
1044 	struct phl_hci_trx_ops *trx_ops = phl_info->hci_trx_ops;
1045 	u32 wait_cnt = 0;
1046 
1047 	FUNCIN();
1048 
1049 	/* pause sw Tx */
1050 	trx_ops->req_tx_stop(phl_info);
1051 
1052 	/* schedule current existing tx handler */
1053 	pstatus = rtw_phl_tx_req_notify(phl_info);
1054 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1055 		PHL_ERR("[wow] rtw_phl_tx_req_notify fail, status(%u)\n", pstatus);
1056 
1057 	/* polling pause sw Tx done */
1058 	while (wait_cnt < MAX_POLLING_TRX_STOP) {
1059 		if (trx_ops->is_tx_pause(phl_info)) {
1060 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] sw tx pause succeed.\n");
1061 			break;
1062 		}
1063 		_os_delay_us(phl_info->phl_com->drv_priv, 1);
1064 		wait_cnt++;
1065 	}
1066 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] stop sw tx wait_cnt %d.\n", wait_cnt);
1067 
1068 	/* init pre-configuration for different interfaces */
1069 	pstatus = _init_precfg(phl_info, wow_info->sta->wrole->hw_band);
1070 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1071 		return pstatus;
1072 
1073 	/* set packet drop by setting rx filter */
1074 	pstatus = _init_precfg_set_rxfltr(phl_info);
1075 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1076 		return pstatus;
1077 
1078 	/* disable ppdu sts */
1079 	rtw_hal_ppdu_sts_cfg(phl_info->hal, wow_info->sta->wrole->hw_band, false);
1080 
1081 	pstatus = RTW_PHL_STATUS_SUCCESS;
1082 
1083 	return pstatus;
1084 }
1085 
phl_wow_init_postcfg(struct phl_wow_info * wow_info)1086 enum rtw_phl_status phl_wow_init_postcfg(struct phl_wow_info *wow_info)
1087 {
1088 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1089 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1090 	struct phl_info_t *phl_info = wow_info->phl_info;
1091 	struct phl_hci_trx_ops *trx_ops = phl_info->hci_trx_ops;
1092 	struct rtw_phl_stainfo_t *sta = wow_info->sta;
1093 	u32 wait_cnt = 0;
1094 #ifdef CONFIG_SYNC_INTERRUPT
1095 	struct rtw_phl_evt_ops *evt_ops = &phl_info->phl_com->evt_ops;
1096 #endif /* CONFIG_SYNC_INTERRUPT */
1097 
1098 	/* disable interrupt */
1099 #ifdef CONFIG_SYNC_INTERRUPT
1100 	evt_ops->set_interrupt_caps(phl_to_drvpriv(phl_info), false);
1101 #else
1102 	rtw_hal_disable_interrupt(phl_info->phl_com, phl_info->hal);
1103 #endif /* CONFIG_SYNC_INTERRUPT */
1104 
1105 	pstatus = _init_postcfg(phl_info);
1106 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1107 		PHL_ERR("[wow] _init_postcfg failed.\n");
1108 
1109 	/* stop sw rx */
1110 	trx_ops->req_rx_stop(phl_info);
1111 	pstatus = rtw_phl_start_rx_process(phl_info);
1112 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1113 		PHL_ERR("[wow] rtw_phl_start_rx_process failed.\n");
1114 
1115 	while (wait_cnt < MAX_POLLING_TRX_STOP) {
1116 		if (trx_ops->is_rx_pause(phl_info)) {
1117 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] sw rx pause succeed.\n");
1118 			break;
1119 		}
1120 		_os_delay_us(phl_info->phl_com->drv_priv, 1);
1121 		wait_cnt++;
1122 	}
1123 
1124 	if (wait_cnt == MAX_POLLING_TRX_STOP)
1125 		PHL_WARN("[wow] sw rx pause fail.\n");
1126 
1127 	/* configure wow sleep */
1128 	hstatus = rtw_hal_cfg_wow_sleep(phl_info->hal, true);
1129 	if (RTW_HAL_STATUS_SUCCESS != hstatus)
1130 		return RTW_PHL_STATUS_FAILURE;
1131 
1132 	/* forward rx packet to host by setting rx filter */
1133 	pstatus = _init_postcfg_set_rxfltr(phl_info);
1134 
1135 	/* reset trx */
1136 #ifdef CONFIG_USB_HCI
1137 	trx_ops->trx_stop(phl_info);
1138 #else
1139 	trx_ops->trx_reset(phl_info, PHL_CTRL_TX | PHL_CTRL_RX);
1140 #endif
1141 
1142 
1143 	/* notify reorder sleep */
1144 	phl_notify_reorder_sleep(phl_info, sta);
1145 	return pstatus;
1146 }
1147 
_phl_indic_wake_sec_upd(struct phl_wow_info * wow_info,u8 aoac_report_get_ok,u8 rx_ready)1148 static void _phl_indic_wake_sec_upd(struct phl_wow_info *wow_info, u8 aoac_report_get_ok, u8 rx_ready)
1149 {
1150 	struct phl_info_t *phl_info = wow_info->phl_info;
1151 	struct rtw_phl_evt_ops *ops = &phl_info->phl_com->evt_ops;
1152 	void *drv_priv = phl_to_drvpriv(phl_info);
1153 
1154 	if (NULL != ops->wow_handle_sec_info_update)
1155 		ops->wow_handle_sec_info_update(drv_priv, &wow_info->aoac_info, aoac_report_get_ok, rx_ready);
1156 	else
1157 		PHL_TRACE(COMP_PHL_WOW, _PHL_ERR_, "[wow] %s : evt_ops->wow_handle_sec_info_update is NULL.\n"
1158 			, __func__);
1159 }
1160 
_phl_handle_aoac_rpt_action(struct phl_wow_info * wow_info,bool rx_ready)1161 static void _phl_handle_aoac_rpt_action(struct phl_wow_info *wow_info, bool rx_ready)
1162 {
1163 	struct phl_info_t *phl_info = wow_info->phl_info;
1164 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1165 	u8 aoac_report_get_ok = false;
1166 	static u8 phase_0_ok = false;
1167 
1168 	if (wow_info->wow_wake_info.pairwise_sec_algo) {
1169 		if (rx_ready == false) {
1170 			/* phase 0 */
1171 			hstatus = rtw_hal_get_wow_aoac_rpt(phl_info->hal, &wow_info->aoac_info, rx_ready);
1172 			aoac_report_get_ok = (hstatus == RTW_HAL_STATUS_SUCCESS) ? true : false;
1173 			_phl_indic_wake_sec_upd(wow_info, aoac_report_get_ok, rx_ready);
1174 
1175 			phase_0_ok = aoac_report_get_ok;
1176 		}
1177 
1178 		if (rx_ready == true) {
1179 			/* phase 1 */
1180 			if (phase_0_ok) {
1181 				hstatus = rtw_hal_get_wow_aoac_rpt(phl_info->hal, &wow_info->aoac_info, rx_ready);
1182 				aoac_report_get_ok = (hstatus == RTW_HAL_STATUS_SUCCESS) ? true : false;
1183 				_phl_indic_wake_sec_upd(wow_info, aoac_report_get_ok, rx_ready);
1184 			}
1185 
1186 			phase_0_ok = false;
1187 
1188 			wow_info->aoac_info.rpt_fail = (aoac_report_get_ok == false) ? true : false;
1189 		}
1190 	}
1191 }
1192 
_phl_indic_wake_rsn(struct phl_wow_info * wow_info)1193 static enum rtw_phl_status _phl_indic_wake_rsn(struct phl_wow_info *wow_info)
1194 {
1195 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1196 	struct phl_info_t *phl_info = wow_info->phl_info;
1197 	struct rtw_phl_evt_ops *evt_ops = &(phl_info->phl_com->evt_ops);
1198 
1199 	FUNCIN_WSTS(phl_status);
1200 
1201 	if (NULL != evt_ops->indicate_wake_rsn) {
1202 		evt_ops->indicate_wake_rsn(phl_to_drvpriv(phl_info), wow_info->wake_rsn);
1203 	}
1204 
1205 	FUNCOUT_WSTS(phl_status);
1206 
1207 	return phl_status;
1208 }
1209 
phl_wow_handle_wake_rsn(struct phl_wow_info * wow_info,u8 * reset)1210 void phl_wow_handle_wake_rsn(struct phl_wow_info *wow_info, u8 *reset)
1211 {
1212 	struct phl_info_t *phl_info = wow_info->phl_info;
1213 
1214 	rtw_hal_get_wake_rsn(phl_info->hal, &wow_info->wake_rsn, reset);
1215 	_phl_indic_wake_rsn(wow_info);
1216 }
1217 
1218 #ifdef CONFIG_PCI_HCI
_deinit_precfg(struct phl_info_t * phl_info)1219 enum rtw_phl_status _deinit_precfg(struct phl_info_t *phl_info)
1220 {
1221 #ifdef DBG_RST_BDRAM_TIME
1222 	u32 rst_bdram_start = _os_get_cur_time_ms();
1223 #endif /* DBG_RST_BDRAM_TIME */
1224 
1225 	rtw_hal_clear_bdidx(phl_info->hal);
1226 
1227 #ifdef DBG_RST_BDRAM_TIME
1228 	rst_bdram_start = _os_get_cur_time_ms();
1229 #endif
1230 	rtw_hal_rst_bdram(phl_info->hal);
1231 
1232 #ifdef DBG_RST_BDRAM_TIME
1233 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : Reset bdram takes %u (ms).\n"
1234 		, __func__, phl_get_passing_time_ms(rst_bdram_start));
1235 #endif
1236 
1237 	rtw_hal_cfg_txhci(phl_info->hal, true);
1238 	rtw_hal_cfg_rxhci(phl_info->hal, true);
1239 
1240 	/* start tx dma */
1241 	rtw_hal_wow_cfg_txdma(phl_info->hal, true);
1242 
1243 	return RTW_PHL_STATUS_SUCCESS;
1244 }
1245 #elif defined(CONFIG_USB_HCI)
_deinit_precfg(struct phl_info_t * phl_info)1246 enum rtw_phl_status _deinit_precfg(struct phl_info_t *phl_info)
1247 {
1248 	return RTW_PHL_STATUS_SUCCESS;
1249 }
1250 #elif defined(CONFIG_SDIO_HCI)
_deinit_precfg(struct phl_info_t * phl_info)1251 enum rtw_phl_status _deinit_precfg(struct phl_info_t *phl_info)
1252 {
1253 	return RTW_PHL_STATUS_SUCCESS;
1254 }
1255 #endif
1256 
_deinit_precfg_set_intr(struct phl_info_t * phl_info)1257 void _deinit_precfg_set_intr(struct phl_info_t *phl_info)
1258 {
1259 #ifdef CONFIG_SYNC_INTERRUPT
1260 	struct rtw_phl_evt_ops *evt_ops = &phl_info->phl_com->evt_ops;
1261 #endif /* CONFIG_SYNC_INTERRUPT */
1262 
1263 	rtw_hal_set_default_var(phl_info->hal, SET_DEF_RSN_WOW_RESUME_HNDL_RX);
1264 #ifdef CONFIG_SYNC_INTERRUPT
1265 	evt_ops->set_interrupt_caps(phl_to_drvpriv(phl_info), true);
1266 #else
1267 	rtw_hal_enable_interrupt(phl_info->phl_com, phl_info->hal);
1268 #endif /* CONFIG_SYNC_INTERRUPT */
1269 }
1270 
phl_wow_deinit_precfg(struct phl_wow_info * wow_info)1271 enum rtw_phl_status phl_wow_deinit_precfg(struct phl_wow_info *wow_info)
1272 {
1273 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1274 	struct phl_info_t *phl_info = wow_info->phl_info;
1275 	struct phl_hci_trx_ops *trx_ops = phl_info->hci_trx_ops;
1276 
1277 	FUNCIN();
1278 
1279 	_deinit_precfg(phl_info);
1280 
1281 	rtw_hal_cfg_wow_sleep(phl_info->hal, false);
1282 
1283 	_phl_handle_aoac_rpt_action(wow_info, false);
1284 
1285 	/* resume sw rx */
1286 #ifdef CONFIG_USB_HCI
1287 	trx_ops->trx_cfg(phl_info);
1288 #else
1289 	trx_ops->trx_resume(phl_info, PHL_CTRL_RX);
1290 #endif
1291 
1292 	_deinit_precfg_set_intr(phl_info);
1293 
1294 	_phl_handle_aoac_rpt_action(wow_info, true);
1295 
1296 	return phl_status;
1297 }
1298 
phl_reset_wow_info(struct phl_wow_info * wow_info)1299 void phl_reset_wow_info(struct phl_wow_info *wow_info)
1300 {
1301 	struct phl_info_t *phl_info = wow_info->phl_info;
1302 	void *d = phl_to_drvpriv(phl_info);
1303 
1304 	wow_info->func_en = 0;
1305 	wow_info->op_mode = RTW_WOW_OP_NONE;
1306 	wow_info->mac_pwr = RTW_MAC_PWR_NONE;
1307 	wow_info->ps_pwr_lvl = PS_PWR_LVL_PWRON;
1308 
1309 	_os_mem_set(d, &wow_info->err, 0, sizeof(struct phl_wow_error));
1310 	_os_mem_set(d, &wow_info->keep_alive_info, 0, sizeof(struct rtw_keep_alive_info));
1311 	_os_mem_set(d, &wow_info->disc_det_info, 0, sizeof(struct rtw_disc_det_info));
1312 	_os_mem_set(d, &wow_info->nlo_info, 0, sizeof(struct rtw_nlo_info));
1313 	_os_mem_set(d, &wow_info->arp_ofld_info, 0, sizeof(struct rtw_arp_ofld_info));
1314 	_os_mem_set(d, &wow_info->ndp_ofld_info, 0, sizeof(struct rtw_ndp_ofld_info));
1315 	_os_mem_set(d, &wow_info->gtk_ofld_info, 0, sizeof(struct rtw_gtk_ofld_info));
1316 	_os_mem_set(d, &wow_info->realwow_info, 0, sizeof(struct rtw_realwow_info));
1317 	_os_mem_set(d, &wow_info->wow_wake_info, 0, sizeof(struct rtw_wow_wake_info));
1318 	_os_mem_set(d, &wow_info->aoac_info, 0, sizeof(struct rtw_aoac_report));
1319 
1320 	wow_info->wake_rsn = RTW_WOW_RSN_UNKNOWN;
1321 
1322 	/*
1323 		&wow_info->pattern_match_info need not to be reset here.
1324 		We expect those items will be remove triggered by core layer
1325 	*/
1326 }
1327 
_deinit_postcfg_set_intr(struct phl_info_t * phl_info)1328 void _deinit_postcfg_set_intr(struct phl_info_t *phl_info)
1329 {
1330 #ifdef CONFIG_SYNC_INTERRUPT
1331 	struct rtw_phl_evt_ops *evt_ops = &phl_info->phl_com->evt_ops;
1332 #endif /* CONFIG_SYNC_INTERRUPT */
1333 
1334 #ifdef CONFIG_SYNC_INTERRUPT
1335 	evt_ops->set_interrupt_caps(phl_to_drvpriv(phl_info), false);
1336 #else
1337 	rtw_hal_disable_interrupt(phl_info->phl_com, phl_info->hal);
1338 #endif /* CONFIG_SYNC_INTERRUPT */
1339 	rtw_hal_set_default_var(phl_info->hal, SET_DEF_RSN_WOW_RESUME_DONE);
1340 #ifdef CONFIG_SYNC_INTERRUPT
1341 	evt_ops->set_interrupt_caps(phl_to_drvpriv(phl_info), true);
1342 #else
1343 	rtw_hal_enable_interrupt(phl_info->phl_com, phl_info->hal);
1344 #endif /* CONFIG_SYNC_INTERRUPT */
1345 }
1346 
phl_wow_deinit_postcfg(struct phl_wow_info * wow_info)1347 enum rtw_phl_status phl_wow_deinit_postcfg(struct phl_wow_info *wow_info)
1348 {
1349 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1350 	struct phl_info_t *phl_info = wow_info->phl_info;
1351 	struct phl_hci_trx_ops *trx_ops = phl_info->hci_trx_ops;
1352 
1353 	FUNCIN();
1354 
1355 	/* resume sw tx */
1356 	trx_ops->trx_resume(phl_info, PHL_CTRL_TX);
1357 	/* enable ppdu sts */
1358 	rtw_hal_ppdu_sts_cfg(phl_info->hal, wow_info->sta->wrole->hw_band, true);
1359 
1360 	_deinit_postcfg_set_intr(phl_info);
1361 
1362 	return phl_status;
1363 }
1364 
_phl_wow_cfg_pkt_ofld(struct phl_wow_info * wow_info,u8 pkt_type,u8 * pkt_id,void * buf)1365 enum rtw_phl_status _phl_wow_cfg_pkt_ofld(struct phl_wow_info *wow_info, u8 pkt_type, u8 *pkt_id, void *buf)
1366 {
1367 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1368 	u16 macid = wow_info->sta->macid;
1369 	u32 *token;
1370 
1371 	switch(pkt_type) {
1372 	case PKT_TYPE_NULL_DATA:
1373 		token = &wow_info->null_pkt_token;
1374 		break;
1375 	case PKT_TYPE_ARP_RSP:
1376 		token = &wow_info->arp_pkt_token;
1377 		break;
1378 	case PKT_TYPE_NDP:
1379 		token = &wow_info->ndp_pkt_token;
1380 		break;
1381 	case PKT_TYPE_EAPOL_KEY:
1382 		token = &wow_info->eapol_key_pkt_token;
1383 		break;
1384 	case PKT_TYPE_SA_QUERY:
1385 		token = &wow_info->sa_query_pkt_token;
1386 		break;
1387 	case PKT_TYPE_REALWOW_KAPKT:
1388 		token = &wow_info->kapkt_pkt_token;
1389 		break;
1390 	case PKT_TYPE_REALWOW_ACK:
1391 		token = &wow_info->ack_pkt_token;
1392 		break;
1393 	case PKT_TYPE_REALWOW_WP:
1394 		token = &wow_info->wp_token;
1395 		break;
1396 	case PKT_TYPE_PROBE_REQ:
1397 		token = &wow_info->probe_req_pkt_token;
1398 		break;
1399 	default:
1400 		PHL_TRACE(COMP_PHL_WOW, _PHL_ERR_, "[wow] %s : unknown pkt_type %d.\n"
1401 			, __func__, pkt_type);
1402 		return pstatus;
1403 	}
1404 
1405 	pstatus = RTW_PHL_PKT_OFLD_REQ(wow_info->phl_info, macid, pkt_type, token, buf);
1406 
1407 	if (pstatus == RTW_PHL_STATUS_SUCCESS)
1408 		*pkt_id = phl_pkt_ofld_get_id(wow_info->phl_info, macid, pkt_type);
1409 
1410 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : pkt_type %s, pkt_id %d, token %u, status(%u)\n",
1411 		__func__, phl_get_pkt_ofld_str(pkt_type), *pkt_id, *token, pstatus);
1412 
1413 	return pstatus;
1414 }
1415 
_phl_wow_cfg_nlo(struct phl_wow_info * wow_info)1416 static enum rtw_phl_status _phl_wow_cfg_nlo(struct phl_wow_info *wow_info)
1417 {
1418 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1419 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1420 	struct phl_info_t *phl_info = wow_info->phl_info;
1421 	struct rtw_phl_stainfo_t *sta = wow_info->sta;
1422 
1423 	do {
1424 
1425 		/* always stop first */
1426 		hstatus = rtw_hal_wow_cfg_nlo(phl_info->hal, SCAN_OFLD_OP_STOP,
1427 					sta->macid, sta->wrole->hw_band, sta->wrole->hw_port,
1428 					&wow_info->nlo_info);
1429 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1430 			pstatus = RTW_PHL_STATUS_FAILURE;
1431 			break;
1432 		}
1433 
1434 		/* construct channel list and offload to fw */
1435 		hstatus = rtw_hal_wow_cfg_nlo_chnl_list(phl_info->hal,
1436 					&wow_info->nlo_info);
1437 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1438 			pstatus = RTW_PHL_STATUS_FAILURE;
1439 			break;
1440 		}
1441 
1442 		hstatus = rtw_hal_wow_cfg_nlo(phl_info->hal, SCAN_OFLD_OP_START,
1443 					sta->macid, sta->wrole->hw_band, sta->wrole->hw_port,
1444 					&wow_info->nlo_info);
1445 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1446 			pstatus = RTW_PHL_STATUS_FAILURE;
1447 			break;
1448 		}
1449 
1450 	} while (0);
1451 
1452 	return pstatus;
1453 }
1454 
phl_wow_func_en(struct phl_wow_info * wow_info)1455 enum rtw_phl_status phl_wow_func_en(struct phl_wow_info *wow_info)
1456 {
1457 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1458 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1459 	struct phl_info_t *phl_info = wow_info->phl_info;
1460 	struct rtw_phl_stainfo_t *sta = wow_info->sta;
1461 	struct rtw_pkt_ofld_null_info null_info = {0};
1462 	struct rtw_pkt_ofld_arp_rsp_info arp_rsp_info = {0};
1463 	struct rtw_pkt_ofld_na_info na_info = {0};
1464 	struct rtw_pkt_ofld_eapol_key_info eapol_key_info = {0};
1465 	struct rtw_pkt_ofld_sa_query_info sa_query_info = {0};
1466 	struct rtw_pkt_ofld_realwow_kapkt_info kapkt_info = {0};
1467 	struct rtw_pkt_ofld_realwow_ack_info ack_info = {0};
1468 	struct rtw_pkt_ofld_realwow_wp_info wakeup_info = {0};
1469 	struct rtw_pkt_ofld_probe_req_info probe_req_info = {0};
1470 	struct rtw_hal_wow_cfg cfg;
1471 
1472 	FUNCIN();
1473 
1474 	if (!wow_info->wow_wake_info.wow_en) {
1475 		PHL_WARN("%s : wow func is not enabled!\n", __func__);
1476 		return pstatus;
1477 	}
1478 
1479 	do {
1480 
1481 		hstatus = rtw_hal_reset_pkt_ofld_state(phl_info->hal);
1482 
1483 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1484 			pstatus = RTW_PHL_STATUS_FAILURE;
1485 			break;
1486 		}
1487 
1488 		if (wow_info->keep_alive_info.keep_alive_en) {
1489 
1490 			_phl_cfg_pkt_ofld_null_info(wow_info, sta, &null_info);
1491 
1492 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1493 					PKT_TYPE_NULL_DATA,
1494 					&wow_info->keep_alive_info.null_pkt_id,
1495 					(void *)&null_info);
1496 
1497 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1498 				break;
1499 		}
1500 
1501 		if (wow_info->arp_ofld_info.arp_en) {
1502 
1503 			_phl_cfg_pkt_ofld_arp_rsp_info(wow_info, sta, &arp_rsp_info);
1504 
1505 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1506 					PKT_TYPE_ARP_RSP,
1507 					&wow_info->arp_ofld_info.arp_rsp_id,
1508 					(void *)&arp_rsp_info);
1509 
1510 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1511 				break;
1512 		}
1513 
1514 		if (wow_info->ndp_ofld_info.ndp_en) {
1515 
1516 			_phl_cfg_pkt_ofld_na_info(wow_info, sta, &na_info);
1517 
1518 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1519 					PKT_TYPE_NDP, &wow_info->ndp_ofld_info.ndp_id,
1520 					(void *)&na_info);
1521 
1522 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1523 				break;
1524 		}
1525 
1526 		if (wow_info->gtk_ofld_info.gtk_en) {
1527 			_phl_cfg_pkt_ofld_eapol_key_info(wow_info, sta, &eapol_key_info);
1528 
1529 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1530 					PKT_TYPE_EAPOL_KEY, &wow_info->gtk_ofld_info.gtk_rsp_id,
1531 					(void *)&eapol_key_info);
1532 
1533 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1534 				break;
1535 
1536 			if (wow_info->gtk_ofld_info.ieee80211w_en) {
1537 				_phl_cfg_pkt_ofld_sa_query_info(wow_info, sta, &sa_query_info);
1538 
1539 				pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1540 					PKT_TYPE_SA_QUERY, &wow_info->gtk_ofld_info.sa_query_id,
1541 					(void *)&sa_query_info);
1542 
1543 				if (pstatus != RTW_PHL_STATUS_SUCCESS)
1544 					break;
1545 			}
1546 		}
1547 
1548 		if (wow_info->realwow_info.realwow_en) {
1549 
1550 			/* realwow keep alive */
1551 			_phl_cfg_pkt_ofld_realwow_kapkt_info(wow_info, sta, &kapkt_info);
1552 
1553 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1554 					PKT_TYPE_REALWOW_KAPKT,
1555 					&wow_info->realwow_info.keepalive_id,
1556 					(void *)&kapkt_info);
1557 
1558 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1559 				break;
1560 
1561 			/* realwow ack */
1562 			_phl_cfg_pkt_ofld_realwow_ack_info(wow_info, &ack_info);
1563 
1564 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1565 					PKT_TYPE_REALWOW_ACK,
1566 					&wow_info->realwow_info.ack_pattern_id,
1567 					(void *)&ack_info);
1568 
1569 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1570 				break;
1571 
1572 			/* realwow wake up */
1573 			_phl_cfg_pkt_ofld_realwow_wp_info(wow_info, &wakeup_info);
1574 
1575 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1576 					PKT_TYPE_REALWOW_WP,
1577 					&wow_info->realwow_info.wakeup_pattern_id,
1578 					(void *)&wakeup_info);
1579 
1580 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1581 				break;
1582 		}
1583 
1584 		if (wow_info->nlo_info.nlo_en) {
1585 
1586 			_phl_cfg_pkt_ofld_probe_req_info(wow_info, sta, &probe_req_info);
1587 
1588 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1589 					PKT_TYPE_PROBE_REQ,
1590 					&wow_info->nlo_info.probe_req_id,
1591 					(void *)&probe_req_info);
1592 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1593 				break;
1594 
1595 			pstatus = _phl_wow_cfg_nlo(wow_info);
1596 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1597 				break;
1598 		}
1599 
1600 		cfg.keep_alive_cfg = &wow_info->keep_alive_info;
1601 		cfg.disc_det_cfg = &wow_info->disc_det_info;
1602 		cfg.nlo_cfg = &wow_info->nlo_info;
1603 		cfg.arp_ofld_cfg = &wow_info->arp_ofld_info;
1604 		cfg.ndp_ofld_cfg = &wow_info->ndp_ofld_info;
1605 		cfg.gtk_ofld_cfg = &wow_info->gtk_ofld_info;
1606 		cfg.realwow_cfg = &wow_info->realwow_info;
1607 		cfg.wow_wake_cfg = &wow_info->wow_wake_info;
1608 		cfg.pattern_match_info = &wow_info->pattern_match_info;
1609 		cfg.wow_gpio = &wow_info->wow_gpio;
1610 
1611 		hstatus = rtw_hal_wow_func_en(phl_info->phl_com, phl_info->hal, sta->macid, &cfg);
1612 		if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1613 			PHL_ERR("rtw_hal_wow_func_en fail, status (%u)\n", hstatus);
1614 			pstatus = RTW_PHL_STATUS_FAILURE;
1615 			break;
1616 		}
1617 
1618 		hstatus = rtw_hal_wow_func_start(phl_info->phl_com, phl_info->hal, sta->macid, &cfg);
1619 		if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1620 			PHL_ERR("rtw_hal_wow_func_start fail, status (%u)\n", hstatus);
1621 			pstatus = RTW_PHL_STATUS_FAILURE;
1622 			break;
1623 		}
1624 
1625 		wow_info->func_en = true;
1626 		pstatus = RTW_PHL_STATUS_SUCCESS;
1627 
1628 	} while (0);
1629 
1630 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s status (%u).\n", __func__, pstatus);
1631 
1632 	return pstatus;
1633 }
1634 
phl_wow_func_dis(struct phl_wow_info * wow_info)1635 void phl_wow_func_dis(struct phl_wow_info *wow_info)
1636 {
1637 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1638 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1639 	struct phl_info_t *phl_info = wow_info->phl_info;
1640 	struct rtw_phl_stainfo_t *sta = wow_info->sta;
1641 	struct rtw_hal_wow_cfg cfg;
1642 
1643 	if (!wow_info->wow_wake_info.wow_en) {
1644 		PHL_WARN("%s : wow func is not enabled!\n", __func__);
1645 		return;
1646 	}
1647 
1648 	cfg.keep_alive_cfg = &wow_info->keep_alive_info;
1649 	cfg.disc_det_cfg = &wow_info->disc_det_info;
1650 	cfg.nlo_cfg = &wow_info->nlo_info;
1651 	cfg.arp_ofld_cfg = &wow_info->arp_ofld_info;
1652 	cfg.ndp_ofld_cfg = &wow_info->ndp_ofld_info;
1653 	cfg.gtk_ofld_cfg = &wow_info->gtk_ofld_info;
1654 	cfg.realwow_cfg = &wow_info->realwow_info;
1655 	cfg.wow_wake_cfg = &wow_info->wow_wake_info;
1656 	cfg.pattern_match_info = &wow_info->pattern_match_info;
1657 	cfg.wow_gpio = &wow_info->wow_gpio;
1658 
1659 	hstatus = rtw_hal_wow_func_dis(phl_info->phl_com, phl_info->hal, sta->macid,
1660 		&cfg);
1661 	if (hstatus != RTW_HAL_STATUS_SUCCESS)
1662 		PHL_ERR("rtw_hal_wow_func_dis fail, status (%u)\n", hstatus);
1663 
1664 	if (wow_info->keep_alive_info.keep_alive_en) {
1665 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1666 							PKT_TYPE_NULL_DATA, &wow_info->null_pkt_token);
1667 	}
1668 
1669 	if (wow_info->arp_ofld_info.arp_en) {
1670 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1671 							PKT_TYPE_ARP_RSP, &wow_info->arp_pkt_token);
1672 	}
1673 
1674 	if (wow_info->ndp_ofld_info.ndp_en) {
1675 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1676 							PKT_TYPE_NDP, &wow_info->ndp_pkt_token);
1677 	}
1678 
1679 	if (wow_info->gtk_ofld_info.gtk_en) {
1680 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1681 							PKT_TYPE_EAPOL_KEY, &wow_info->eapol_key_pkt_token);
1682 		if (wow_info->gtk_ofld_info.ieee80211w_en) {
1683 			phl_pkt_ofld_cancel(phl_info, sta->macid,
1684 								PKT_TYPE_SA_QUERY, &wow_info->sa_query_pkt_token);
1685 		}
1686 	}
1687 
1688 	if (wow_info->realwow_info.realwow_en) {
1689 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1690 					PKT_TYPE_REALWOW_KAPKT, &wow_info->kapkt_pkt_token);
1691 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1692 					PKT_TYPE_REALWOW_ACK, &wow_info->ack_pkt_token);
1693 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1694 					PKT_TYPE_REALWOW_WP, &wow_info->wp_token);
1695 	}
1696 
1697 	if (wow_info->nlo_info.nlo_en) {
1698 
1699 		pstatus = phl_pkt_ofld_cancel(phl_info, sta->macid,
1700 					PKT_TYPE_PROBE_REQ, &wow_info->probe_req_pkt_token);
1701 
1702 		hstatus = rtw_hal_wow_cfg_nlo(phl_info->hal, SCAN_OFLD_OP_STOP,
1703 						sta->macid, sta->wrole->hw_band, sta->wrole->hw_port,
1704 						&wow_info->nlo_info);
1705 	}
1706 
1707 
1708 	hstatus = rtw_hal_wow_func_stop(phl_info->phl_com, phl_info->hal, sta->macid);
1709 	if (hstatus != RTW_HAL_STATUS_SUCCESS)
1710 		PHL_ERR("rtw_hal_wow_func_stop fail, status (%u)\n", hstatus);
1711 
1712 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s done.\n", __func__);
1713 }
1714 
phl_wow_decide_op_mode(struct phl_wow_info * wow_info,struct rtw_phl_stainfo_t * sta)1715 void phl_wow_decide_op_mode(struct phl_wow_info *wow_info, struct rtw_phl_stainfo_t *sta)
1716 {
1717 	u8 nlo_en = wow_info->nlo_info.nlo_en;
1718 	enum mlme_state mstat = sta->wrole->mstate;
1719 	struct rtw_ps_cap_t *ps_cap = _get_ps_cap(wow_info->phl_info);
1720 
1721 	wow_info->sta = sta;
1722 	wow_info->ps_pwr_lvl = PS_PWR_LVL_PWRON;
1723 
1724 	if (mstat == MLME_NO_LINK && !nlo_en) {
1725 		wow_info->op_mode = RTW_WOW_OP_PWR_DOWN;
1726 	} else if (mstat == MLME_NO_LINK && nlo_en) {
1727 		wow_info->op_mode = RTW_WOW_OP_DISCONNECT_STBY;
1728 		#ifdef CONFIG_POWER_SAVE
1729 		if (ps_cap->ips_wow_en)
1730 			wow_info->ps_pwr_lvl = phl_ps_judge_pwr_lvl(ps_cap->ips_wow_cap, PS_MODE_IPS, true);
1731 		#endif
1732 	} else if (mstat == MLME_LINKED) {
1733 		wow_info->op_mode = RTW_WOW_OP_CONNECT_STBY;
1734 		#ifdef CONFIG_POWER_SAVE
1735 		if (ps_cap->lps_wow_en)
1736 			wow_info->ps_pwr_lvl = phl_ps_judge_pwr_lvl(ps_cap->lps_wow_cap, PS_MODE_LPS, true);
1737 		#endif
1738 	} else {
1739 		wow_info->op_mode = RTW_WOW_OP_PWR_DOWN;
1740 	}
1741 
1742 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s op mode set to %d, pwr lvl %s.\n.",
1743 			  __func__, wow_info->op_mode, phl_ps_pwr_lvl_to_str(wow_info->ps_pwr_lvl));
1744 }
1745 
1746 #ifdef CONFIG_POWER_SAVE
1747 /**
1748  * phl_wow_ps_proto_cfg - set the ps protocol under wowlan
1749  * @wow_info: see struct phl_wow_info
1750  * @enter_ps: enter lps or not
1751  *
1752  * return enum rtw_phl_status
1753  */
phl_wow_ps_proto_cfg(struct phl_wow_info * wow_info,bool enter_ps)1754 enum rtw_phl_status phl_wow_ps_proto_cfg(struct phl_wow_info *wow_info, bool enter_ps)
1755 {
1756 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1757 	struct phl_info_t *phl_info = wow_info->phl_info;
1758 	struct ps_cfg cfg = {0};
1759 	struct rtw_ps_cap_t *ps_cap = _get_ps_cap(phl_info);
1760 
1761 	if (wow_info->op_mode == RTW_WOW_OP_DISCONNECT_STBY) {
1762 		/* IPS */
1763 		if (ps_cap->ips_wow_en) {
1764 			cfg.macid = wow_info->sta->macid;
1765 			pstatus = phl_ps_ips_cfg(phl_info, &cfg, enter_ps);
1766 		}
1767 	} else if (wow_info->op_mode == RTW_WOW_OP_CONNECT_STBY) {
1768 		/* LPS */
1769 		if (ps_cap->lps_wow_en) {
1770 			cfg.macid = wow_info->sta->macid;
1771 			cfg.awake_interval = ps_cap->lps_wow_awake_interval;
1772 			cfg.listen_bcn_mode = ps_cap->lps_wow_listen_bcn_mode;
1773 			cfg.smart_ps_mode = ps_cap->lps_wow_smart_ps_mode;
1774 			pstatus = phl_ps_lps_cfg(phl_info, &cfg, enter_ps);
1775 		}
1776 	} else {
1777 		PHL_ERR("%s : undefined wowlan op mode.\n", __func__);
1778 	}
1779 
1780 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : op mode %d, enter ps %d, pwr lvl %s.\n.",
1781 			  __func__, wow_info->op_mode, enter_ps, phl_ps_pwr_lvl_to_str(wow_info->ps_pwr_lvl));
1782 
1783 	return pstatus;
1784 }
1785 
1786 /**
1787  * phl_wow_ps_pwr_ntfy - notify the power level when enter low power
1788  * @wow_info: see struct phl_wow_info
1789  * @enter_ps: enter low power or not
1790  *
1791  */
phl_wow_ps_pwr_ntfy(struct phl_wow_info * wow_info,bool enter_ps)1792 void phl_wow_ps_pwr_ntfy(struct phl_wow_info *wow_info, bool enter_ps)
1793 {
1794 	struct phl_info_t *phl_info = wow_info->phl_info;
1795 
1796 	if (wow_info->ps_pwr_lvl == PS_PWR_LVL_PWRON)
1797 		return;
1798 
1799 	if (wow_info->op_mode == RTW_WOW_OP_DISCONNECT_STBY) {
1800 		/* IPS */
1801 	} else if (wow_info->op_mode == RTW_WOW_OP_CONNECT_STBY) {
1802 		#ifdef CONFIG_BTCOEX
1803 		rtw_hal_btc_radio_state_ntfy(phl_info->hal, (enter_ps == true ?
1804 							BTC_RFCTRL_FW_CTRL : BTC_RFCTRL_WL_ON));
1805 		#endif
1806 	} else {
1807 		PHL_ERR("%s : undefined wowlan op mode.\n", __func__);
1808 	}
1809 
1810 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : op mode %d, enter ps %d, pwr lvl %s.\n.",
1811 			  __func__, wow_info->op_mode, enter_ps, phl_ps_pwr_lvl_to_str(wow_info->ps_pwr_lvl));
1812 }
1813 
1814 
1815 /**
1816  * phl_wow_ps_pwr_cfg - set the low power level under wowlan
1817  * @wow_info: see struct phl_wow_info
1818  * @enter_ps: enter low power or not
1819  *
1820  * returns enum rtw_phl_status
1821  */
phl_wow_ps_pwr_cfg(struct phl_wow_info * wow_info,bool enter_ps)1822 enum rtw_phl_status phl_wow_ps_pwr_cfg(struct phl_wow_info *wow_info, bool enter_ps)
1823 {
1824 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1825 	struct phl_info_t *phl_info = wow_info->phl_info;
1826 
1827 	if (wow_info->ps_pwr_lvl == PS_PWR_LVL_PWRON)
1828 		return hstatus;
1829 
1830 	if (wow_info->op_mode == RTW_WOW_OP_DISCONNECT_STBY) {
1831 		hstatus = rtw_hal_ps_pwr_lvl_cfg(phl_info->phl_com, phl_info->hal,
1832 					(enter_ps == true ? wow_info->ps_pwr_lvl : PS_PWR_LVL_PWRON));
1833 	} else if (wow_info->op_mode == RTW_WOW_OP_CONNECT_STBY) {
1834 		hstatus = rtw_hal_ps_pwr_lvl_cfg(phl_info->phl_com, phl_info->hal,
1835 					(enter_ps == true ? wow_info->ps_pwr_lvl : PS_PWR_LVL_PWRON));
1836 	} else {
1837 		PHL_ERR("%s : undefined wowlan op mode.\n", __func__);
1838 	}
1839 
1840 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : op mode %d, enter ps %d, pwr lvl %s.\n.",
1841 			  __func__, wow_info->op_mode, enter_ps, phl_ps_pwr_lvl_to_str(wow_info->ps_pwr_lvl));
1842 
1843 	return (hstatus == RTW_HAL_STATUS_SUCCESS ?
1844 			RTW_PHL_STATUS_SUCCESS : RTW_PHL_STATUS_FAILURE);
1845 }
1846 #endif /* CONFIG_POWER_SAVE */
1847 
1848 #define case_rsn(rsn) \
1849 	case RTW_WOW_RSN_##rsn: return #rsn
1850 
rtw_phl_get_wow_rsn_str(void * phl,enum rtw_wow_wake_reason wake_rsn)1851 const char *rtw_phl_get_wow_rsn_str(void *phl, enum rtw_wow_wake_reason wake_rsn)
1852 {
1853 	switch (wake_rsn) {
1854 	case_rsn(UNKNOWN); /* RTW_WOW_RSN_UNKNOWN */
1855 	case_rsn(RX_PAIRWISEKEY);
1856 	case_rsn(RX_GTK);
1857 	case_rsn(RX_FOURWAY_HANDSHAKE);
1858 	case_rsn(RX_DISASSOC);
1859 	case_rsn(RX_DEAUTH);
1860 	case_rsn(RX_ARP_REQUEST);
1861 	case_rsn(RX_NS);
1862 	case_rsn(RX_EAPREQ_IDENTIFY);
1863 	case_rsn(FW_DECISION_DISCONNECT);
1864 	case_rsn(RX_MAGIC_PKT);
1865 	case_rsn(RX_UNICAST_PKT);
1866 	case_rsn(RX_PATTERN_PKT);
1867 	case_rsn(RTD3_SSID_MATCH);
1868 	case_rsn(RX_DATA_PKT);
1869 	case_rsn(RX_SSDP_MATCH);
1870 	case_rsn(RX_WSD_MATCH);
1871 	case_rsn(RX_SLP_MATCH);
1872 	case_rsn(RX_LLTD_MATCH);
1873 	case_rsn(RX_MDNS_MATCH);
1874 	case_rsn(RX_REALWOW_V2_WAKEUP_PKT);
1875 	case_rsn(RX_REALWOW_V2_ACK_LOST);
1876 	case_rsn(RX_REALWOW_V2_TX_KAPKT);
1877 	case_rsn(ENABLE_FAIL_DMA_IDLE);
1878 	case_rsn(ENABLE_FAIL_DMA_PAUSE);
1879 	case_rsn(RTIME_FAIL_DMA_IDLE);
1880 	case_rsn(RTIME_FAIL_DMA_PAUSE);
1881 	case_rsn(RX_SNMP_MISMATCHED_PKT);
1882 	case_rsn(RX_DESIGNATED_MAC_PKT);
1883 	case_rsn(NLO_SSID_MACH);
1884 	case_rsn(AP_OFFLOAD_WAKEUP);
1885 	case_rsn(DMAC_ERROR_OCCURRED);
1886 	case_rsn(EXCEPTION_OCCURRED);
1887 	case_rsn(L0_TO_L1_ERROR_OCCURRED);
1888 	case_rsn(ASSERT_OCCURRED);
1889 	case_rsn(L2_ERROR_OCCURRED);
1890 	case_rsn(WDT_TIMEOUT_WAKE);
1891 	case_rsn(RX_ACTION);
1892 	case_rsn(CLK_32K_UNLOCK);
1893 	case_rsn(CLK_32K_LOCK);
1894 	default:
1895 		return "UNDEFINED"; /* RTW_WOW_RSN_MAX */
1896 	}
1897 }
1898 
rtw_phl_cfg_wow_set_sw_gpio_mode(void * phl,struct rtw_wow_gpio_info * info)1899 enum rtw_phl_status rtw_phl_cfg_wow_set_sw_gpio_mode(void *phl, struct rtw_wow_gpio_info *info)
1900 {
1901 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1902 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1903 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
1904 	struct rtw_wow_gpio_info *wow_gpio = &wow_info->wow_gpio;
1905 
1906 	FUNCIN();
1907 
1908 	wow_gpio->dev2hst_gpio = info->dev2hst_gpio;
1909 	wow_gpio->dev2hst_gpio_mode = info->dev2hst_gpio_mode;
1910 	phl_status = rtw_hal_set_sw_gpio_mode(phl_info->phl_com, phl_info->hal
1911 		, wow_gpio->dev2hst_gpio_mode, wow_gpio->dev2hst_gpio);
1912 
1913 	PHL_INFO("%s, gpio=%d, gpio_mode=%d\n", __FUNCTION__
1914 		, wow_gpio->dev2hst_gpio, wow_gpio->dev2hst_gpio_mode);
1915 
1916 	return phl_status;
1917 }
1918 
rtw_phl_cfg_wow_sw_gpio_ctrl(void * phl,struct rtw_wow_gpio_info * info)1919 enum rtw_phl_status rtw_phl_cfg_wow_sw_gpio_ctrl(void *phl, struct rtw_wow_gpio_info *info)
1920 {
1921 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1922 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1923 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
1924 	struct rtw_wow_gpio_info *wow_gpio = &wow_info->wow_gpio;
1925 
1926 	FUNCIN();
1927 
1928 	wow_gpio->dev2hst_high = info->dev2hst_high;
1929 	phl_status = rtw_hal_sw_gpio_ctrl(phl_info->phl_com, phl_info->hal
1930 		, wow_gpio->dev2hst_high, wow_gpio->dev2hst_gpio);
1931 
1932 	PHL_INFO("%s, gpio=%d, output=%d\n", __FUNCTION__
1933 		, wow_gpio->dev2hst_gpio, wow_gpio->dev2hst_high);
1934 
1935 	return phl_status;
1936 }
1937 
1938 #endif /* CONFIG_WOWLAN */
1939