1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 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 _RTW_WOW_C_
16
17 #include <drv_types.h>
18
19 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
20 #include <linux/inetdevice.h>
21 #define ETH_TYPE_OFFSET 12
22 #define PROTOCOL_OFFSET 23
23 #define IP_OFFSET 30
24 #define IPv6_OFFSET 38
25 #define IPv6_PROTOCOL_OFFSET 20
26 #endif
27
28 #ifdef CONFIG_WOWLAN
29
rtw_init_wow(_adapter * padapter)30 void rtw_init_wow(_adapter *padapter)
31 {
32 struct registry_priv *registry_par = &padapter->registrypriv;
33 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
34 struct wow_priv *wowpriv = adapter_to_wowlan(padapter);
35
36 #ifdef CONFIG_GPIO_WAKEUP
37 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
38 void *phl = GET_PHL_INFO(dvobj);
39 enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
40 struct rtw_wow_gpio_info *wow_gpio = &wowpriv->wow_gpio;
41 u8 toggle_pulse = DEV2HST_TOGGLE, gpio_time_unit = 1, gpio_pulse_count = 3, gpio_pulse_period = 10, gpio_pulse_dura = 5;
42 u8 gpio_pulse_en_a = 0, customer_id = 0, gpio_duration_unit_a = 0, gpio_pulse_count_a = 0, gpio_duration_a = 0, special_reason_a = 0;
43 #endif
44
45 #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
46 pwrctrlpriv->early_suspend.suspend = NULL;
47 rtw_register_early_suspend(pwrctrlpriv);
48 #endif /* CONFIG_HAS_EARLYSUSPEND || CONFIG_ANDROID_POWER */
49 pwrctrlpriv->wowlan_mode = _FALSE;
50 pwrctrlpriv->wowlan_ap_mode = _FALSE;
51 pwrctrlpriv->wowlan_p2p_mode = _FALSE;
52 pwrctrlpriv->wowlan_in_resume = _FALSE;
53 pwrctrlpriv->wowlan_last_wake_reason = 0;
54
55 #ifdef CONFIG_GPIO_WAKEUP
56 #ifdef ROKU_PRIVATE
57 gpio_pulse_en_a = DEV2HST_PULSE;
58 customer_id = 0x3f;
59 gpio_duration_unit_a = 1;
60 gpio_pulse_count_a = 1;
61 gpio_duration_a = 5;
62 special_reason_a = 0x21;
63 #endif /* ROKU_PRIVATE */
64 /*default low active*/
65 wow_gpio->gpio_active = HIGH_ACTIVE_DEV2HST;
66 pwrctrlpriv->hst2dev_high_active = HIGH_ACTIVE_HST2DEV;
67 wow_gpio->dev2hst_gpio = WAKEUP_GPIO_IDX;
68 wow_gpio->toggle_pulse = toggle_pulse;
69 wow_gpio->gpio_time_unit = gpio_time_unit;
70 wow_gpio->gpio_pulse_dura = gpio_pulse_dura;
71 wow_gpio->gpio_pulse_period = gpio_pulse_period;
72 wow_gpio->gpio_pulse_count = gpio_pulse_count;
73
74 wow_gpio->customer_id = customer_id;
75 wow_gpio->gpio_pulse_en_a = gpio_pulse_en_a;
76 wow_gpio->gpio_duration_unit_a = gpio_duration_unit_a;
77 wow_gpio->gpio_duration_a = gpio_duration_a;
78 wow_gpio->special_reason_a = special_reason_a;
79 wow_gpio->gpio_pulse_count_a = gpio_pulse_count_a;
80
81 #ifdef CONFIG_RTW_ONE_PIN_GPIO
82 wow_gpio->dev2hst_gpio_mode = RTW_AX_SW_IO_MODE_INPUT;
83 status = rtw_phl_cfg_wow_set_sw_gpio_mode(phl, wow_gpio);
84 #else
85 #ifdef CONFIG_WAKEUP_GPIO_INPUT_MODE
86 wow_gpio->dev2hst_gpio_mode = RTW_AX_SW_IO_MODE_OUTPUT_OD;
87 #else
88 wow_gpio->dev2hst_gpio_mode = RTW_AX_SW_IO_MODE_OUTPUT_PP;
89 #endif /*CONFIG_WAKEUP_GPIO_INPUT_MODE*/
90 /* switch GPIO to open-drain or push-pull */
91 status = rtw_phl_cfg_wow_set_sw_gpio_mode(phl, wow_gpio);
92 wow_gpio->dev2hst_high = wow_gpio->gpio_active == 0 ? 1 : 0;
93 status = rtw_phl_cfg_wow_sw_gpio_ctrl(phl, wow_gpio);
94 RTW_INFO("%s: set GPIO_%d %d as default. status=%d\n",
95 __func__, WAKEUP_GPIO_IDX, wow_gpio->dev2hst_high, status);
96 #endif /* CONFIG_RTW_ONE_PIN_GPIO */
97 #endif /* CONFIG_GPIO_WAKEUP */
98
99 #ifdef CONFIG_WOWLAN
100 #ifdef CONFIG_LPS_1T1R
101 #define WOW_LPS_1T1R_FMT ", WOW_LPS_1T1R=%d"
102 #define WOW_LPS_1T1R_ARG , pwrctrlpriv->wowlan_lps_1t1r
103 #else
104 #define WOW_LPS_1T1R_FMT ""
105 #define WOW_LPS_1T1R_ARG
106 #endif
107
108 pwrctrlpriv->wowlan_power_mgmt = padapter->registrypriv.wow_power_mgnt;
109 pwrctrlpriv->wowlan_lps_level = padapter->registrypriv.wow_lps_level;
110 #ifdef CONFIG_LPS_1T1R
111 pwrctrlpriv->wowlan_lps_1t1r = padapter->registrypriv.wow_lps_1t1r;
112 #endif
113
114 RTW_INFO("%s: WOW_LPS_mode=%d, WOW_LPS_level=%d"WOW_LPS_1T1R_FMT"\n",
115 __func__, pwrctrlpriv->wowlan_power_mgmt, pwrctrlpriv->wowlan_lps_level
116 WOW_LPS_1T1R_ARG
117 );
118
119 if (!(registry_par->wakeup_event & BIT(3)))
120 rtw_wow_pattern_clean(padapter, RTW_CUSTOMIZED_PATTERN);
121
122 rtw_wow_pattern_clean(padapter, RTW_DEFAULT_PATTERN);
123
124 _rtw_mutex_init(&pwrctrlpriv->wowlan_pattern_cam_mutex);
125
126 pwrctrlpriv->wowlan_aoac_rpt_loc = 0;
127 #endif /* CONFIG_WOWLAN */
128
129 }
130
rtw_free_wow(_adapter * adapter)131 void rtw_free_wow(_adapter *adapter)
132 {
133 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(adapter);
134
135 _rtw_mutex_free(&pwrctrlpriv->wowlan_pattern_cam_mutex);
136
137 #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
138 rtw_unregister_early_suspend(pwrctrlpriv);
139 #endif /* CONFIG_HAS_EARLYSUSPEND || CONFIG_ANDROID_POWER */
140 }
141
rtw_wowlan_set_pattern_cast_type(_adapter * adapter,struct rtw_wowcam_upd_info * wowcam_info)142 void rtw_wowlan_set_pattern_cast_type(_adapter *adapter, struct rtw_wowcam_upd_info *wowcam_info)
143 {
144 if (is_broadcast_mac_addr(wowcam_info->ptrn))
145 wowcam_info->bc = 1;
146 else if (is_multicast_mac_addr(wowcam_info->ptrn))
147 wowcam_info->mc = 1;
148 else if (!memcmp(wowcam_info->ptrn, adapter_mac_addr(adapter), ETH_ALEN))
149 wowcam_info->uc = 1;
150 }
151
_rtw_wow_chk_cap(_adapter * adapter,u8 cap)152 inline bool _rtw_wow_chk_cap(_adapter *adapter, u8 cap)
153 {
154 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
155 struct wow_ctl_t *wow_ctl = &dvobj->wow_ctl;
156
157 if (wow_ctl->wow_cap & cap)
158 return _TRUE;
159 return _FALSE;
160 }
rtw_wowlan_parser_pattern_cmd(u8 * input,char * pattern,int * pattern_len,char * bit_mask)161 bool rtw_wowlan_parser_pattern_cmd(u8 *input, char *pattern,
162 int *pattern_len, char *bit_mask)
163 {
164 char *cp = NULL;
165 size_t len = 0;
166 int pos = 0, mask_pos = 0, res = 0;
167 u8 member[2] = {0};
168
169 /* To get the pattern string after "=", when we use :
170 * iwpriv wlanX pattern=XX:XX:..:XX
171 */
172 cp = strchr(input, '=');
173 if (cp) {
174 *cp = 0;
175 cp++;
176 input = cp;
177 }
178
179 /* To take off the newline character '\n'(0x0a) at the end of pattern string,
180 * when we use echo xxxx > /proc/xxxx
181 */
182 cp = strchr(input, '\n');
183 if (cp)
184 *cp = 0;
185
186 while (input) {
187 cp = strsep((char **)(&input), ":");
188
189 if (bit_mask && (strcmp(cp, "-") == 0 ||
190 strcmp(cp, "xx") == 0 ||
191 strcmp(cp, "--") == 0)) {
192 /* skip this byte and leave mask bit unset */
193 } else {
194 u8 hex;
195
196 if (strlen(cp) != 2) {
197 RTW_ERR("%s:[ERROR] hex len != 2, input=[%s]\n",
198 __func__, cp);
199 goto error;
200 }
201
202 if (hexstr2bin(cp, &hex, 1) < 0) {
203 RTW_ERR("%s:[ERROR] pattern is invalid, input=[%s]\n",
204 __func__, cp);
205 goto error;
206 }
207
208 pattern[pos] = hex;
209 mask_pos = pos / 8;
210 if (bit_mask)
211 bit_mask[mask_pos] |= 1 << (pos % 8);
212 }
213
214 pos++;
215 }
216
217 (*pattern_len) = pos;
218
219 return _TRUE;
220 error:
221 return _FALSE;
222 }
223
rtw_wow_pattern_set(_adapter * adapter,struct rtw_wowcam_upd_info * wowcam_info,enum pattern_type set_type)224 u8 rtw_wow_pattern_set(_adapter *adapter, struct rtw_wowcam_upd_info *wowcam_info,
225 enum pattern_type set_type)
226 {
227 struct wow_priv *wowpriv = adapter_to_wowlan(adapter);
228 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
229 void *phl = GET_PHL_INFO(dvobj);
230 enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
231 u8 cam_idx = MAX_WKFM_CAM_NUM;
232
233 rtw_wowlan_set_pattern_cast_type(adapter, wowcam_info);
234 status = rtw_phl_add_wow_ptrn_info(phl, wowcam_info, &cam_idx);
235 if (status != RTW_PHL_STATUS_SUCCESS) {
236 RTW_INFO("Add wow pattern fail(%d)\n", status);
237 return _FAIL;
238 }
239
240 wowpriv->wow_ptrn_valid[cam_idx] = set_type;
241
242 RTW_INFO("wowcam_id: %d, type: %d\n", cam_idx, set_type);
243
244 return _SUCCESS;
245 }
246
rtw_wow_pattern_clean(_adapter * adapter,enum pattern_type clean_type)247 void rtw_wow_pattern_clean(_adapter *adapter, enum pattern_type clean_type)
248 {
249 struct wow_priv *wowpriv = adapter_to_wowlan(adapter);
250 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
251 void *phl = GET_PHL_INFO(dvobj);
252 u8 cam_idx;
253
254 for (cam_idx = 0; cam_idx < MAX_WKFM_CAM_NUM; cam_idx++) {
255 if (wowpriv->wow_ptrn_valid[cam_idx] == clean_type) {
256 rtw_phl_remove_wow_ptrn_info(phl, cam_idx);
257 wowpriv->wow_ptrn_valid[cam_idx] = RTW_INVALID_PATTERN;
258 }
259 }
260 }
261
rtw_set_default_pattern(_adapter * adapter)262 void rtw_set_default_pattern(_adapter *adapter)
263 {
264 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
265 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
266 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
267 struct rtw_wowcam_upd_info wowcam_info = {0};
268 u8 index = 0;
269 u8 multicast_addr[3] = {0x01, 0x00, 0x5e};
270 u8 multicast_ip[4] = {0xe0, 0x28, 0x28, 0x2a};
271
272 u8 unicast_mask[5] = {0x3f, 0x70, 0x80, 0xc0, 0x03};
273 u8 icmpv6_mask[7] = {0x00, 0x70, 0x10, 0x00, 0xc0, 0xc0, 0x3f};
274 u8 multicast_mask[5] = {0x07, 0x70, 0x80, 0xc0, 0x03};
275
276 u8 ip_protocol[3] = {0x08, 0x00, 0x45};
277 u8 ipv6_protocol[3] = {0x86, 0xdd, 0x60};
278
279 u8 *target = NULL;
280
281 /*TCP/ICMP unicast*/
282 for (index = 0 ; index < DEFAULT_PATTERN_NUM ; index++) {
283 _rtw_memset((void *)&wowcam_info, 0, sizeof(wowcam_info));
284
285 switch (index) {
286 case 0:
287 target = wowcam_info.ptrn;
288 _rtw_memcpy(target, adapter_mac_addr(adapter), ETH_ALEN);
289
290 target += ETH_TYPE_OFFSET;
291 _rtw_memcpy(target, &ip_protocol, sizeof(ip_protocol));
292
293 /* TCP */
294 target += (PROTOCOL_OFFSET - ETH_TYPE_OFFSET);
295 _rtw_memset(target, 0x06, 1);
296
297 target += (IP_OFFSET - PROTOCOL_OFFSET);
298
299 _rtw_memcpy(target, pmlmeinfo->ip_addr, RTW_IP_ADDR_LEN);
300
301 _rtw_memcpy(wowcam_info.mask,
302 &unicast_mask, sizeof(unicast_mask));
303
304 wowcam_info.ptrn_len = IP_OFFSET + RTW_IP_ADDR_LEN;
305
306 rtw_wow_pattern_set(adapter, &wowcam_info, RTW_DEFAULT_PATTERN);
307
308 break;
309 case 1:
310 target = wowcam_info.ptrn;
311 _rtw_memcpy(target, adapter_mac_addr(adapter), ETH_ALEN);
312
313 target += ETH_TYPE_OFFSET;
314 _rtw_memcpy(target, &ip_protocol, sizeof(ip_protocol));
315
316 /* ICMP */
317 target += (PROTOCOL_OFFSET - ETH_TYPE_OFFSET);
318 _rtw_memset(target, 0x01, 1);
319
320 target += (IP_OFFSET - PROTOCOL_OFFSET);
321 _rtw_memcpy(target, pmlmeinfo->ip_addr, RTW_IP_ADDR_LEN);
322
323 _rtw_memcpy(wowcam_info.mask,
324 &unicast_mask, sizeof(unicast_mask));
325
326 wowcam_info.ptrn_len = IP_OFFSET + RTW_IP_ADDR_LEN;
327
328 rtw_wow_pattern_set(adapter, &wowcam_info, RTW_DEFAULT_PATTERN);
329
330 break;
331 #ifdef CONFIG_IPV6
332 case 2:
333 if (pwrpriv->wowlan_ns_offload_en == _TRUE) {
334 target = wowcam_info.ptrn;
335 target += ETH_TYPE_OFFSET;
336
337 _rtw_memcpy(target, &ipv6_protocol,
338 sizeof(ipv6_protocol));
339
340 /* ICMPv6 */
341 target += (IPv6_PROTOCOL_OFFSET -
342 ETH_TYPE_OFFSET);
343 _rtw_memset(target, 0x3a, 1);
344
345 target += (IPv6_OFFSET - IPv6_PROTOCOL_OFFSET);
346 _rtw_memcpy(target, pmlmeinfo->ip6_addr,
347 RTW_IPv6_ADDR_LEN);
348
349 _rtw_memcpy(wowcam_info.mask,
350 &icmpv6_mask, sizeof(icmpv6_mask));
351
352 wowcam_info.ptrn_len = IPv6_OFFSET + RTW_IPv6_ADDR_LEN;
353
354 rtw_wow_pattern_set(adapter, &wowcam_info,
355 RTW_DEFAULT_PATTERN);
356 }
357 break;
358 #endif /*CONFIG_IPV6*/
359 case 3:
360 target = wowcam_info.ptrn;
361 _rtw_memcpy(target, &multicast_addr, sizeof(multicast_addr));
362
363 target += ETH_TYPE_OFFSET;
364 _rtw_memcpy(target, &ip_protocol, sizeof(ip_protocol));
365
366 /* UDP */
367 target += (PROTOCOL_OFFSET - ETH_TYPE_OFFSET);
368 _rtw_memset(target, 0x11, 1);
369
370 target += (IP_OFFSET - PROTOCOL_OFFSET);
371 _rtw_memcpy(target, &multicast_ip, sizeof(multicast_ip));
372
373 _rtw_memcpy(wowcam_info.mask,
374 &multicast_mask, sizeof(multicast_mask));
375
376 wowcam_info.ptrn_len = IP_OFFSET + sizeof(multicast_ip);
377
378 rtw_wow_pattern_set(adapter, &wowcam_info, RTW_DEFAULT_PATTERN);
379
380 break;
381 default:
382 break;
383 }
384 }
385
386 return;
387 }
388
rtw_dump_priv_pattern(_adapter * adapter,u8 idx)389 void rtw_dump_priv_pattern(_adapter *adapter, u8 idx)
390 {
391 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
392 char str_1[128];
393 char *p_str;
394 u8 val8 = 0;
395 int i = 0, j = 0, len = 0, max_len = 0;
396
397 RTW_INFO("=========[%d]========\n", idx);
398
399 RTW_INFO(">>>priv_pattern_content:\n");
400 p_str = str_1;
401 max_len = sizeof(str_1);
402 for (i = 0 ; i < MAX_WKFM_PATTERN_SIZE / 8 ; i++) {
403 _rtw_memset(p_str, 0, max_len);
404 len = 0;
405 for (j = 0 ; j < 8 ; j++) {
406 val8 = pwrctl->patterns[idx].content[i * 8 + j];
407 len += snprintf(p_str + len, max_len - len,
408 "%02x ", val8);
409 }
410 RTW_INFO("%s\n", p_str);
411 }
412
413 RTW_INFO(">>>priv_pattern_mask:\n");
414 for (i = 0 ; i < MAX_WKFM_SIZE / 8 ; i++) {
415 _rtw_memset(p_str, 0, max_len);
416 len = 0;
417 for (j = 0 ; j < 8 ; j++) {
418 val8 = pwrctl->patterns[idx].mask[i * 8 + j];
419 len += snprintf(p_str + len, max_len - len,
420 "%02x ", val8);
421 }
422 RTW_INFO("%s\n", p_str);
423 }
424
425 RTW_INFO(">>>priv_pattern_len:\n");
426 RTW_INFO("%s: len: %d\n", __func__, pwrctl->patterns[idx].len);
427 }
428
rtw_wow_pattern_sw_dump(_adapter * adapter)429 void rtw_wow_pattern_sw_dump(_adapter *adapter)
430 {
431 int i;
432
433 RTW_INFO("********[RTK priv-patterns]*********\n");
434 for (i = 0 ; i < MAX_WKFM_CAM_NUM; i++)
435 rtw_dump_priv_pattern(adapter, i);
436 }
437
rtw_get_sec_iv(_adapter * padapter,u8 * pcur_dot11txpn,u8 * StaAddr)438 void rtw_get_sec_iv(_adapter *padapter, u8 *pcur_dot11txpn, u8 *StaAddr)
439 {
440 struct sta_info *psta;
441 struct security_priv *psecpriv = &padapter->securitypriv;
442
443 _rtw_memset(pcur_dot11txpn, 0, 8);
444 if (NULL == StaAddr)
445 return;
446 psta = rtw_get_stainfo(&padapter->stapriv, StaAddr);
447 RTW_INFO("%s(): StaAddr: %02x %02x %02x %02x %02x %02x\n",
448 __func__, StaAddr[0], StaAddr[1], StaAddr[2],
449 StaAddr[3], StaAddr[4], StaAddr[5]);
450
451 if (psta) {
452 if ((psecpriv->dot11PrivacyAlgrthm == _AES_) ||
453 (psecpriv->dot11PrivacyAlgrthm == _CCMP_256_))
454 AES_IV(pcur_dot11txpn, psta->dot11txpn, 0);
455 else if (psecpriv->dot11PrivacyAlgrthm == _TKIP_)
456 TKIP_IV(pcur_dot11txpn, psta->dot11txpn, 0);
457 else if ((psecpriv->dot11PrivacyAlgrthm == _GCMP_) ||
458 (psecpriv->dot11PrivacyAlgrthm == _GCMP_256_))
459 GCMP_IV(pcur_dot11txpn, psta->dot11txpn, 0);
460 }
461 }
462
rtw_construct_remote_control_info(_adapter * adapter,struct rtw_remote_wake_ctrl_info * ctrl_info)463 void rtw_construct_remote_control_info(_adapter *adapter,
464 struct rtw_remote_wake_ctrl_info *ctrl_info)
465 {
466 struct security_priv *securitypriv = &adapter->securitypriv;
467 struct stainfo_rxcache *rxcache = NULL;
468 struct sta_info *sta = NULL;
469 u8 gtk_rx_iv[4][IV_LENGTH] = {0};
470 u8 tid_id = 0;
471 u8 i = 0;
472
473 sta = rtw_get_stainfo(&adapter->stapriv, get_bssid(&adapter->mlmepriv));
474
475 if (!sta) {
476 rtw_warn_on(1);
477 return;
478 }
479
480 rxcache = &sta->sta_recvpriv.rxcache;
481
482 rtw_get_sec_iv(adapter, ctrl_info->ptk_tx_iv, get_bssid(&adapter->mlmepriv));
483 RTW_INFO("[wow] ptk_tx_iv = " IV_FMT "\n", IV_ARG(ctrl_info->ptk_tx_iv));
484
485 ctrl_info->valid_check = REMOTECTRL_INFO_VALID_CHECK;
486 ctrl_info->symbol_check_en |= REMOTECTRL_INFO_SYMBOL_CHK_PTK |
487 REMOTECTRL_INFO_SYMBOL_CHK_GTK;
488
489 ctrl_info->gtk_key_idx = securitypriv->dot118021XGrpKeyid;
490 RTW_INFO("[wow] gtk_key_idx = %d\n", ctrl_info->gtk_key_idx);
491
492 tid_id = rxcache->last_tid;
493 _rtw_memcpy(ctrl_info->ptk_rx_iv, rxcache->iv[tid_id], IV_LENGTH);
494 RTW_INFO("[wow] ptk_rx_iv = " IV_FMT "\n", IV_ARG(ctrl_info->ptk_rx_iv));
495
496 for (i = 0; i < 4; i++) {
497 rtw_pn_to_iv(securitypriv->iv_seq[i], gtk_rx_iv[i], i,
498 securitypriv->dot118021XGrpPrivacy);
499 RTW_INFO("[wow] gtk_rx_iv[%u] = " IV_FMT "\n", i, IV_ARG(gtk_rx_iv[i]));
500 }
501 _rtw_memcpy(ctrl_info->gtk_rx_iv_idx0, gtk_rx_iv[0], IV_LENGTH);
502 _rtw_memcpy(ctrl_info->gtk_rx_iv_idx1, gtk_rx_iv[1], IV_LENGTH);
503 _rtw_memcpy(ctrl_info->gtk_rx_iv_idx2, gtk_rx_iv[2], IV_LENGTH);
504 _rtw_memcpy(ctrl_info->gtk_rx_iv_idx3, gtk_rx_iv[3], IV_LENGTH);
505 }
506
rtw_wow_lps_level_decide(_adapter * adapter,u8 wow_en)507 void rtw_wow_lps_level_decide(_adapter *adapter, u8 wow_en)
508 {
509 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
510 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
511
512 if (wow_en) {
513 pwrpriv->lps_level_bk = pwrpriv->lps_level;
514 pwrpriv->lps_level = pwrpriv->wowlan_lps_level;
515 #ifdef CONFIG_LPS_1T1R
516 pwrpriv->lps_1t1r_bk = pwrpriv->lps_1t1r;
517 pwrpriv->lps_1t1r = pwrpriv->wowlan_lps_1t1r;
518 #endif
519 } else {
520 pwrpriv->lps_level = pwrpriv->lps_level_bk;
521 #ifdef CONFIG_LPS_1T1R
522 pwrpriv->lps_1t1r = pwrpriv->lps_1t1r_bk;
523 #endif
524 }
525 }
526
rtw_pm_set_wow_lps(_adapter * padapter,u8 mode)527 int rtw_pm_set_wow_lps(_adapter *padapter, u8 mode)
528 {
529 int ret = 0;
530 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
531
532 if (mode < PM_PS_MODE_NUM) {
533 if (pwrctrlpriv->wowlan_power_mgmt != mode)
534 pwrctrlpriv->wowlan_power_mgmt = mode;
535 } else
536 ret = -EINVAL;
537
538 return ret;
539 }
rtw_pm_set_wow_lps_level(_adapter * padapter,u8 level)540 int rtw_pm_set_wow_lps_level(_adapter *padapter, u8 level)
541 {
542 int ret = 0;
543 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
544
545 if (level < LPS_LEVEL_MAX)
546 pwrctrlpriv->wowlan_lps_level = level;
547 else
548 ret = -EINVAL;
549
550 return ret;
551 }
552 #ifdef CONFIG_LPS_1T1R
rtw_pm_set_wow_lps_1t1r(_adapter * padapter,u8 en)553 int rtw_pm_set_wow_lps_1t1r(_adapter *padapter, u8 en)
554 {
555 int ret = 0;
556 struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
557
558 en = en ? 1 : 0;
559 pwrctrlpriv->wowlan_lps_1t1r = en;
560
561 return ret;
562 }
563 #endif /* CONFIG_LPS_1T1R */
564
565 #ifdef CONFIG_GTK_OL
_update_aoac_rpt_phase_0(_adapter * adapter,struct rtw_aoac_report * aoac_info)566 void _update_aoac_rpt_phase_0(_adapter *adapter, struct rtw_aoac_report *aoac_info)
567 {
568 struct security_priv *securitypriv = &adapter->securitypriv;
569 struct stainfo_rxcache *rxcache = NULL;
570 struct sta_info *sta = NULL;
571 u8 pn[8] = {0};
572 u8 gtk_key_idx = 0;
573 u8 i = 0;
574
575 /* handle ptk rx iv */
576 /* This Rx IV has no effect, the driver does not drop unicast packets
577 * due to different PNs. (Refer to recv_ucast_pn_decache)
578 */
579 sta = rtw_get_stainfo(&adapter->stapriv, get_bssid(&adapter->mlmepriv));
580 if (sta) {
581 if (rtw_iv_to_pn(aoac_info->ptk_rx_iv, pn, NULL,
582 securitypriv->dot11PrivacyAlgrthm)) {
583 rxcache = &sta->sta_recvpriv.rxcache;
584 for (i = 0; i < TID_NUM; i++)
585 _rtw_memcpy(rxcache->iv[i], aoac_info->ptk_rx_iv,
586 IV_LENGTH);
587 sta->dot11rxpn.val = RTW_GET_LE64(pn);
588 RTW_INFO("[wow] ptk_rx_pn = " PN_FMT "\n", PN_ARG(pn));
589 }
590 }
591
592 /* handle gtk rx iv */
593 gtk_key_idx = aoac_info->key_idx;
594 if (rtw_iv_to_pn(aoac_info->gtk_rx_iv[gtk_key_idx], pn, NULL,
595 securitypriv->dot118021XGrpPrivacy)) {
596 _rtw_memcpy(securitypriv->iv_seq[gtk_key_idx], pn, 8);
597 RTW_INFO("[wow] gtk_rx_pn[%u] = " PN_FMT "\n", gtk_key_idx, PN_ARG(pn));
598 }
599 }
600
_update_aoac_rpt_phase_1(_adapter * adapter,struct rtw_aoac_report * aoac_info)601 void _update_aoac_rpt_phase_1(_adapter *adapter, struct rtw_aoac_report *aoac_info)
602 {
603 struct security_priv *securitypriv = &adapter->securitypriv;
604 struct sta_info *sta = NULL;
605 u8 pn[8] = {0};
606 u8 gtk_key_idx = 0;
607 u8 key_len = 0;
608 u8 i = 0;
609
610 /* handle ptk tx iv */
611 sta = rtw_get_stainfo(&adapter->stapriv, get_bssid(&adapter->mlmepriv));
612 if (sta) {
613 if (rtw_iv_to_pn(aoac_info->ptk_tx_iv, pn, NULL,
614 securitypriv->dot11PrivacyAlgrthm)) {
615 sta->dot11txpn.val = RTW_GET_LE64(pn);
616 RTW_INFO("[wow] ptk_tx_pn = " PN_FMT "\n", PN_ARG(pn));
617 }
618 }
619
620 if (aoac_info->rekey_ok) {
621 /* update gtk key */
622 gtk_key_idx = aoac_info->key_idx;
623 securitypriv->dot118021XGrpKeyid = gtk_key_idx;
624
625 switch (securitypriv->dot118021XGrpPrivacy) {
626 case _TKIP_:
627 case _AES_:
628 case _GCMP_:
629 key_len = 16;
630 break;
631 case _GCMP_256_:
632 case _CCMP_256_:
633 key_len = 32;
634 break;
635 default:
636 key_len = 0;
637 }
638
639 if (key_len)
640 _rtw_memcpy(securitypriv->dot118021XGrpKey[gtk_key_idx].skey,
641 aoac_info->gtk, key_len);
642 /* update tkip dot118021XGrptxmickey dot118021XGrprxmickey */
643 if (securitypriv->dot118021XGrpPrivacy == _TKIP_) {
644 /* The order of the GTK Tx/Rx mic keys in the AOAC report is
645 * reversed compared to the GTK Tx/Rx mic keys provided by
646 * wpa_supplicant.
647 */
648 _rtw_memcpy(securitypriv->dot118021XGrptxmickey[gtk_key_idx].skey,
649 &aoac_info->gtk[24], 8);
650 _rtw_memcpy(securitypriv->dot118021XGrprxmickey[gtk_key_idx].skey,
651 &aoac_info->gtk[16], 8);
652 }
653 rtw_set_key(adapter, securitypriv, gtk_key_idx, 1, _TRUE);
654
655 /* update eapol replay_counter */
656 _rtw_memcpy(sta->replay_ctr, aoac_info->eapol_key_replay_count,
657 RTW_REPLAY_CTR_LEN);
658 } else {
659 RTW_INFO("[wow] no rekey event\n");
660 }
661
662 for (i = 0; i < 4; i++) {
663 if (rtw_iv_to_pn(aoac_info->gtk_rx_iv[i], pn, NULL,
664 securitypriv->dot118021XGrpPrivacy)) {
665 _rtw_memcpy(securitypriv->iv_seq[i], pn, 8);
666 RTW_INFO("[wow] gtk_rx_pn[%u] = " PN_FMT "\n", i, PN_ARG(pn));
667 }
668 }
669 }
670
rtw_update_gtk_ofld_info(void * drv_priv,struct rtw_aoac_report * aoac_info,u8 aoac_report_get_ok,u8 rx_ready)671 void rtw_update_gtk_ofld_info(void *drv_priv, struct rtw_aoac_report *aoac_info,
672 u8 aoac_report_get_ok, u8 rx_ready)
673 {
674 struct dvobj_priv *dvobj = (struct dvobj_priv *)drv_priv;
675 _adapter *adapter = dvobj_get_primary_adapter(dvobj);
676
677 if (!rx_ready)
678 _update_aoac_rpt_phase_0(adapter, aoac_info);
679 else
680 _update_aoac_rpt_phase_1(adapter, aoac_info);
681 }
682 #endif /* CONFIG_GTK_OL */
683 #endif /* CONFIG_WOWLAN */
684
685 #ifdef CONFIG_PNO_SUPPORT
nlo_scan_ch_init(struct rtw_nlo_info * wow_nlo,struct ieee80211_channel ** channels,u32 n_channels)686 static void nlo_scan_ch_init(struct rtw_nlo_info *wow_nlo,
687 struct ieee80211_channel **channels,
688 u32 n_channels)
689 {
690 u8 i = 0;
691
692 while (i < MAX_NLO_CHANNEL && i < n_channels) {
693 wow_nlo->channel_list[i].bw = CHANNEL_WIDTH_20;
694 wow_nlo->channel_list[i].center_chan = channels[i]->hw_value;
695 wow_nlo->channel_list[i].chan = channels[i]->hw_value;
696 wow_nlo->channel_list[i].period = 100;
697 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
698 if (channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN)
699 #else
700 if (channels[i]->flags & IEEE80211_CHAN_NO_IR)
701 #endif
702 wow_nlo->channel_list[i].tx_pkt = 0;
703 else
704 wow_nlo->channel_list[i].tx_pkt = 1;
705 wow_nlo->channel_list[i].tx_data_pause = 1;
706 i++;
707 }
708 wow_nlo->channel_num = i;
709 }
710
nlo_ssid_init(struct rtw_nlo_info * wow_nlo,struct cfg80211_ssid * ssids,int n_ssids)711 static void nlo_ssid_init(struct rtw_nlo_info *wow_nlo,
712 struct cfg80211_ssid *ssids, int n_ssids)
713 {
714 u8 i = 0;
715
716 while (i < MAX_NLO_NUM && i < n_ssids) {
717 _rtw_memcpy((void *)wow_nlo->ssid[i], (void *)ssids[i].ssid,
718 ssids[i].ssid_len);
719 wow_nlo->ssidlen[i] = ssids[i].ssid_len;
720 i++;
721 }
722
723 wow_nlo->num_of_networks = i;
724 wow_nlo->num_of_hidden_ap = i;
725 }
726
rtw_nlo_enable(struct net_device * net,struct cfg80211_ssid * ssids,int n_ssids,struct ieee80211_channel ** channels,u32 n_channels,u32 delay,u32 interval,u32 iterations,u32 slow_interval)727 int rtw_nlo_enable(struct net_device *net, struct cfg80211_ssid *ssids,
728 int n_ssids, struct ieee80211_channel **channels,
729 u32 n_channels, u32 delay, u32 interval, u32 iterations,
730 u32 slow_interval)
731 {
732 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
733 struct wow_priv *wowpriv = adapter_to_wowlan(padapter);
734 struct rtw_nlo_info *wow_nlo = &wowpriv->wow_nlo;
735
736 _rtw_memset((void *)wow_nlo, 0, sizeof(struct rtw_nlo_info));
737
738 wow_nlo->nlo_en = _TRUE;
739
740 nlo_scan_ch_init(wow_nlo, channels, n_channels);
741 nlo_ssid_init(wow_nlo, ssids, n_ssids);
742
743 wow_nlo->delay = delay * 1000;
744 wow_nlo->period = interval * 1000;
745 wow_nlo->cycle = iterations;
746 wow_nlo->slow_period = slow_interval * 1000;
747 wow_nlo->construct_pbreq = NULL;;
748
749 rtw_nlo_debug(net);
750
751 return 0;
752 }
753
rtw_nlo_disable(struct net_device * net)754 int rtw_nlo_disable(struct net_device *net)
755 {
756 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
757 struct wow_priv *wowpriv = adapter_to_wowlan(padapter);
758 struct rtw_nlo_info *wow_nlo = &wowpriv->wow_nlo;
759
760 wow_nlo->nlo_en = _FALSE;
761
762 return 0;
763 }
764
rtw_nlo_debug(struct net_device * net)765 void rtw_nlo_debug(struct net_device *net)
766 {
767 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
768 struct wow_priv *wowpriv = adapter_to_wowlan(padapter);
769 struct rtw_nlo_info *wow_nlo = &wowpriv->wow_nlo;
770 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
771 int i;
772
773 RTW_INFO("********NLO_INFO********\n");
774 RTW_INFO("ssid_num: %d\n", wow_nlo->num_of_networks);
775 for (i = 0; i < wow_nlo->num_of_networks; i++) {
776 RTW_INFO("%d SSID (%s) length (%d)\n",
777 i, wow_nlo->ssid[i], wow_nlo->ssidlen[i]);
778 }
779 RTW_INFO("delay: %d\n", wow_nlo->delay);
780 RTW_INFO("fast_scan_iterations: %d\n", wow_nlo->cycle);
781 RTW_INFO("fast_scan_period: %d\n", wow_nlo->period);
782 RTW_INFO("slow_scan_period: %d\n", wow_nlo->slow_period);
783
784 RTW_INFO("********SCAN_INFO*******\n");
785 RTW_INFO("ch_num: %d\n", wow_nlo->channel_num);
786 for (i = 0 ;i < wow_nlo->channel_num; i++) {
787 RTW_INFO("[%02d] avtive:%d, timeout:%d, ch:%02d\n",
788 i, wow_nlo->channel_list[i].tx_pkt,
789 wow_nlo->channel_list[i].period,
790 wow_nlo->channel_list[i].chan);
791 }
792 RTW_INFO("************************\n");
793 }
794 #endif /* CONFIG_PNO_SUPPORT */
795
796