xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/core/rtw_wow.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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