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