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