xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/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 
855 	FUNCIN();
856 
857 	wow_gpio->dev2hst_gpio_en = info->dev2hst_gpio_en;
858 	wow_gpio->disable_inband = info->disable_inband;
859 	wow_gpio->gpio_output_input = info->gpio_output_input;
860 	wow_gpio->gpio_active = info->gpio_active;
861 	wow_gpio->toggle_pulse = info->toggle_pulse;
862 	wow_gpio->data_pin_wakeup = info->data_pin_wakeup;
863 	wow_gpio->gpio_pulse_nonstop = info->gpio_pulse_nonstop;
864 	wow_gpio->gpio_time_unit = info->gpio_time_unit;
865 	wow_gpio->gpio_num = info->gpio_num;
866 	wow_gpio->gpio_pulse_dura = info->gpio_pulse_dura;
867 	wow_gpio->gpio_pulse_period = info->gpio_pulse_period;
868 	wow_gpio->gpio_pulse_count = info->gpio_pulse_count;
869 	wow_gpio->customer_id = info->customer_id;
870 	wow_gpio->gpio_pulse_en_a = info->gpio_pulse_en_a;
871 	wow_gpio->gpio_duration_unit_a = info->gpio_duration_unit_a;
872 	wow_gpio->gpio_pulse_nonstop_a = info->gpio_pulse_nonstop_a;
873 	wow_gpio->special_reason_a = info->special_reason_a;
874 	wow_gpio->gpio_duration_a = info->gpio_duration_a;
875 	wow_gpio->gpio_pulse_count_a = info->gpio_pulse_count_a;
876 	wow_gpio->dev2hst_gpio_mode = info->dev2hst_gpio_mode;
877 	wow_gpio->dev2hst_gpio = info->dev2hst_gpio;
878 	wow_gpio->dev2hst_high = info->dev2hst_high;
879 
880 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] dev2hst_gpio_en %d\n", wow_gpio->dev2hst_gpio_en);
881 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] disable_inband %d\n", wow_gpio->disable_inband);
882 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_output_input %d\n", wow_gpio->gpio_output_input);
883 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_active %d\n", wow_gpio->gpio_active);
884 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] toggle_pulse %d\n", wow_gpio->toggle_pulse);
885 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] data_pin_wakeup %d\n", wow_gpio->data_pin_wakeup);
886 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_nonstop %d\n", wow_gpio->gpio_pulse_nonstop);
887 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_time_unit %d\n", wow_gpio->gpio_time_unit);
888 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_num %d\n", wow_gpio->gpio_num);
889 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_dura %d\n", wow_gpio->gpio_pulse_dura);
890 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_period %d\n", wow_gpio->gpio_pulse_period);
891 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_count %d\n", wow_gpio->gpio_pulse_count);
892 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] customer_id %d\n", wow_gpio->customer_id);
893 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_en_a %d\n", wow_gpio->gpio_pulse_en_a);
894 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_duration_unit_a %d\n", wow_gpio->gpio_duration_unit_a);
895 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_nonstop_a %d\n", wow_gpio->gpio_pulse_nonstop_a);
896 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] special_reason_a %d\n", wow_gpio->special_reason_a);
897 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_duration_a %d\n", wow_gpio->gpio_duration_a);
898 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] gpio_pulse_count_a %d\n", wow_gpio->gpio_pulse_count_a);
899 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] dev2hst_gpio_mode %d\n", wow_gpio->dev2hst_gpio_mode);
900 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] dev2hst_gpio %d\n", wow_gpio->dev2hst_gpio);
901 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] dev2hst_high %d\n", wow_gpio->dev2hst_high);
902 
903 	return phl_status;
904 }
905 
phl_record_wow_stat(struct phl_wow_info * wow_info)906 void phl_record_wow_stat(struct phl_wow_info *wow_info)
907 {
908 	struct phl_wow_stat *wow_stat = &wow_info->wow_stat;
909 
910 	/* init */
911 	wow_stat->func_en = wow_info->func_en;
912 	wow_stat->op_mode = wow_info->op_mode;
913 	wow_stat->keep_alive_en = wow_info->keep_alive_info.keep_alive_en;
914 	wow_stat->disc_det_en = wow_info->disc_det_info.disc_det_en;
915 	wow_stat->arp_en = wow_info->arp_ofld_info.arp_en;
916 	wow_stat->ndp_en = wow_info->ndp_ofld_info.ndp_en;
917 	wow_stat->gtk_en = wow_info->gtk_ofld_info.gtk_en;
918 	wow_stat->dot11w_en = wow_info->gtk_ofld_info.ieee80211w_en;
919 	wow_stat->err.init = wow_info->err.init;
920 	/* deinit */
921 	wow_stat->mac_pwr = wow_info->mac_pwr;
922 	wow_stat->wake_rsn = wow_info->wake_rsn;
923 	wow_stat->err.deinit = wow_info->err.deinit;
924 
925 	if (wow_info->aoac_info.rpt_fail)
926 		++wow_stat->aoac_rpt_fail_cnt;
927 }
928 
929 #ifdef CONFIG_PCI_HCI
_init_precfg(struct phl_info_t * phl_info,u8 band)930 enum rtw_phl_status _init_precfg(struct phl_info_t *phl_info, u8 band)
931 {
932 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
933 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
934 	u8 status = false;
935 
936 	do {
937 		/* 1. stop Tx DMA */
938 		rtw_hal_wow_cfg_txdma(phl_info->hal, false);
939 
940 		/* 2. stop HW Tx */
941 		hstatus = rtw_hal_wow_drop_tx(phl_info->hal, band);
942 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
943 			PHL_ERR("[wow] rtw_hal_wow_drop_tx fail!\n");
944 			break;
945 		}
946 
947 		/* 3. poll dma idle */
948 		status = rtw_hal_poll_txdma_idle(phl_info->hal);
949 		if (!status) {
950 			PHL_ERR("[wow] rtw_hal_poll_txdma_idle fail!\n");
951 			break;
952 		}
953 
954 	} while (0);
955 
956 	if (RTW_HAL_STATUS_SUCCESS != hstatus)
957 		pstatus = RTW_PHL_STATUS_FAILURE;
958 	else
959 		pstatus = RTW_PHL_STATUS_SUCCESS;
960 
961 	FUNCOUT_WSTS(pstatus);
962 
963 	return pstatus;
964 }
_init_postcfg(struct phl_info_t * phl_info)965 enum rtw_phl_status _init_postcfg(struct phl_info_t *phl_info)
966 {
967 	/* stop tx/rx hci */
968 	rtw_hal_cfg_txhci(phl_info->hal, false);
969 	rtw_hal_cfg_rxhci(phl_info->hal, false);
970 
971 	rtw_hal_poll_txdma_idle(phl_info->hal);
972 
973 	return RTW_PHL_STATUS_SUCCESS;
974 }
975 #elif defined(CONFIG_USB_HCI)
_init_precfg(struct phl_info_t * phl_info,u8 band)976 enum rtw_phl_status _init_precfg(struct phl_info_t *phl_info, u8 band)
977 {
978 	return RTW_PHL_STATUS_SUCCESS;
979 }
_init_postcfg(struct phl_info_t * phl_info)980 enum rtw_phl_status _init_postcfg(struct phl_info_t *phl_info)
981 {
982 	return RTW_PHL_STATUS_SUCCESS;
983 }
984 
985 #elif defined(CONFIG_SDIO_HCI)
_init_precfg(struct phl_info_t * phl_info,u8 band)986 enum rtw_phl_status _init_precfg(struct phl_info_t *phl_info, u8 band)
987 {
988 	return RTW_PHL_STATUS_SUCCESS;
989 }
_init_postcfg(struct phl_info_t * phl_info)990 enum rtw_phl_status _init_postcfg(struct phl_info_t *phl_info)
991 {
992 	return RTW_PHL_STATUS_SUCCESS;
993 }
994 
995 #endif
996 
_init_precfg_set_rxfltr(struct phl_info_t * phl_info)997 static enum rtw_phl_status _init_precfg_set_rxfltr(struct phl_info_t *phl_info)
998 {
999 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1000 
1001 	do {
1002 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_DATA, 0);
1003 	 	if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1004 			PHL_ERR("[wow] set rx filter data drop fail, status(%u)\n", hstatus);
1005 			break;
1006 		}
1007 
1008 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_MGNT, 0);
1009 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1010 			PHL_ERR("[wow] set rx filter mgnt drop fail, status(%u)\n", hstatus);
1011 			break;
1012 		}
1013 
1014 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_CTRL, 0);
1015 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1016 			PHL_ERR("[wow] set rx filter ctrl drop fail, status(%u)\n", hstatus);
1017 			break;
1018 		}
1019 	} while (0);
1020 
1021 	return (hstatus == RTW_HAL_STATUS_SUCCESS) ?
1022 			RTW_PHL_STATUS_SUCCESS : RTW_PHL_STATUS_FAILURE;
1023 }
1024 
_init_postcfg_set_rxfltr(struct phl_info_t * phl_info)1025 static enum rtw_phl_status _init_postcfg_set_rxfltr(struct phl_info_t *phl_info)
1026 {
1027 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1028 
1029 	do {
1030 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_DATA, 1);
1031 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1032 			PHL_ERR("[wow] set rx filter data to host fail, status(%u)\n", hstatus);
1033 			break;
1034 		}
1035 
1036 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_MGNT, 1);
1037 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1038 			PHL_ERR("[wow] set rx filter mgnt to host fail, status(%u)\n", hstatus);
1039 			break;
1040 		}
1041 
1042 		hstatus = rtw_hal_set_rxfltr_by_type(phl_info->hal, 0, RTW_PHL_PKT_TYPE_CTRL, 1);
1043 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1044 			PHL_ERR("[wow] set rx filter ctrl to host fail, status(%u)\n", hstatus);
1045 			break;
1046 		}
1047 	} while (0);
1048 
1049 	return (hstatus == RTW_HAL_STATUS_SUCCESS) ?
1050 			RTW_PHL_STATUS_SUCCESS : RTW_PHL_STATUS_FAILURE;
1051 }
1052 
1053 #define MAX_POLLING_TRX_STOP 2000 /* us */
phl_wow_init_precfg(struct phl_wow_info * wow_info)1054 enum rtw_phl_status phl_wow_init_precfg(struct phl_wow_info *wow_info)
1055 {
1056 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1057 	struct phl_info_t *phl_info = wow_info->phl_info;
1058 	struct phl_hci_trx_ops *trx_ops = phl_info->hci_trx_ops;
1059 	u32 wait_cnt = 0;
1060 
1061 	FUNCIN();
1062 
1063 	/* pause sw Tx */
1064 	trx_ops->req_tx_stop(phl_info);
1065 
1066 	/* schedule current existing tx handler */
1067 	pstatus = rtw_phl_tx_req_notify(phl_info);
1068 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1069 		PHL_ERR("[wow] rtw_phl_tx_req_notify fail, status(%u)\n", pstatus);
1070 
1071 	/* polling pause sw Tx done */
1072 	while (wait_cnt < MAX_POLLING_TRX_STOP) {
1073 		if (trx_ops->is_tx_pause(phl_info)) {
1074 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] sw tx pause succeed.\n");
1075 			break;
1076 		}
1077 		_os_delay_us(phl_info->phl_com->drv_priv, 1);
1078 		wait_cnt++;
1079 	}
1080 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] stop sw tx wait_cnt %d.\n", wait_cnt);
1081 
1082 	/* init pre-configuration for different interfaces */
1083 	pstatus = _init_precfg(phl_info, wow_info->sta->wrole->hw_band);
1084 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1085 		return pstatus;
1086 
1087 	/* set packet drop by setting rx filter */
1088 	pstatus = _init_precfg_set_rxfltr(phl_info);
1089 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1090 		return pstatus;
1091 
1092 	/* disable ppdu sts */
1093 	rtw_hal_ppdu_sts_cfg(phl_info->hal, wow_info->sta->wrole->hw_band, false);
1094 
1095 	pstatus = RTW_PHL_STATUS_SUCCESS;
1096 
1097 	return pstatus;
1098 }
1099 
phl_wow_init_postcfg(struct phl_wow_info * wow_info)1100 enum rtw_phl_status phl_wow_init_postcfg(struct phl_wow_info *wow_info)
1101 {
1102 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1103 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1104 	struct phl_info_t *phl_info = wow_info->phl_info;
1105 	struct phl_hci_trx_ops *trx_ops = phl_info->hci_trx_ops;
1106 	struct rtw_phl_stainfo_t *sta = wow_info->sta;
1107 	u32 wait_cnt = 0;
1108 #ifdef CONFIG_SYNC_INTERRUPT
1109 	struct rtw_phl_evt_ops *evt_ops = &phl_info->phl_com->evt_ops;
1110 #endif /* CONFIG_SYNC_INTERRUPT */
1111 
1112 	/* disable interrupt */
1113 #ifdef CONFIG_SYNC_INTERRUPT
1114 	evt_ops->set_interrupt_caps(phl_to_drvpriv(phl_info), false);
1115 #else
1116 	rtw_hal_disable_interrupt(phl_info->phl_com, phl_info->hal);
1117 #endif /* CONFIG_SYNC_INTERRUPT */
1118 
1119 	pstatus = _init_postcfg(phl_info);
1120 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1121 		PHL_ERR("[wow] _init_postcfg failed.\n");
1122 
1123 	/* stop sw rx */
1124 	trx_ops->req_rx_stop(phl_info);
1125 	pstatus = rtw_phl_start_rx_process(phl_info);
1126 	if (RTW_PHL_STATUS_SUCCESS != pstatus)
1127 		PHL_ERR("[wow] rtw_phl_start_rx_process failed.\n");
1128 
1129 	while (wait_cnt < MAX_POLLING_TRX_STOP) {
1130 		if (trx_ops->is_rx_pause(phl_info)) {
1131 			PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] sw rx pause succeed.\n");
1132 			break;
1133 		}
1134 		_os_delay_us(phl_info->phl_com->drv_priv, 1);
1135 		wait_cnt++;
1136 	}
1137 
1138 	if (wait_cnt == MAX_POLLING_TRX_STOP)
1139 		PHL_WARN("[wow] sw rx pause fail.\n");
1140 
1141 	/* configure wow sleep */
1142 	hstatus = rtw_hal_cfg_wow_sleep(phl_info->hal, true);
1143 	if (RTW_HAL_STATUS_SUCCESS != hstatus)
1144 		return RTW_PHL_STATUS_FAILURE;
1145 
1146 	/* forward rx packet to host by setting rx filter */
1147 	pstatus = _init_postcfg_set_rxfltr(phl_info);
1148 
1149 	/* reset trx */
1150 #ifdef CONFIG_USB_HCI
1151 	trx_ops->trx_stop(phl_info);
1152 #else
1153 	trx_ops->trx_reset(phl_info, PHL_CTRL_TX | PHL_CTRL_RX);
1154 #endif
1155 
1156 
1157 	/* notify reorder sleep */
1158 	phl_notify_reorder_sleep(phl_info, sta);
1159 	return pstatus;
1160 }
1161 
_phl_indic_wake_sec_upd(struct phl_wow_info * wow_info,u8 aoac_report_get_ok,u8 rx_ready)1162 static void _phl_indic_wake_sec_upd(struct phl_wow_info *wow_info, u8 aoac_report_get_ok, u8 rx_ready)
1163 {
1164 	struct phl_info_t *phl_info = wow_info->phl_info;
1165 	struct rtw_phl_evt_ops *ops = &phl_info->phl_com->evt_ops;
1166 	void *drv_priv = phl_to_drvpriv(phl_info);
1167 
1168 	if (NULL != ops->wow_handle_sec_info_update)
1169 		ops->wow_handle_sec_info_update(drv_priv, &wow_info->aoac_info, aoac_report_get_ok, rx_ready);
1170 	else
1171 		PHL_TRACE(COMP_PHL_WOW, _PHL_ERR_, "[wow] %s : evt_ops->wow_handle_sec_info_update is NULL.\n"
1172 			, __func__);
1173 }
1174 
_phl_handle_aoac_rpt_action(struct phl_wow_info * wow_info,bool rx_ready)1175 static void _phl_handle_aoac_rpt_action(struct phl_wow_info *wow_info, bool rx_ready)
1176 {
1177 	struct phl_info_t *phl_info = wow_info->phl_info;
1178 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1179 	u8 aoac_report_get_ok = false;
1180 	static u8 phase_0_ok = false;
1181 
1182 	if (wow_info->wow_wake_info.pairwise_sec_algo) {
1183 		if (rx_ready == false) {
1184 			/* phase 0 */
1185 			hstatus = rtw_hal_get_wow_aoac_rpt(phl_info->hal, &wow_info->aoac_info, rx_ready);
1186 			aoac_report_get_ok = (hstatus == RTW_HAL_STATUS_SUCCESS) ? true : false;
1187 			_phl_indic_wake_sec_upd(wow_info, aoac_report_get_ok, rx_ready);
1188 
1189 			phase_0_ok = aoac_report_get_ok;
1190 		}
1191 
1192 		if (rx_ready == true) {
1193 			/* phase 1 */
1194 			if (phase_0_ok) {
1195 				hstatus = rtw_hal_get_wow_aoac_rpt(phl_info->hal, &wow_info->aoac_info, rx_ready);
1196 				aoac_report_get_ok = (hstatus == RTW_HAL_STATUS_SUCCESS) ? true : false;
1197 				_phl_indic_wake_sec_upd(wow_info, aoac_report_get_ok, rx_ready);
1198 			}
1199 
1200 			phase_0_ok = false;
1201 
1202 			wow_info->aoac_info.rpt_fail = (aoac_report_get_ok == false) ? true : false;
1203 		}
1204 	}
1205 }
1206 
_phl_indic_wake_rsn(struct phl_wow_info * wow_info)1207 static enum rtw_phl_status _phl_indic_wake_rsn(struct phl_wow_info *wow_info)
1208 {
1209 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1210 	struct phl_info_t *phl_info = wow_info->phl_info;
1211 	struct rtw_phl_evt_ops *evt_ops = &(phl_info->phl_com->evt_ops);
1212 
1213 	FUNCIN_WSTS(phl_status);
1214 
1215 	if (NULL != evt_ops->indicate_wake_rsn) {
1216 		evt_ops->indicate_wake_rsn(phl_to_drvpriv(phl_info), wow_info->wake_rsn);
1217 	}
1218 
1219 	FUNCOUT_WSTS(phl_status);
1220 
1221 	return phl_status;
1222 }
1223 
phl_wow_handle_wake_rsn(struct phl_wow_info * wow_info,u8 * reset)1224 void phl_wow_handle_wake_rsn(struct phl_wow_info *wow_info, u8 *reset)
1225 {
1226 	struct phl_info_t *phl_info = wow_info->phl_info;
1227 
1228 	rtw_hal_get_wake_rsn(phl_info->hal, &wow_info->wake_rsn, reset);
1229 	_phl_indic_wake_rsn(wow_info);
1230 }
1231 
1232 #ifdef CONFIG_PCI_HCI
_deinit_precfg(struct phl_info_t * phl_info)1233 enum rtw_phl_status _deinit_precfg(struct phl_info_t *phl_info)
1234 {
1235 #ifdef DBG_RST_BDRAM_TIME
1236 	u32 rst_bdram_start = _os_get_cur_time_ms();
1237 #endif /* DBG_RST_BDRAM_TIME */
1238 
1239 	rtw_hal_clear_bdidx(phl_info->hal);
1240 
1241 #ifdef DBG_RST_BDRAM_TIME
1242 	rst_bdram_start = _os_get_cur_time_ms();
1243 #endif
1244 	rtw_hal_rst_bdram(phl_info->hal);
1245 
1246 #ifdef DBG_RST_BDRAM_TIME
1247 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : Reset bdram takes %u (ms).\n"
1248 		, __func__, phl_get_passing_time_ms(rst_bdram_start));
1249 #endif
1250 
1251 	rtw_hal_cfg_txhci(phl_info->hal, true);
1252 	rtw_hal_cfg_rxhci(phl_info->hal, true);
1253 
1254 	/* start tx dma */
1255 	rtw_hal_wow_cfg_txdma(phl_info->hal, true);
1256 
1257 	return RTW_PHL_STATUS_SUCCESS;
1258 }
1259 #elif defined(CONFIG_USB_HCI)
_deinit_precfg(struct phl_info_t * phl_info)1260 enum rtw_phl_status _deinit_precfg(struct phl_info_t *phl_info)
1261 {
1262 	return RTW_PHL_STATUS_SUCCESS;
1263 }
1264 #elif defined(CONFIG_SDIO_HCI)
_deinit_precfg(struct phl_info_t * phl_info)1265 enum rtw_phl_status _deinit_precfg(struct phl_info_t *phl_info)
1266 {
1267 	return RTW_PHL_STATUS_SUCCESS;
1268 }
1269 #endif
1270 
_deinit_precfg_set_intr(struct phl_info_t * phl_info)1271 void _deinit_precfg_set_intr(struct phl_info_t *phl_info)
1272 {
1273 #ifdef CONFIG_SYNC_INTERRUPT
1274 	struct rtw_phl_evt_ops *evt_ops = &phl_info->phl_com->evt_ops;
1275 #endif /* CONFIG_SYNC_INTERRUPT */
1276 
1277 	rtw_hal_set_default_var(phl_info->hal, SET_DEF_RSN_WOW_RESUME_HNDL_RX);
1278 #ifdef CONFIG_SYNC_INTERRUPT
1279 	evt_ops->set_interrupt_caps(phl_to_drvpriv(phl_info), true);
1280 #else
1281 	rtw_hal_enable_interrupt(phl_info->phl_com, phl_info->hal);
1282 #endif /* CONFIG_SYNC_INTERRUPT */
1283 }
1284 
phl_wow_deinit_precfg(struct phl_wow_info * wow_info)1285 enum rtw_phl_status phl_wow_deinit_precfg(struct phl_wow_info *wow_info)
1286 {
1287 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1288 	struct phl_info_t *phl_info = wow_info->phl_info;
1289 	struct phl_hci_trx_ops *trx_ops = phl_info->hci_trx_ops;
1290 
1291 	FUNCIN();
1292 
1293 	_deinit_precfg(phl_info);
1294 
1295 	rtw_hal_cfg_wow_sleep(phl_info->hal, false);
1296 
1297 	_phl_handle_aoac_rpt_action(wow_info, false);
1298 
1299 	/* resume sw rx */
1300 #ifdef CONFIG_USB_HCI
1301 	trx_ops->trx_cfg(phl_info);
1302 #else
1303 	trx_ops->trx_resume(phl_info, PHL_CTRL_RX);
1304 #endif
1305 
1306 	_deinit_precfg_set_intr(phl_info);
1307 
1308 	_phl_handle_aoac_rpt_action(wow_info, true);
1309 
1310 	return phl_status;
1311 }
1312 
phl_reset_wow_info(struct phl_wow_info * wow_info)1313 void phl_reset_wow_info(struct phl_wow_info *wow_info)
1314 {
1315 	struct phl_info_t *phl_info = wow_info->phl_info;
1316 	void *d = phl_to_drvpriv(phl_info);
1317 
1318 	wow_info->func_en = 0;
1319 	wow_info->op_mode = RTW_WOW_OP_NONE;
1320 	wow_info->mac_pwr = RTW_MAC_PWR_NONE;
1321 	wow_info->ps_pwr_lvl = PS_PWR_LVL_PWRON;
1322 
1323 	_os_mem_set(d, &wow_info->err, 0, sizeof(struct phl_wow_error));
1324 	_os_mem_set(d, &wow_info->keep_alive_info, 0, sizeof(struct rtw_keep_alive_info));
1325 	_os_mem_set(d, &wow_info->disc_det_info, 0, sizeof(struct rtw_disc_det_info));
1326 	_os_mem_set(d, &wow_info->nlo_info, 0, sizeof(struct rtw_nlo_info));
1327 	_os_mem_set(d, &wow_info->arp_ofld_info, 0, sizeof(struct rtw_arp_ofld_info));
1328 	_os_mem_set(d, &wow_info->ndp_ofld_info, 0, sizeof(struct rtw_ndp_ofld_info));
1329 	_os_mem_set(d, &wow_info->gtk_ofld_info, 0, sizeof(struct rtw_gtk_ofld_info));
1330 	_os_mem_set(d, &wow_info->realwow_info, 0, sizeof(struct rtw_realwow_info));
1331 	_os_mem_set(d, &wow_info->wow_wake_info, 0, sizeof(struct rtw_wow_wake_info));
1332 	_os_mem_set(d, &wow_info->aoac_info, 0, sizeof(struct rtw_aoac_report));
1333 
1334 	wow_info->wake_rsn = RTW_WOW_RSN_UNKNOWN;
1335 
1336 	/*
1337 		&wow_info->pattern_match_info need not to be reset here.
1338 		We expect those items will be remove triggered by core layer
1339 	*/
1340 }
1341 
_deinit_postcfg_set_intr(struct phl_info_t * phl_info)1342 void _deinit_postcfg_set_intr(struct phl_info_t *phl_info)
1343 {
1344 #ifdef CONFIG_SYNC_INTERRUPT
1345 	struct rtw_phl_evt_ops *evt_ops = &phl_info->phl_com->evt_ops;
1346 #endif /* CONFIG_SYNC_INTERRUPT */
1347 
1348 #ifdef CONFIG_SYNC_INTERRUPT
1349 	evt_ops->set_interrupt_caps(phl_to_drvpriv(phl_info), false);
1350 #else
1351 	rtw_hal_disable_interrupt(phl_info->phl_com, phl_info->hal);
1352 #endif /* CONFIG_SYNC_INTERRUPT */
1353 	rtw_hal_set_default_var(phl_info->hal, SET_DEF_RSN_WOW_RESUME_DONE);
1354 #ifdef CONFIG_SYNC_INTERRUPT
1355 	evt_ops->set_interrupt_caps(phl_to_drvpriv(phl_info), true);
1356 #else
1357 	rtw_hal_enable_interrupt(phl_info->phl_com, phl_info->hal);
1358 #endif /* CONFIG_SYNC_INTERRUPT */
1359 }
1360 
phl_wow_deinit_postcfg(struct phl_wow_info * wow_info)1361 enum rtw_phl_status phl_wow_deinit_postcfg(struct phl_wow_info *wow_info)
1362 {
1363 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1364 	struct phl_info_t *phl_info = wow_info->phl_info;
1365 	struct phl_hci_trx_ops *trx_ops = phl_info->hci_trx_ops;
1366 
1367 	FUNCIN();
1368 
1369 	/* resume sw tx */
1370 	trx_ops->trx_resume(phl_info, PHL_CTRL_TX);
1371 	/* enable ppdu sts */
1372 	rtw_hal_ppdu_sts_cfg(phl_info->hal, wow_info->sta->wrole->hw_band, true);
1373 
1374 	_deinit_postcfg_set_intr(phl_info);
1375 
1376 	return phl_status;
1377 }
1378 
_phl_wow_cfg_pkt_ofld(struct phl_wow_info * wow_info,u8 pkt_type,u8 * pkt_id,void * buf)1379 enum rtw_phl_status _phl_wow_cfg_pkt_ofld(struct phl_wow_info *wow_info, u8 pkt_type, u8 *pkt_id, void *buf)
1380 {
1381 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1382 	u16 macid = wow_info->sta->macid;
1383 	u32 *token;
1384 
1385 	switch(pkt_type) {
1386 	case PKT_TYPE_NULL_DATA:
1387 		token = &wow_info->null_pkt_token;
1388 		break;
1389 	case PKT_TYPE_ARP_RSP:
1390 		token = &wow_info->arp_pkt_token;
1391 		break;
1392 	case PKT_TYPE_NDP:
1393 		token = &wow_info->ndp_pkt_token;
1394 		break;
1395 	case PKT_TYPE_EAPOL_KEY:
1396 		token = &wow_info->eapol_key_pkt_token;
1397 		break;
1398 	case PKT_TYPE_SA_QUERY:
1399 		token = &wow_info->sa_query_pkt_token;
1400 		break;
1401 	case PKT_TYPE_REALWOW_KAPKT:
1402 		token = &wow_info->kapkt_pkt_token;
1403 		break;
1404 	case PKT_TYPE_REALWOW_ACK:
1405 		token = &wow_info->ack_pkt_token;
1406 		break;
1407 	case PKT_TYPE_REALWOW_WP:
1408 		token = &wow_info->wp_token;
1409 		break;
1410 	case PKT_TYPE_PROBE_REQ:
1411 		token = &wow_info->probe_req_pkt_token;
1412 		break;
1413 	default:
1414 		PHL_TRACE(COMP_PHL_WOW, _PHL_ERR_, "[wow] %s : unknown pkt_type %d.\n"
1415 			, __func__, pkt_type);
1416 		return pstatus;
1417 	}
1418 
1419 	pstatus = RTW_PHL_PKT_OFLD_REQ(wow_info->phl_info, macid, pkt_type, token, buf);
1420 
1421 	if (pstatus == RTW_PHL_STATUS_SUCCESS)
1422 		*pkt_id = phl_pkt_ofld_get_id(wow_info->phl_info, macid, pkt_type);
1423 
1424 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : pkt_type %s, pkt_id %d, token %u, status(%u)\n",
1425 		__func__, phl_get_pkt_ofld_str(pkt_type), *pkt_id, *token, pstatus);
1426 
1427 	return pstatus;
1428 }
1429 
_phl_wow_cfg_nlo(struct phl_wow_info * wow_info)1430 static enum rtw_phl_status _phl_wow_cfg_nlo(struct phl_wow_info *wow_info)
1431 {
1432 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1433 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1434 	struct phl_info_t *phl_info = wow_info->phl_info;
1435 	struct rtw_phl_stainfo_t *sta = wow_info->sta;
1436 
1437 	do {
1438 
1439 		/* always stop first */
1440 		hstatus = rtw_hal_wow_cfg_nlo(phl_info->hal, SCAN_OFLD_OP_STOP,
1441 					sta->macid, sta->wrole->hw_band, sta->wrole->hw_port,
1442 					&wow_info->nlo_info);
1443 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1444 			pstatus = RTW_PHL_STATUS_FAILURE;
1445 			break;
1446 		}
1447 
1448 		/* construct channel list and offload to fw */
1449 		hstatus = rtw_hal_wow_cfg_nlo_chnl_list(phl_info->hal,
1450 					&wow_info->nlo_info);
1451 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1452 			pstatus = RTW_PHL_STATUS_FAILURE;
1453 			break;
1454 		}
1455 
1456 		hstatus = rtw_hal_wow_cfg_nlo(phl_info->hal, SCAN_OFLD_OP_START,
1457 					sta->macid, sta->wrole->hw_band, sta->wrole->hw_port,
1458 					&wow_info->nlo_info);
1459 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1460 			pstatus = RTW_PHL_STATUS_FAILURE;
1461 			break;
1462 		}
1463 
1464 	} while (0);
1465 
1466 	return pstatus;
1467 }
1468 
phl_wow_func_en(struct phl_wow_info * wow_info)1469 enum rtw_phl_status phl_wow_func_en(struct phl_wow_info *wow_info)
1470 {
1471 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1472 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1473 	struct phl_info_t *phl_info = wow_info->phl_info;
1474 	struct rtw_phl_stainfo_t *sta = wow_info->sta;
1475 	struct rtw_pkt_ofld_null_info null_info = {0};
1476 	struct rtw_pkt_ofld_arp_rsp_info arp_rsp_info = {0};
1477 	struct rtw_pkt_ofld_na_info na_info = {0};
1478 	struct rtw_pkt_ofld_eapol_key_info eapol_key_info = {0};
1479 	struct rtw_pkt_ofld_sa_query_info sa_query_info = {0};
1480 	struct rtw_pkt_ofld_realwow_kapkt_info kapkt_info = {0};
1481 	struct rtw_pkt_ofld_realwow_ack_info ack_info = {0};
1482 	struct rtw_pkt_ofld_realwow_wp_info wakeup_info = {0};
1483 	struct rtw_pkt_ofld_probe_req_info probe_req_info = {0};
1484 	struct rtw_hal_wow_cfg cfg;
1485 
1486 	FUNCIN();
1487 
1488 	if (!wow_info->wow_wake_info.wow_en) {
1489 		PHL_WARN("%s : wow func is not enabled!\n", __func__);
1490 		return pstatus;
1491 	}
1492 
1493 	do {
1494 
1495 		hstatus = rtw_hal_reset_pkt_ofld_state(phl_info->hal);
1496 
1497 		if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1498 			pstatus = RTW_PHL_STATUS_FAILURE;
1499 			break;
1500 		}
1501 
1502 		if (wow_info->keep_alive_info.keep_alive_en) {
1503 
1504 			_phl_cfg_pkt_ofld_null_info(wow_info, sta, &null_info);
1505 
1506 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1507 					PKT_TYPE_NULL_DATA,
1508 					&wow_info->keep_alive_info.null_pkt_id,
1509 					(void *)&null_info);
1510 
1511 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1512 				break;
1513 		}
1514 
1515 		if (wow_info->arp_ofld_info.arp_en) {
1516 
1517 			_phl_cfg_pkt_ofld_arp_rsp_info(wow_info, sta, &arp_rsp_info);
1518 
1519 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1520 					PKT_TYPE_ARP_RSP,
1521 					&wow_info->arp_ofld_info.arp_rsp_id,
1522 					(void *)&arp_rsp_info);
1523 
1524 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1525 				break;
1526 		}
1527 
1528 		if (wow_info->ndp_ofld_info.ndp_en) {
1529 
1530 			_phl_cfg_pkt_ofld_na_info(wow_info, sta, &na_info);
1531 
1532 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1533 					PKT_TYPE_NDP, &wow_info->ndp_ofld_info.ndp_id,
1534 					(void *)&na_info);
1535 
1536 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1537 				break;
1538 		}
1539 
1540 		if (wow_info->gtk_ofld_info.gtk_en) {
1541 			_phl_cfg_pkt_ofld_eapol_key_info(wow_info, sta, &eapol_key_info);
1542 
1543 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1544 					PKT_TYPE_EAPOL_KEY, &wow_info->gtk_ofld_info.gtk_rsp_id,
1545 					(void *)&eapol_key_info);
1546 
1547 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1548 				break;
1549 
1550 			if (wow_info->gtk_ofld_info.ieee80211w_en) {
1551 				_phl_cfg_pkt_ofld_sa_query_info(wow_info, sta, &sa_query_info);
1552 
1553 				pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1554 					PKT_TYPE_SA_QUERY, &wow_info->gtk_ofld_info.sa_query_id,
1555 					(void *)&sa_query_info);
1556 
1557 				if (pstatus != RTW_PHL_STATUS_SUCCESS)
1558 					break;
1559 			}
1560 		}
1561 
1562 		if (wow_info->realwow_info.realwow_en) {
1563 
1564 			/* realwow keep alive */
1565 			_phl_cfg_pkt_ofld_realwow_kapkt_info(wow_info, sta, &kapkt_info);
1566 
1567 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1568 					PKT_TYPE_REALWOW_KAPKT,
1569 					&wow_info->realwow_info.keepalive_id,
1570 					(void *)&kapkt_info);
1571 
1572 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1573 				break;
1574 
1575 			/* realwow ack */
1576 			_phl_cfg_pkt_ofld_realwow_ack_info(wow_info, &ack_info);
1577 
1578 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1579 					PKT_TYPE_REALWOW_ACK,
1580 					&wow_info->realwow_info.ack_pattern_id,
1581 					(void *)&ack_info);
1582 
1583 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1584 				break;
1585 
1586 			/* realwow wake up */
1587 			_phl_cfg_pkt_ofld_realwow_wp_info(wow_info, &wakeup_info);
1588 
1589 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1590 					PKT_TYPE_REALWOW_WP,
1591 					&wow_info->realwow_info.wakeup_pattern_id,
1592 					(void *)&wakeup_info);
1593 
1594 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1595 				break;
1596 		}
1597 
1598 		if (wow_info->nlo_info.nlo_en) {
1599 
1600 			_phl_cfg_pkt_ofld_probe_req_info(wow_info, sta, &probe_req_info);
1601 
1602 			pstatus = _phl_wow_cfg_pkt_ofld(wow_info,
1603 					PKT_TYPE_PROBE_REQ,
1604 					&wow_info->nlo_info.probe_req_id,
1605 					(void *)&probe_req_info);
1606 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1607 				break;
1608 
1609 			pstatus = _phl_wow_cfg_nlo(wow_info);
1610 			if (pstatus != RTW_PHL_STATUS_SUCCESS)
1611 				break;
1612 		}
1613 
1614 		cfg.keep_alive_cfg = &wow_info->keep_alive_info;
1615 		cfg.disc_det_cfg = &wow_info->disc_det_info;
1616 		cfg.nlo_cfg = &wow_info->nlo_info;
1617 		cfg.arp_ofld_cfg = &wow_info->arp_ofld_info;
1618 		cfg.ndp_ofld_cfg = &wow_info->ndp_ofld_info;
1619 		cfg.gtk_ofld_cfg = &wow_info->gtk_ofld_info;
1620 		cfg.realwow_cfg = &wow_info->realwow_info;
1621 		cfg.wow_wake_cfg = &wow_info->wow_wake_info;
1622 		cfg.pattern_match_info = &wow_info->pattern_match_info;
1623 		cfg.wow_gpio = &wow_info->wow_gpio;
1624 
1625 		hstatus = rtw_hal_wow_func_en(phl_info->phl_com, phl_info->hal, sta->macid, &cfg);
1626 		if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1627 			PHL_ERR("rtw_hal_wow_func_en fail, status (%u)\n", hstatus);
1628 			pstatus = RTW_PHL_STATUS_FAILURE;
1629 			break;
1630 		}
1631 
1632 		hstatus = rtw_hal_wow_func_start(phl_info->phl_com, phl_info->hal, sta->macid, &cfg);
1633 		if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1634 			PHL_ERR("rtw_hal_wow_func_start fail, status (%u)\n", hstatus);
1635 			pstatus = RTW_PHL_STATUS_FAILURE;
1636 			break;
1637 		}
1638 
1639 		wow_info->func_en = true;
1640 		pstatus = RTW_PHL_STATUS_SUCCESS;
1641 
1642 	} while (0);
1643 
1644 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s status (%u).\n", __func__, pstatus);
1645 
1646 	return pstatus;
1647 }
1648 
phl_wow_func_dis(struct phl_wow_info * wow_info)1649 void phl_wow_func_dis(struct phl_wow_info *wow_info)
1650 {
1651 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1652 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1653 	struct phl_info_t *phl_info = wow_info->phl_info;
1654 	struct rtw_phl_stainfo_t *sta = wow_info->sta;
1655 	struct rtw_hal_wow_cfg cfg;
1656 
1657 	if (!wow_info->wow_wake_info.wow_en) {
1658 		PHL_WARN("%s : wow func is not enabled!\n", __func__);
1659 		return;
1660 	}
1661 
1662 	cfg.keep_alive_cfg = &wow_info->keep_alive_info;
1663 	cfg.disc_det_cfg = &wow_info->disc_det_info;
1664 	cfg.nlo_cfg = &wow_info->nlo_info;
1665 	cfg.arp_ofld_cfg = &wow_info->arp_ofld_info;
1666 	cfg.ndp_ofld_cfg = &wow_info->ndp_ofld_info;
1667 	cfg.gtk_ofld_cfg = &wow_info->gtk_ofld_info;
1668 	cfg.realwow_cfg = &wow_info->realwow_info;
1669 	cfg.wow_wake_cfg = &wow_info->wow_wake_info;
1670 	cfg.pattern_match_info = &wow_info->pattern_match_info;
1671 	cfg.wow_gpio = &wow_info->wow_gpio;
1672 
1673 	hstatus = rtw_hal_wow_func_dis(phl_info->phl_com, phl_info->hal, sta->macid,
1674 		&cfg);
1675 	if (hstatus != RTW_HAL_STATUS_SUCCESS)
1676 		PHL_ERR("rtw_hal_wow_func_dis fail, status (%u)\n", hstatus);
1677 
1678 	if (wow_info->keep_alive_info.keep_alive_en) {
1679 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1680 							PKT_TYPE_NULL_DATA, &wow_info->null_pkt_token);
1681 	}
1682 
1683 	if (wow_info->arp_ofld_info.arp_en) {
1684 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1685 							PKT_TYPE_ARP_RSP, &wow_info->arp_pkt_token);
1686 	}
1687 
1688 	if (wow_info->ndp_ofld_info.ndp_en) {
1689 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1690 							PKT_TYPE_NDP, &wow_info->ndp_pkt_token);
1691 	}
1692 
1693 	if (wow_info->gtk_ofld_info.gtk_en) {
1694 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1695 							PKT_TYPE_EAPOL_KEY, &wow_info->eapol_key_pkt_token);
1696 		if (wow_info->gtk_ofld_info.ieee80211w_en) {
1697 			phl_pkt_ofld_cancel(phl_info, sta->macid,
1698 								PKT_TYPE_SA_QUERY, &wow_info->sa_query_pkt_token);
1699 		}
1700 	}
1701 
1702 	if (wow_info->realwow_info.realwow_en) {
1703 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1704 					PKT_TYPE_REALWOW_KAPKT, &wow_info->kapkt_pkt_token);
1705 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1706 					PKT_TYPE_REALWOW_ACK, &wow_info->ack_pkt_token);
1707 		phl_pkt_ofld_cancel(phl_info, sta->macid,
1708 					PKT_TYPE_REALWOW_WP, &wow_info->wp_token);
1709 	}
1710 
1711 	if (wow_info->nlo_info.nlo_en) {
1712 
1713 		pstatus = phl_pkt_ofld_cancel(phl_info, sta->macid,
1714 					PKT_TYPE_PROBE_REQ, &wow_info->probe_req_pkt_token);
1715 
1716 		hstatus = rtw_hal_wow_cfg_nlo(phl_info->hal, SCAN_OFLD_OP_STOP,
1717 						sta->macid, sta->wrole->hw_band, sta->wrole->hw_port,
1718 						&wow_info->nlo_info);
1719 	}
1720 
1721 
1722 	hstatus = rtw_hal_wow_func_stop(phl_info->phl_com, phl_info->hal, sta->macid);
1723 	if (hstatus != RTW_HAL_STATUS_SUCCESS)
1724 		PHL_ERR("rtw_hal_wow_func_stop fail, status (%u)\n", hstatus);
1725 
1726 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s done.\n", __func__);
1727 }
1728 
phl_wow_decide_op_mode(struct phl_wow_info * wow_info,struct rtw_phl_stainfo_t * sta)1729 void phl_wow_decide_op_mode(struct phl_wow_info *wow_info, struct rtw_phl_stainfo_t *sta)
1730 {
1731 	u8 nlo_en = wow_info->nlo_info.nlo_en;
1732 	enum mlme_state mstat = sta->wrole->mstate;
1733 	struct rtw_ps_cap_t *ps_cap = _get_ps_cap(wow_info->phl_info);
1734 
1735 	wow_info->sta = sta;
1736 	wow_info->ps_pwr_lvl = PS_PWR_LVL_PWRON;
1737 
1738 	if (mstat == MLME_NO_LINK && !nlo_en) {
1739 		wow_info->op_mode = RTW_WOW_OP_PWR_DOWN;
1740 	} else if (mstat == MLME_NO_LINK && nlo_en) {
1741 		wow_info->op_mode = RTW_WOW_OP_DISCONNECT_STBY;
1742 		#ifdef CONFIG_POWER_SAVE
1743 		if (ps_cap->ips_wow_en)
1744 			wow_info->ps_pwr_lvl = phl_ps_judge_pwr_lvl(ps_cap->ips_wow_cap, PS_MODE_IPS, true);
1745 		#endif
1746 	} else if (mstat == MLME_LINKED) {
1747 		wow_info->op_mode = RTW_WOW_OP_CONNECT_STBY;
1748 		#ifdef CONFIG_POWER_SAVE
1749 		if (ps_cap->lps_wow_en)
1750 			wow_info->ps_pwr_lvl = phl_ps_judge_pwr_lvl(ps_cap->lps_wow_cap, PS_MODE_LPS, true);
1751 		#endif
1752 	} else {
1753 		wow_info->op_mode = RTW_WOW_OP_PWR_DOWN;
1754 	}
1755 
1756 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s op mode set to %d, pwr lvl %s.\n.",
1757 			  __func__, wow_info->op_mode, phl_ps_pwr_lvl_to_str(wow_info->ps_pwr_lvl));
1758 }
1759 
1760 #ifdef CONFIG_POWER_SAVE
1761 /**
1762  * phl_wow_ps_proto_cfg - set the ps protocol under wowlan
1763  * @wow_info: see struct phl_wow_info
1764  * @enter_ps: enter lps or not
1765  *
1766  * return enum rtw_phl_status
1767  */
phl_wow_ps_proto_cfg(struct phl_wow_info * wow_info,bool enter_ps)1768 enum rtw_phl_status phl_wow_ps_proto_cfg(struct phl_wow_info *wow_info, bool enter_ps)
1769 {
1770 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1771 	struct phl_info_t *phl_info = wow_info->phl_info;
1772 	struct ps_cfg cfg = {0};
1773 	struct rtw_ps_cap_t *ps_cap = _get_ps_cap(phl_info);
1774 
1775 	if (wow_info->op_mode == RTW_WOW_OP_DISCONNECT_STBY) {
1776 		/* IPS */
1777 		if (ps_cap->ips_wow_en) {
1778 			cfg.macid = wow_info->sta->macid;
1779 			pstatus = phl_ps_ips_cfg(phl_info, &cfg, enter_ps);
1780 		}
1781 	} else if (wow_info->op_mode == RTW_WOW_OP_CONNECT_STBY) {
1782 		/* LPS */
1783 		if (ps_cap->lps_wow_en) {
1784 			cfg.macid = wow_info->sta->macid;
1785 			cfg.awake_interval = ps_cap->lps_wow_awake_interval;
1786 			cfg.listen_bcn_mode = ps_cap->lps_wow_listen_bcn_mode;
1787 			cfg.smart_ps_mode = ps_cap->lps_wow_smart_ps_mode;
1788 			pstatus = phl_ps_lps_cfg(phl_info, &cfg, enter_ps);
1789 		}
1790 	} else {
1791 		PHL_ERR("%s : undefined wowlan op mode.\n", __func__);
1792 	}
1793 
1794 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : op mode %d, enter ps %d, pwr lvl %s.\n.",
1795 			  __func__, wow_info->op_mode, enter_ps, phl_ps_pwr_lvl_to_str(wow_info->ps_pwr_lvl));
1796 
1797 	return pstatus;
1798 }
1799 
1800 /**
1801  * phl_wow_ps_pwr_ntfy - notify the power level when enter low power
1802  * @wow_info: see struct phl_wow_info
1803  * @enter_ps: enter low power or not
1804  *
1805  */
phl_wow_ps_pwr_ntfy(struct phl_wow_info * wow_info,bool enter_ps)1806 void phl_wow_ps_pwr_ntfy(struct phl_wow_info *wow_info, bool enter_ps)
1807 {
1808 	struct phl_info_t *phl_info = wow_info->phl_info;
1809 
1810 	if (wow_info->ps_pwr_lvl == PS_PWR_LVL_PWRON)
1811 		return;
1812 
1813 	if (wow_info->op_mode == RTW_WOW_OP_DISCONNECT_STBY) {
1814 		/* IPS */
1815 	} else if (wow_info->op_mode == RTW_WOW_OP_CONNECT_STBY) {
1816 		#ifdef CONFIG_BTCOEX
1817 		rtw_hal_btc_radio_state_ntfy(phl_info->hal, (enter_ps == true ?
1818 							BTC_RFCTRL_FW_CTRL : BTC_RFCTRL_WL_ON));
1819 		#endif
1820 	} else {
1821 		PHL_ERR("%s : undefined wowlan op mode.\n", __func__);
1822 	}
1823 
1824 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : op mode %d, enter ps %d, pwr lvl %s.\n.",
1825 			  __func__, wow_info->op_mode, enter_ps, phl_ps_pwr_lvl_to_str(wow_info->ps_pwr_lvl));
1826 }
1827 
1828 
1829 /**
1830  * phl_wow_ps_pwr_cfg - set the low power level under wowlan
1831  * @wow_info: see struct phl_wow_info
1832  * @enter_ps: enter low power or not
1833  *
1834  * returns enum rtw_phl_status
1835  */
phl_wow_ps_pwr_cfg(struct phl_wow_info * wow_info,bool enter_ps)1836 enum rtw_phl_status phl_wow_ps_pwr_cfg(struct phl_wow_info *wow_info, bool enter_ps)
1837 {
1838 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1839 	struct phl_info_t *phl_info = wow_info->phl_info;
1840 
1841 	if (wow_info->ps_pwr_lvl == PS_PWR_LVL_PWRON)
1842 		return hstatus;
1843 
1844 	if (wow_info->op_mode == RTW_WOW_OP_DISCONNECT_STBY) {
1845 		hstatus = rtw_hal_ps_pwr_lvl_cfg(phl_info->phl_com, phl_info->hal,
1846 					(enter_ps == true ? wow_info->ps_pwr_lvl : PS_PWR_LVL_PWRON));
1847 	} else if (wow_info->op_mode == RTW_WOW_OP_CONNECT_STBY) {
1848 		hstatus = rtw_hal_ps_pwr_lvl_cfg(phl_info->phl_com, phl_info->hal,
1849 					(enter_ps == true ? wow_info->ps_pwr_lvl : PS_PWR_LVL_PWRON));
1850 	} else {
1851 		PHL_ERR("%s : undefined wowlan op mode.\n", __func__);
1852 	}
1853 
1854 	PHL_TRACE(COMP_PHL_WOW, _PHL_INFO_, "[wow] %s : op mode %d, enter ps %d, pwr lvl %s.\n.",
1855 			  __func__, wow_info->op_mode, enter_ps, phl_ps_pwr_lvl_to_str(wow_info->ps_pwr_lvl));
1856 
1857 	return (hstatus == RTW_HAL_STATUS_SUCCESS ?
1858 			RTW_PHL_STATUS_SUCCESS : RTW_PHL_STATUS_FAILURE);
1859 }
1860 #endif /* CONFIG_POWER_SAVE */
1861 
1862 #define case_rsn(rsn) \
1863 	case RTW_WOW_RSN_##rsn: return #rsn
1864 
rtw_phl_get_wow_rsn_str(void * phl,enum rtw_wow_wake_reason wake_rsn)1865 const char *rtw_phl_get_wow_rsn_str(void *phl, enum rtw_wow_wake_reason wake_rsn)
1866 {
1867 	switch (wake_rsn) {
1868 	case_rsn(UNKNOWN); /* RTW_WOW_RSN_UNKNOWN */
1869 	case_rsn(RX_PAIRWISEKEY);
1870 	case_rsn(RX_GTK);
1871 	case_rsn(RX_FOURWAY_HANDSHAKE);
1872 	case_rsn(RX_DISASSOC);
1873 	case_rsn(RX_DEAUTH);
1874 	case_rsn(RX_ARP_REQUEST);
1875 	case_rsn(RX_NS);
1876 	case_rsn(RX_EAPREQ_IDENTIFY);
1877 	case_rsn(FW_DECISION_DISCONNECT);
1878 	case_rsn(RX_MAGIC_PKT);
1879 	case_rsn(RX_UNICAST_PKT);
1880 	case_rsn(RX_PATTERN_PKT);
1881 	case_rsn(RTD3_SSID_MATCH);
1882 	case_rsn(RX_DATA_PKT);
1883 	case_rsn(RX_SSDP_MATCH);
1884 	case_rsn(RX_WSD_MATCH);
1885 	case_rsn(RX_SLP_MATCH);
1886 	case_rsn(RX_LLTD_MATCH);
1887 	case_rsn(RX_MDNS_MATCH);
1888 	case_rsn(RX_REALWOW_V2_WAKEUP_PKT);
1889 	case_rsn(RX_REALWOW_V2_ACK_LOST);
1890 	case_rsn(RX_REALWOW_V2_TX_KAPKT);
1891 	case_rsn(ENABLE_FAIL_DMA_IDLE);
1892 	case_rsn(ENABLE_FAIL_DMA_PAUSE);
1893 	case_rsn(RTIME_FAIL_DMA_IDLE);
1894 	case_rsn(RTIME_FAIL_DMA_PAUSE);
1895 	case_rsn(RX_SNMP_MISMATCHED_PKT);
1896 	case_rsn(RX_DESIGNATED_MAC_PKT);
1897 	case_rsn(NLO_SSID_MACH);
1898 	case_rsn(AP_OFFLOAD_WAKEUP);
1899 	case_rsn(DMAC_ERROR_OCCURRED);
1900 	case_rsn(EXCEPTION_OCCURRED);
1901 	case_rsn(L0_TO_L1_ERROR_OCCURRED);
1902 	case_rsn(ASSERT_OCCURRED);
1903 	case_rsn(L2_ERROR_OCCURRED);
1904 	case_rsn(WDT_TIMEOUT_WAKE);
1905 	case_rsn(RX_ACTION);
1906 	case_rsn(CLK_32K_UNLOCK);
1907 	case_rsn(CLK_32K_LOCK);
1908 	default:
1909 		return "UNDEFINED"; /* RTW_WOW_RSN_MAX */
1910 	}
1911 }
1912 
rtw_phl_cfg_wow_set_sw_gpio_mode(void * phl,struct rtw_wow_gpio_info * info)1913 enum rtw_phl_status rtw_phl_cfg_wow_set_sw_gpio_mode(void *phl, struct rtw_wow_gpio_info *info)
1914 {
1915 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1916 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1917 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
1918 	struct rtw_wow_gpio_info *wow_gpio = &wow_info->wow_gpio;
1919 
1920 	FUNCIN();
1921 
1922 	wow_gpio->dev2hst_gpio = info->dev2hst_gpio;
1923 	wow_gpio->dev2hst_gpio_mode = info->dev2hst_gpio_mode;
1924 	phl_status = rtw_hal_set_sw_gpio_mode(phl_info->phl_com, phl_info->hal
1925 		, wow_gpio->dev2hst_gpio_mode, wow_gpio->dev2hst_gpio);
1926 
1927 	PHL_INFO("%s, gpio=%d, gpio_mode=%d\n", __FUNCTION__
1928 		, wow_gpio->dev2hst_gpio, wow_gpio->dev2hst_gpio_mode);
1929 
1930 	return phl_status;
1931 }
1932 
rtw_phl_cfg_wow_sw_gpio_ctrl(void * phl,struct rtw_wow_gpio_info * info)1933 enum rtw_phl_status rtw_phl_cfg_wow_sw_gpio_ctrl(void *phl, struct rtw_wow_gpio_info *info)
1934 {
1935 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
1936 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1937 	struct phl_wow_info *wow_info = phl_to_wow_info(phl_info);
1938 	struct rtw_wow_gpio_info *wow_gpio = &wow_info->wow_gpio;
1939 
1940 	FUNCIN();
1941 
1942 	wow_gpio->dev2hst_high = info->dev2hst_high;
1943 	phl_status = rtw_hal_sw_gpio_ctrl(phl_info->phl_com, phl_info->hal
1944 		, wow_gpio->dev2hst_high, wow_gpio->dev2hst_gpio);
1945 
1946 	PHL_INFO("%s, gpio=%d, output=%d\n", __FUNCTION__
1947 		, wow_gpio->dev2hst_gpio, wow_gpio->dev2hst_high);
1948 
1949 	return phl_status;
1950 }
1951 
1952 #endif /* CONFIG_WOWLAN */
1953