xref: /freebsd/sys/contrib/dev/rtw89/wow.c (revision 848fdcae0326db5b7c3edd2e8c264d25254abe1d)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2019-2022  Realtek Corporation
3  */
4 #include "cam.h"
5 #include "core.h"
6 #include "debug.h"
7 #include "fw.h"
8 #include "mac.h"
9 #include "phy.h"
10 #include "ps.h"
11 #include "reg.h"
12 #include "util.h"
13 #include "wow.h"
14 
rtw89_wow_parse_akm(struct rtw89_dev * rtwdev,struct sk_buff * skb)15 void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb)
16 {
17 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
18 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
19 	const u8 *rsn, *ies = mgmt->u.assoc_req.variable;
20 #if defined(__linux__)
21 	struct rtw89_rsn_ie *rsn_ie;
22 #elif defined(__FreeBSD__)
23 	const struct rtw89_rsn_ie *rsn_ie;
24 #endif
25 
26 	rsn = cfg80211_find_ie(WLAN_EID_RSN, ies, skb->len);
27 	if (!rsn)
28 		return;
29 
30 #if defined(__linux__)
31 	rsn_ie = (struct rtw89_rsn_ie *)rsn;
32 #elif defined(__FreeBSD__)
33 	rsn_ie = (const struct rtw89_rsn_ie *)rsn;
34 #endif
35 	rtw_wow->akm = rsn_ie->akm_cipher_suite.type;
36 }
37 
38 #define RTW89_CIPHER_INFO_DEF(cipher) \
39 	{WLAN_CIPHER_SUITE_ ## cipher, .fw_alg = RTW89_WOW_FW_ALG_ ## cipher, \
40 	 .len = WLAN_KEY_LEN_ ## cipher}
41 
42 static const struct rtw89_cipher_info rtw89_cipher_info_defs[] = {
43 	RTW89_CIPHER_INFO_DEF(WEP40),
44 	RTW89_CIPHER_INFO_DEF(WEP104),
45 	RTW89_CIPHER_INFO_DEF(TKIP),
46 	RTW89_CIPHER_INFO_DEF(CCMP),
47 	RTW89_CIPHER_INFO_DEF(GCMP),
48 	RTW89_CIPHER_INFO_DEF(CCMP_256),
49 	RTW89_CIPHER_INFO_DEF(GCMP_256),
50 	RTW89_CIPHER_INFO_DEF(AES_CMAC),
51 };
52 
53 #undef RTW89_CIPHER_INFO_DEF
54 
55 static const
rtw89_cipher_alg_recognize(u32 cipher)56 struct rtw89_cipher_info *rtw89_cipher_alg_recognize(u32 cipher)
57 {
58 	const struct rtw89_cipher_info *cipher_info_defs;
59 	int i;
60 
61 	for (i = 0; i < ARRAY_SIZE(rtw89_cipher_info_defs); i++) {
62 		cipher_info_defs = &rtw89_cipher_info_defs[i];
63 		if (cipher_info_defs->cipher == cipher)
64 			return cipher_info_defs;
65 	}
66 
67 	return NULL;
68 }
69 
_pn_to_iv(struct rtw89_dev * rtwdev,struct ieee80211_key_conf * key,u8 * iv,u64 pn,u8 key_idx)70 static int _pn_to_iv(struct rtw89_dev *rtwdev, struct ieee80211_key_conf *key,
71 		     u8 *iv, u64 pn, u8 key_idx)
72 {
73 	switch (key->cipher) {
74 	case WLAN_CIPHER_SUITE_TKIP:
75 		iv[0] = u64_get_bits(pn, RTW89_KEY_PN_1);
76 		iv[1] = (u64_get_bits(pn, RTW89_KEY_PN_1) | 0x20) & 0x7f;
77 		iv[2] = u64_get_bits(pn, RTW89_KEY_PN_0);
78 		break;
79 	case WLAN_CIPHER_SUITE_CCMP:
80 	case WLAN_CIPHER_SUITE_GCMP:
81 	case WLAN_CIPHER_SUITE_CCMP_256:
82 	case WLAN_CIPHER_SUITE_GCMP_256:
83 		iv[0] = u64_get_bits(pn, RTW89_KEY_PN_0);
84 		iv[1] = u64_get_bits(pn, RTW89_KEY_PN_1);
85 		iv[2] = 0;
86 		break;
87 	default:
88 		return -EINVAL;
89 	}
90 
91 	iv[3] = BIT(5) | ((key_idx & 0x3) << 6);
92 	iv[4] = u64_get_bits(pn, RTW89_KEY_PN_2);
93 	iv[5] = u64_get_bits(pn, RTW89_KEY_PN_3);
94 	iv[6] = u64_get_bits(pn, RTW89_KEY_PN_4);
95 	iv[7] = u64_get_bits(pn, RTW89_KEY_PN_5);
96 
97 	return 0;
98 }
99 
rtw89_rx_pn_to_iv(struct rtw89_dev * rtwdev,struct ieee80211_key_conf * key,u8 * iv)100 static int rtw89_rx_pn_to_iv(struct rtw89_dev *rtwdev,
101 			     struct ieee80211_key_conf *key,
102 			     u8 *iv)
103 {
104 	struct ieee80211_key_seq seq;
105 	int err;
106 	u64 pn;
107 
108 	ieee80211_get_key_rx_seq(key, 0, &seq);
109 
110 	/* seq.ccmp.pn[] is BE order array */
111 	pn = u64_encode_bits(seq.ccmp.pn[0], RTW89_KEY_PN_5) |
112 	     u64_encode_bits(seq.ccmp.pn[1], RTW89_KEY_PN_4) |
113 	     u64_encode_bits(seq.ccmp.pn[2], RTW89_KEY_PN_3) |
114 	     u64_encode_bits(seq.ccmp.pn[3], RTW89_KEY_PN_2) |
115 	     u64_encode_bits(seq.ccmp.pn[4], RTW89_KEY_PN_1) |
116 	     u64_encode_bits(seq.ccmp.pn[5], RTW89_KEY_PN_0);
117 
118 	err = _pn_to_iv(rtwdev, key, iv, pn, key->keyidx);
119 	if (err)
120 		return err;
121 
122 #if defined(__linux__)
123 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%llx to iv-%*ph\n",
124 		    __func__, key->keyidx, pn, 8, iv);
125 #elif defined(__FreeBSD__)
126 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%jx to iv-%*ph\n",
127 		    __func__, key->keyidx, (uintmax_t)pn, 8, iv);
128 #endif
129 
130 	return 0;
131 }
132 
rtw89_tx_pn_to_iv(struct rtw89_dev * rtwdev,struct ieee80211_key_conf * key,u8 * iv)133 static int rtw89_tx_pn_to_iv(struct rtw89_dev *rtwdev,
134 			     struct ieee80211_key_conf *key,
135 			     u8 *iv)
136 {
137 	int err;
138 	u64 pn;
139 
140 	pn = atomic64_inc_return(&key->tx_pn);
141 	err = _pn_to_iv(rtwdev, key, iv, pn, key->keyidx);
142 	if (err)
143 		return err;
144 
145 #if defined(__linux__)
146 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%llx to iv-%*ph\n",
147 		    __func__, key->keyidx, pn, 8, iv);
148 #elif defined(__FreeBSD__)
149 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%jx to iv-%*ph\n",
150 		    __func__, key->keyidx, (uintmax_t)pn, 8, iv);
151 #endif
152 
153 	return 0;
154 }
155 
_iv_to_pn(struct rtw89_dev * rtwdev,u8 * iv,u64 * pn,u8 * key_id,struct ieee80211_key_conf * key)156 static int _iv_to_pn(struct rtw89_dev *rtwdev, u8 *iv, u64 *pn, u8 *key_id,
157 		     struct ieee80211_key_conf *key)
158 {
159 	switch (key->cipher) {
160 	case WLAN_CIPHER_SUITE_TKIP:
161 		*pn = u64_encode_bits(iv[2], RTW89_KEY_PN_0) |
162 		      u64_encode_bits(iv[0], RTW89_KEY_PN_1);
163 		break;
164 	case WLAN_CIPHER_SUITE_CCMP:
165 	case WLAN_CIPHER_SUITE_GCMP:
166 	case WLAN_CIPHER_SUITE_CCMP_256:
167 	case WLAN_CIPHER_SUITE_GCMP_256:
168 		*pn = u64_encode_bits(iv[0], RTW89_KEY_PN_0) |
169 		      u64_encode_bits(iv[1], RTW89_KEY_PN_1);
170 		break;
171 	default:
172 		return -EINVAL;
173 	}
174 
175 	*pn |= u64_encode_bits(iv[4], RTW89_KEY_PN_2) |
176 	       u64_encode_bits(iv[5], RTW89_KEY_PN_3) |
177 	       u64_encode_bits(iv[6], RTW89_KEY_PN_4) |
178 	       u64_encode_bits(iv[7], RTW89_KEY_PN_5);
179 
180 	if (key_id)
181 		*key_id = *(iv + 3) >> 6;
182 
183 	return 0;
184 }
185 
rtw89_rx_iv_to_pn(struct rtw89_dev * rtwdev,struct ieee80211_key_conf * key,u8 * iv)186 static int rtw89_rx_iv_to_pn(struct rtw89_dev *rtwdev,
187 			     struct ieee80211_key_conf *key,
188 			     u8 *iv)
189 {
190 	struct ieee80211_key_seq seq;
191 	int err;
192 	u64 pn;
193 
194 	err = _iv_to_pn(rtwdev, iv, &pn, NULL, key);
195 	if (err)
196 		return err;
197 
198 	/* seq.ccmp.pn[] is BE order array */
199 	seq.ccmp.pn[0] = u64_get_bits(pn, RTW89_KEY_PN_5);
200 	seq.ccmp.pn[1] = u64_get_bits(pn, RTW89_KEY_PN_4);
201 	seq.ccmp.pn[2] = u64_get_bits(pn, RTW89_KEY_PN_3);
202 	seq.ccmp.pn[3] = u64_get_bits(pn, RTW89_KEY_PN_2);
203 	seq.ccmp.pn[4] = u64_get_bits(pn, RTW89_KEY_PN_1);
204 	seq.ccmp.pn[5] = u64_get_bits(pn, RTW89_KEY_PN_0);
205 
206 	ieee80211_set_key_rx_seq(key, 0, &seq);
207 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d iv-%*ph to pn-%*ph\n",
208 		    __func__, key->keyidx, 8, iv, 6, seq.ccmp.pn);
209 
210 	return 0;
211 }
212 
rtw89_tx_iv_to_pn(struct rtw89_dev * rtwdev,struct ieee80211_key_conf * key,u8 * iv)213 static int rtw89_tx_iv_to_pn(struct rtw89_dev *rtwdev,
214 			     struct ieee80211_key_conf *key,
215 			     u8 *iv)
216 {
217 	int err;
218 	u64 pn;
219 
220 	err = _iv_to_pn(rtwdev, iv, &pn, NULL, key);
221 	if (err)
222 		return err;
223 
224 	atomic64_set(&key->tx_pn, pn);
225 #if defined(__linux__)
226 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d iv-%*ph to pn-%llx\n",
227 		    __func__, key->keyidx, 8, iv, pn);
228 #elif defined(__FreeBSD__)
229 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d iv-%*ph to pn-%jx\n",
230 		    __func__, key->keyidx, 8, iv, (uintmax_t)pn);
231 #endif
232 
233 	return 0;
234 }
235 
rtw89_rx_pn_get_pmf(struct rtw89_dev * rtwdev,struct ieee80211_key_conf * key,struct rtw89_wow_gtk_info * gtk_info)236 static int rtw89_rx_pn_get_pmf(struct rtw89_dev *rtwdev,
237 			       struct ieee80211_key_conf *key,
238 			       struct rtw89_wow_gtk_info *gtk_info)
239 {
240 	struct ieee80211_key_seq seq;
241 	u64 pn;
242 
243 	if (key->keyidx == 4)
244 		memcpy(gtk_info->igtk[0], key->key, key->keylen);
245 	else if (key->keyidx == 5)
246 		memcpy(gtk_info->igtk[1], key->key, key->keylen);
247 	else
248 		return -EINVAL;
249 
250 	ieee80211_get_key_rx_seq(key, 0, &seq);
251 
252 	/* seq.ccmp.pn[] is BE order array */
253 	pn = u64_encode_bits(seq.ccmp.pn[0], RTW89_KEY_PN_5) |
254 	     u64_encode_bits(seq.ccmp.pn[1], RTW89_KEY_PN_4) |
255 	     u64_encode_bits(seq.ccmp.pn[2], RTW89_KEY_PN_3) |
256 	     u64_encode_bits(seq.ccmp.pn[3], RTW89_KEY_PN_2) |
257 	     u64_encode_bits(seq.ccmp.pn[4], RTW89_KEY_PN_1) |
258 	     u64_encode_bits(seq.ccmp.pn[5], RTW89_KEY_PN_0);
259 	gtk_info->ipn = cpu_to_le64(pn);
260 	gtk_info->igtk_keyid = cpu_to_le32(key->keyidx);
261 #if defined(__linux__)
262 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%llx\n",
263 		    __func__, key->keyidx, pn);
264 #elif defined(__FreeBSD__)
265 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%jx\n",
266 		    __func__, key->keyidx, (uintmax_t)pn);
267 #endif
268 
269 	return 0;
270 }
271 
rtw89_rx_pn_set_pmf(struct rtw89_dev * rtwdev,struct ieee80211_key_conf * key,u64 pn)272 static int rtw89_rx_pn_set_pmf(struct rtw89_dev *rtwdev,
273 			       struct ieee80211_key_conf *key,
274 			       u64 pn)
275 {
276 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
277 	struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
278 	struct ieee80211_key_seq seq;
279 
280 	if (key->keyidx != aoac_rpt->igtk_key_id)
281 		return 0;
282 
283 	/* seq.ccmp.pn[] is BE order array */
284 	seq.ccmp.pn[0] = u64_get_bits(pn, RTW89_KEY_PN_5);
285 	seq.ccmp.pn[1] = u64_get_bits(pn, RTW89_KEY_PN_4);
286 	seq.ccmp.pn[2] = u64_get_bits(pn, RTW89_KEY_PN_3);
287 	seq.ccmp.pn[3] = u64_get_bits(pn, RTW89_KEY_PN_2);
288 	seq.ccmp.pn[4] = u64_get_bits(pn, RTW89_KEY_PN_1);
289 	seq.ccmp.pn[5] = u64_get_bits(pn, RTW89_KEY_PN_0);
290 
291 	ieee80211_set_key_rx_seq(key, 0, &seq);
292 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d pn-%*ph\n",
293 		    __func__, key->keyidx, 6, seq.ccmp.pn);
294 
295 	return 0;
296 }
297 
rtw89_wow_get_key_info_iter(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ieee80211_key_conf * key,void * data)298 static void rtw89_wow_get_key_info_iter(struct ieee80211_hw *hw,
299 					struct ieee80211_vif *vif,
300 					struct ieee80211_sta *sta,
301 					struct ieee80211_key_conf *key,
302 					void *data)
303 {
304 	struct rtw89_dev *rtwdev = hw->priv;
305 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
306 	struct rtw89_wow_key_info *key_info = &rtw_wow->key_info;
307 	struct rtw89_wow_gtk_info *gtk_info = &rtw_wow->gtk_info;
308 	const struct rtw89_cipher_info *cipher_info;
309 	bool *err = data;
310 	int ret;
311 
312 	cipher_info = rtw89_cipher_alg_recognize(key->cipher);
313 
314 	switch (key->cipher) {
315 	case WLAN_CIPHER_SUITE_TKIP:
316 	case WLAN_CIPHER_SUITE_CCMP:
317 	case WLAN_CIPHER_SUITE_GCMP:
318 	case WLAN_CIPHER_SUITE_CCMP_256:
319 	case WLAN_CIPHER_SUITE_GCMP_256:
320 		if (sta) {
321 			ret = rtw89_tx_pn_to_iv(rtwdev, key,
322 						key_info->ptk_tx_iv);
323 			if (ret)
324 				goto err;
325 			ret = rtw89_rx_pn_to_iv(rtwdev, key,
326 						key_info->ptk_rx_iv);
327 			if (ret)
328 				goto err;
329 
330 			rtw_wow->ptk_alg = cipher_info->fw_alg;
331 			rtw_wow->ptk_keyidx = key->keyidx;
332 		} else {
333 			ret = rtw89_rx_pn_to_iv(rtwdev, key,
334 						key_info->gtk_rx_iv[key->keyidx]);
335 			if (ret)
336 				goto err;
337 
338 			rtw_wow->gtk_alg = cipher_info->fw_alg;
339 			key_info->gtk_keyidx = key->keyidx;
340 		}
341 		break;
342 	case WLAN_CIPHER_SUITE_AES_CMAC:
343 		ret = rtw89_rx_pn_get_pmf(rtwdev, key, gtk_info);
344 		if (ret)
345 			goto err;
346 		break;
347 	case WLAN_CIPHER_SUITE_WEP40:
348 	case WLAN_CIPHER_SUITE_WEP104:
349 		/* WEP only set group key in mac80211, but fw need to set
350 		 * both of pairwise key and group key.
351 		 */
352 		rtw_wow->ptk_alg = cipher_info->fw_alg;
353 		rtw_wow->ptk_keyidx = key->keyidx;
354 		rtw_wow->gtk_alg = cipher_info->fw_alg;
355 		key_info->gtk_keyidx = key->keyidx;
356 		break;
357 	default:
358 		rtw89_debug(rtwdev, RTW89_DBG_WOW, "unsupport cipher %x\n",
359 			    key->cipher);
360 		goto err;
361 	}
362 
363 	return;
364 err:
365 	*err = true;
366 }
367 
rtw89_wow_set_key_info_iter(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ieee80211_key_conf * key,void * data)368 static void rtw89_wow_set_key_info_iter(struct ieee80211_hw *hw,
369 					struct ieee80211_vif *vif,
370 					struct ieee80211_sta *sta,
371 					struct ieee80211_key_conf *key,
372 					void *data)
373 {
374 	struct rtw89_dev *rtwdev = hw->priv;
375 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
376 	struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
377 	struct rtw89_set_key_info_iter_data *iter_data = data;
378 	bool update_tx_key_info = iter_data->rx_ready;
379 	int ret;
380 
381 	switch (key->cipher) {
382 	case WLAN_CIPHER_SUITE_TKIP:
383 	case WLAN_CIPHER_SUITE_CCMP:
384 	case WLAN_CIPHER_SUITE_GCMP:
385 	case WLAN_CIPHER_SUITE_CCMP_256:
386 	case WLAN_CIPHER_SUITE_GCMP_256:
387 		if (sta && !update_tx_key_info) {
388 			ret = rtw89_rx_iv_to_pn(rtwdev, key,
389 						aoac_rpt->ptk_rx_iv);
390 			if (ret)
391 				goto err;
392 		}
393 
394 		if (sta && update_tx_key_info) {
395 			ret = rtw89_tx_iv_to_pn(rtwdev, key,
396 						aoac_rpt->ptk_tx_iv);
397 			if (ret)
398 				goto err;
399 		}
400 
401 		if (!sta && !update_tx_key_info) {
402 			ret = rtw89_rx_iv_to_pn(rtwdev, key,
403 						aoac_rpt->gtk_rx_iv[key->keyidx]);
404 			if (ret)
405 				goto err;
406 		}
407 
408 		if (!sta && update_tx_key_info && aoac_rpt->rekey_ok)
409 			iter_data->gtk_cipher = key->cipher;
410 		break;
411 	case WLAN_CIPHER_SUITE_AES_CMAC:
412 		if (update_tx_key_info) {
413 			if (aoac_rpt->rekey_ok)
414 				iter_data->igtk_cipher = key->cipher;
415 		} else {
416 			ret = rtw89_rx_pn_set_pmf(rtwdev, key,
417 						  aoac_rpt->igtk_ipn);
418 			if (ret)
419 				goto err;
420 		}
421 		break;
422 	case WLAN_CIPHER_SUITE_WEP40:
423 	case WLAN_CIPHER_SUITE_WEP104:
424 		break;
425 	default:
426 		rtw89_debug(rtwdev, RTW89_DBG_WOW, "unsupport cipher %x\n",
427 			    key->cipher);
428 		goto err;
429 	}
430 
431 	return;
432 
433 err:
434 	iter_data->error = true;
435 }
436 
rtw89_wow_key_clear(struct rtw89_dev * rtwdev)437 static void rtw89_wow_key_clear(struct rtw89_dev *rtwdev)
438 {
439 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
440 
441 	memset(&rtw_wow->aoac_rpt, 0, sizeof(rtw_wow->aoac_rpt));
442 	memset(&rtw_wow->gtk_info, 0, sizeof(rtw_wow->gtk_info));
443 	memset(&rtw_wow->key_info, 0, sizeof(rtw_wow->key_info));
444 	rtw_wow->ptk_alg = 0;
445 	rtw_wow->gtk_alg = 0;
446 }
447 
rtw89_wow_construct_key_info(struct rtw89_dev * rtwdev)448 static void rtw89_wow_construct_key_info(struct rtw89_dev *rtwdev)
449 {
450 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
451 	struct rtw89_wow_key_info *key_info = &rtw_wow->key_info;
452 	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
453 	bool err = false;
454 
455 	rcu_read_lock();
456 	ieee80211_iter_keys_rcu(rtwdev->hw, wow_vif,
457 				rtw89_wow_get_key_info_iter, &err);
458 	rcu_read_unlock();
459 
460 	if (err) {
461 		rtw89_wow_key_clear(rtwdev);
462 		return;
463 	}
464 
465 	key_info->valid_check = RTW89_WOW_VALID_CHECK;
466 	key_info->symbol_check_en = RTW89_WOW_SYMBOL_CHK_PTK |
467 				    RTW89_WOW_SYMBOL_CHK_GTK;
468 }
469 
rtw89_wow_debug_aoac_rpt(struct rtw89_dev * rtwdev)470 static void rtw89_wow_debug_aoac_rpt(struct rtw89_dev *rtwdev)
471 {
472 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
473 	struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
474 
475 	if (!rtw89_debug_is_enabled(rtwdev, RTW89_DBG_WOW))
476 		return;
477 
478 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] rpt_ver = %d\n",
479 		    aoac_rpt->rpt_ver);
480 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] sec_type = %d\n",
481 		    aoac_rpt->sec_type);
482 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] key_idx = %d\n",
483 		    aoac_rpt->key_idx);
484 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] pattern_idx = %d\n",
485 		    aoac_rpt->pattern_idx);
486 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] rekey_ok = %d\n",
487 		    aoac_rpt->rekey_ok);
488 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] ptk_tx_iv = %*ph\n",
489 		    8, aoac_rpt->ptk_tx_iv);
490 	rtw89_debug(rtwdev, RTW89_DBG_WOW,
491 		    "[aoac_rpt] eapol_key_replay_count = %*ph\n",
492 		    8, aoac_rpt->eapol_key_replay_count);
493 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] ptk_rx_iv = %*ph\n",
494 		    8, aoac_rpt->ptk_rx_iv);
495 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] gtk_rx_iv[0] = %*ph\n",
496 		    8, aoac_rpt->gtk_rx_iv[0]);
497 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] gtk_rx_iv[1] = %*ph\n",
498 		    8, aoac_rpt->gtk_rx_iv[1]);
499 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] gtk_rx_iv[2] = %*ph\n",
500 		    8, aoac_rpt->gtk_rx_iv[2]);
501 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] gtk_rx_iv[3] = %*ph\n",
502 		    8, aoac_rpt->gtk_rx_iv[3]);
503 #if defined(__linux__)
504 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] igtk_key_id = %llu\n",
505 		    aoac_rpt->igtk_key_id);
506 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] igtk_ipn = %llu\n",
507 		    aoac_rpt->igtk_ipn);
508 #elif defined(__FreeBSD__)
509 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] igtk_key_id = %ju\n",
510 		    (uintmax_t)aoac_rpt->igtk_key_id);
511 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] igtk_ipn = %ju\n",
512 		    (uintmax_t)aoac_rpt->igtk_ipn);
513 #endif
514 	rtw89_debug(rtwdev, RTW89_DBG_WOW, "[aoac_rpt] igtk = %*ph\n",
515 		    32, aoac_rpt->igtk);
516 }
517 
rtw89_wow_get_aoac_rpt_reg(struct rtw89_dev * rtwdev)518 static int rtw89_wow_get_aoac_rpt_reg(struct rtw89_dev *rtwdev)
519 {
520 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
521 	struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
522 	struct rtw89_mac_c2h_info c2h_info = {};
523 	struct rtw89_mac_h2c_info h2c_info = {};
524 	u8 igtk_ipn[8];
525 	u8 key_idx;
526 	int ret;
527 
528 	h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_AOAC_RPT_1;
529 	h2c_info.content_len = 2;
530 	ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info);
531 	if (ret)
532 		return ret;
533 
534 	aoac_rpt->key_idx =
535 		u32_get_bits(c2h_info.u.c2hreg[0], RTW89_C2HREG_AOAC_RPT_1_W0_KEY_IDX);
536 	key_idx = aoac_rpt->key_idx;
537 	aoac_rpt->gtk_rx_iv[key_idx][0] =
538 		u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_1_W1_IV_0);
539 	aoac_rpt->gtk_rx_iv[key_idx][1] =
540 		u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_1_W1_IV_1);
541 	aoac_rpt->gtk_rx_iv[key_idx][2] =
542 		u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_1_W1_IV_2);
543 	aoac_rpt->gtk_rx_iv[key_idx][3] =
544 		u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_1_W1_IV_3);
545 	aoac_rpt->gtk_rx_iv[key_idx][4] =
546 		u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_1_W2_IV_4);
547 	aoac_rpt->gtk_rx_iv[key_idx][5] =
548 		u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_1_W2_IV_5);
549 	aoac_rpt->gtk_rx_iv[key_idx][6] =
550 		u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_1_W2_IV_6);
551 	aoac_rpt->gtk_rx_iv[key_idx][7] =
552 		u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_1_W2_IV_7);
553 	aoac_rpt->ptk_rx_iv[0] =
554 		u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_0);
555 	aoac_rpt->ptk_rx_iv[1] =
556 		u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_1);
557 	aoac_rpt->ptk_rx_iv[2] =
558 		u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_2);
559 	aoac_rpt->ptk_rx_iv[3] =
560 		u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_1_W3_PTK_IV_3);
561 
562 	h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_AOAC_RPT_2;
563 	h2c_info.content_len = 2;
564 	ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info);
565 	if (ret)
566 		return ret;
567 
568 	aoac_rpt->ptk_rx_iv[4] =
569 		u32_get_bits(c2h_info.u.c2hreg[0], RTW89_C2HREG_AOAC_RPT_2_W0_PTK_IV_4);
570 	aoac_rpt->ptk_rx_iv[5] =
571 		u32_get_bits(c2h_info.u.c2hreg[0], RTW89_C2HREG_AOAC_RPT_2_W0_PTK_IV_5);
572 	aoac_rpt->ptk_rx_iv[6] =
573 		u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_2_W1_PTK_IV_6);
574 	aoac_rpt->ptk_rx_iv[7] =
575 		u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_2_W1_PTK_IV_7);
576 	igtk_ipn[0] =
577 		u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_2_W1_IGTK_IPN_IV_0);
578 	igtk_ipn[1] =
579 		u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_AOAC_RPT_2_W1_IGTK_IPN_IV_1);
580 	igtk_ipn[2] =
581 		u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_2);
582 	igtk_ipn[3] =
583 		u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_3);
584 	igtk_ipn[4] =
585 		u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_4);
586 	igtk_ipn[5] =
587 		u32_get_bits(c2h_info.u.c2hreg[2], RTW89_C2HREG_AOAC_RPT_2_W2_IGTK_IPN_IV_5);
588 	igtk_ipn[6] =
589 		u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_6);
590 	igtk_ipn[7] =
591 		u32_get_bits(c2h_info.u.c2hreg[3], RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_7);
592 	aoac_rpt->igtk_ipn = u64_encode_bits(igtk_ipn[0], RTW89_IGTK_IPN_0) |
593 			     u64_encode_bits(igtk_ipn[1], RTW89_IGTK_IPN_1) |
594 			     u64_encode_bits(igtk_ipn[2], RTW89_IGTK_IPN_2) |
595 			     u64_encode_bits(igtk_ipn[3], RTW89_IGTK_IPN_3) |
596 			     u64_encode_bits(igtk_ipn[4], RTW89_IGTK_IPN_4) |
597 			     u64_encode_bits(igtk_ipn[5], RTW89_IGTK_IPN_5) |
598 			     u64_encode_bits(igtk_ipn[6], RTW89_IGTK_IPN_6) |
599 			     u64_encode_bits(igtk_ipn[7], RTW89_IGTK_IPN_7);
600 
601 	return 0;
602 }
603 
rtw89_wow_get_aoac_rpt(struct rtw89_dev * rtwdev,bool rx_ready)604 static int rtw89_wow_get_aoac_rpt(struct rtw89_dev *rtwdev, bool rx_ready)
605 {
606 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
607 	int ret;
608 
609 	if (!rtw_wow->ptk_alg)
610 		return -EPERM;
611 
612 	if (!rx_ready) {
613 		ret = rtw89_wow_get_aoac_rpt_reg(rtwdev);
614 		if (ret) {
615 			rtw89_err(rtwdev, "wow: failed to get aoac rpt by reg\n");
616 			return ret;
617 		}
618 	} else {
619 		ret = rtw89_fw_h2c_wow_request_aoac(rtwdev);
620 		if (ret) {
621 			rtw89_err(rtwdev, "wow: failed to get aoac rpt by pkt\n");
622 			return ret;
623 		}
624 	}
625 
626 	rtw89_wow_debug_aoac_rpt(rtwdev);
627 
628 	return 0;
629 }
630 
rtw89_wow_gtk_rekey(struct rtw89_dev * rtwdev,u32 cipher,u8 keyidx,u8 * gtk)631 static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev,
632 						      u32 cipher, u8 keyidx, u8 *gtk)
633 {
634 	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
635 	const struct rtw89_cipher_info *cipher_info;
636 	struct ieee80211_key_conf *rekey_conf;
637 	struct ieee80211_key_conf *key;
638 	u8 sz;
639 
640 	cipher_info = rtw89_cipher_alg_recognize(cipher);
641 	sz = struct_size(rekey_conf, key, cipher_info->len);
642 	rekey_conf = kmalloc(sz, GFP_KERNEL);
643 	if (!rekey_conf)
644 		return NULL;
645 
646 	rekey_conf->cipher = cipher;
647 	rekey_conf->keyidx = keyidx;
648 	rekey_conf->keylen = cipher_info->len;
649 	memcpy(rekey_conf->key, gtk,
650 	       flex_array_size(rekey_conf, key, cipher_info->len));
651 
652 	/* ieee80211_gtk_rekey_add() will call set_key(), therefore we
653 	 * need to unlock mutex
654 	 */
655 	mutex_unlock(&rtwdev->mutex);
656 	key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, -1);
657 	mutex_lock(&rtwdev->mutex);
658 
659 	kfree(rekey_conf);
660 	if (IS_ERR(key)) {
661 		rtw89_err(rtwdev, "ieee80211_gtk_rekey_add failed\n");
662 		return NULL;
663 	}
664 
665 	return key;
666 }
667 
rtw89_wow_update_key_info(struct rtw89_dev * rtwdev,bool rx_ready)668 static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready)
669 {
670 	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
671 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
672 	struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
673 	struct rtw89_set_key_info_iter_data data = {.error = false,
674 						    .rx_ready = rx_ready};
675 	struct ieee80211_key_conf *key;
676 
677 	rcu_read_lock();
678 	ieee80211_iter_keys_rcu(rtwdev->hw, wow_vif,
679 				rtw89_wow_set_key_info_iter, &data);
680 	rcu_read_unlock();
681 
682 	if (data.error) {
683 		rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s error\n", __func__);
684 		return;
685 	}
686 
687 	if (!data.gtk_cipher)
688 		return;
689 
690 	key = rtw89_wow_gtk_rekey(rtwdev, data.gtk_cipher, aoac_rpt->key_idx,
691 				  aoac_rpt->gtk);
692 	if (!key)
693 		return;
694 
695 	rtw89_rx_iv_to_pn(rtwdev, key,
696 			  aoac_rpt->gtk_rx_iv[key->keyidx]);
697 
698 	if (!data.igtk_cipher)
699 		return;
700 
701 	key = rtw89_wow_gtk_rekey(rtwdev, data.igtk_cipher, aoac_rpt->igtk_key_id,
702 				  aoac_rpt->igtk);
703 	if (!key)
704 		return;
705 
706 	rtw89_rx_pn_set_pmf(rtwdev, key, aoac_rpt->igtk_ipn);
707 	ieee80211_gtk_rekey_notify(wow_vif, wow_vif->bss_conf.bssid,
708 				   aoac_rpt->eapol_key_replay_count,
709 				   GFP_KERNEL);
710 }
711 
rtw89_wow_leave_deep_ps(struct rtw89_dev * rtwdev)712 static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev)
713 {
714 	__rtw89_leave_ps_mode(rtwdev);
715 }
716 
rtw89_wow_enter_deep_ps(struct rtw89_dev * rtwdev)717 static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev)
718 {
719 	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
720 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
721 
722 	__rtw89_enter_ps_mode(rtwdev, rtwvif);
723 }
724 
rtw89_wow_enter_lps(struct rtw89_dev * rtwdev)725 static void rtw89_wow_enter_lps(struct rtw89_dev *rtwdev)
726 {
727 	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
728 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
729 
730 	rtw89_enter_lps(rtwdev, rtwvif, false);
731 }
732 
rtw89_wow_leave_lps(struct rtw89_dev * rtwdev)733 static void rtw89_wow_leave_lps(struct rtw89_dev *rtwdev)
734 {
735 	rtw89_leave_lps(rtwdev);
736 }
737 
rtw89_wow_config_mac(struct rtw89_dev * rtwdev,bool enable_wow)738 static int rtw89_wow_config_mac(struct rtw89_dev *rtwdev, bool enable_wow)
739 {
740 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
741 
742 	return mac->wow_config_mac(rtwdev, enable_wow);
743 }
744 
rtw89_wow_set_rx_filter(struct rtw89_dev * rtwdev,bool enable)745 static void rtw89_wow_set_rx_filter(struct rtw89_dev *rtwdev, bool enable)
746 {
747 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
748 	enum rtw89_mac_fwd_target fwd_target = enable ?
749 					       RTW89_FWD_DONT_CARE :
750 					       RTW89_FWD_TO_HOST;
751 
752 	mac->typ_fltr_opt(rtwdev, RTW89_MGNT, fwd_target, RTW89_MAC_0);
753 	mac->typ_fltr_opt(rtwdev, RTW89_CTRL, fwd_target, RTW89_MAC_0);
754 	mac->typ_fltr_opt(rtwdev, RTW89_DATA, fwd_target, RTW89_MAC_0);
755 }
756 
rtw89_wow_show_wakeup_reason(struct rtw89_dev * rtwdev)757 static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
758 {
759 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
760 	struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
761 	struct cfg80211_wowlan_nd_info nd_info;
762 	struct cfg80211_wowlan_wakeup wakeup = {
763 		.pattern_idx = -1,
764 	};
765 	u32 wow_reason_reg;
766 	u8 reason;
767 
768 	if (RTW89_CHK_FW_FEATURE(WOW_REASON_V1, &rtwdev->fw))
769 		wow_reason_reg = rtwdev->chip->wow_reason_reg[RTW89_WOW_REASON_V1];
770 	else
771 		wow_reason_reg = rtwdev->chip->wow_reason_reg[RTW89_WOW_REASON_V0];
772 
773 	reason = rtw89_read8(rtwdev, wow_reason_reg);
774 	switch (reason) {
775 	case RTW89_WOW_RSN_RX_DEAUTH:
776 		wakeup.disconnect = true;
777 		rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx deauth\n");
778 		break;
779 	case RTW89_WOW_RSN_DISCONNECT:
780 		wakeup.disconnect = true;
781 		rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: AP is off\n");
782 		break;
783 	case RTW89_WOW_RSN_RX_MAGIC_PKT:
784 		wakeup.magic_pkt = true;
785 		rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx magic packet\n");
786 		break;
787 	case RTW89_WOW_RSN_RX_GTK_REKEY:
788 		wakeup.gtk_rekey_failure = true;
789 		rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx gtk rekey\n");
790 		break;
791 	case RTW89_WOW_RSN_RX_PATTERN_MATCH:
792 		wakeup.pattern_idx = aoac_rpt->pattern_idx;
793 		rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx pattern match packet\n");
794 		break;
795 	case RTW89_WOW_RSN_RX_NLO:
796 		/* Current firmware and driver don't report ssid index.
797 		 * Use 0 for n_matches based on its comment.
798 		 */
799 		nd_info.n_matches = 0;
800 		wakeup.net_detect = &nd_info;
801 		rtw89_debug(rtwdev, RTW89_DBG_WOW, "Rx NLO\n");
802 		break;
803 	default:
804 		rtw89_warn(rtwdev, "Unknown wakeup reason %x\n", reason);
805 		ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL,
806 					       GFP_KERNEL);
807 		return;
808 	}
809 
810 	ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup,
811 				       GFP_KERNEL);
812 }
813 
rtw89_wow_vif_iter(struct rtw89_dev * rtwdev,struct rtw89_vif * rtwvif)814 static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
815 {
816 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
817 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
818 
819 	/* Current wowlan function support setting of only one STATION vif.
820 	 * So when one suitable vif is found, stop the iteration.
821 	 */
822 	if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION)
823 		return;
824 
825 	switch (rtwvif->net_type) {
826 	case RTW89_NET_TYPE_INFRA:
827 		rtw_wow->wow_vif = vif;
828 		break;
829 	case RTW89_NET_TYPE_NO_LINK:
830 	default:
831 		break;
832 	}
833 }
834 
__rtw89_cal_crc16(u8 data,u16 crc)835 static u16 __rtw89_cal_crc16(u8 data, u16 crc)
836 {
837 	u8 shift_in, data_bit;
838 	u8 crc_bit4, crc_bit11, crc_bit15;
839 	u16 crc_result;
840 	int index;
841 
842 	for (index = 0; index < 8; index++) {
843 		crc_bit15 = crc & BIT(15) ? 1 : 0;
844 		data_bit = data & BIT(index) ? 1 : 0;
845 		shift_in = crc_bit15 ^ data_bit;
846 
847 		crc_result = crc << 1;
848 
849 		if (shift_in == 0)
850 			crc_result &= ~BIT(0);
851 		else
852 			crc_result |= BIT(0);
853 
854 		crc_bit11 = (crc & BIT(11) ? 1 : 0) ^ shift_in;
855 
856 		if (crc_bit11 == 0)
857 			crc_result &= ~BIT(12);
858 		else
859 			crc_result |= BIT(12);
860 
861 		crc_bit4 = (crc & BIT(4) ? 1 : 0) ^ shift_in;
862 
863 		if (crc_bit4 == 0)
864 			crc_result &= ~BIT(5);
865 		else
866 			crc_result |= BIT(5);
867 
868 		crc = crc_result;
869 	}
870 	return crc;
871 }
872 
rtw89_calc_crc(u8 * pdata,int length)873 static u16 rtw89_calc_crc(u8 *pdata, int length)
874 {
875 	u16 crc = 0xffff;
876 	int i;
877 
878 	for (i = 0; i < length; i++)
879 		crc = __rtw89_cal_crc16(pdata[i], crc);
880 
881 	/* get 1' complement */
882 	return ~crc;
883 }
884 
rtw89_wow_pattern_get_type(struct rtw89_vif * rtwvif,struct rtw89_wow_cam_info * rtw_pattern,const u8 * pattern,u8 da_mask)885 static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif,
886 				      struct rtw89_wow_cam_info *rtw_pattern,
887 				      const u8 *pattern, u8 da_mask)
888 {
889 	u8 da[ETH_ALEN];
890 
891 	ether_addr_copy_mask(da, pattern, da_mask);
892 
893 	/* Each pattern is divided into different kinds by DA address
894 	 *  a. DA is broadcast address: set bc = 0;
895 	 *  b. DA is multicast address: set mc = 0
896 	 *  c. DA is unicast address same as dev's mac address: set uc = 0
897 	 *  d. DA is unmasked. Also called wildcard type: set uc = bc = mc = 0
898 	 *  e. Others is invalid type.
899 	 */
900 
901 	if (is_broadcast_ether_addr(da))
902 		rtw_pattern->bc = true;
903 	else if (is_multicast_ether_addr(da))
904 		rtw_pattern->mc = true;
905 	else if (ether_addr_equal(da, rtwvif->mac_addr) &&
906 		 da_mask == GENMASK(5, 0))
907 		rtw_pattern->uc = true;
908 	else if (!da_mask) /*da_mask == 0 mean wildcard*/
909 		return 0;
910 	else
911 		return -EPERM;
912 
913 	return 0;
914 }
915 
rtw89_wow_pattern_generate(struct rtw89_dev * rtwdev,struct rtw89_vif * rtwvif,const struct cfg80211_pkt_pattern * pkt_pattern,struct rtw89_wow_cam_info * rtw_pattern)916 static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev,
917 				      struct rtw89_vif *rtwvif,
918 				      const struct cfg80211_pkt_pattern *pkt_pattern,
919 				      struct rtw89_wow_cam_info *rtw_pattern)
920 {
921 	u8 mask_hw[RTW89_MAX_PATTERN_MASK_SIZE * 4] = {0};
922 	u8 content[RTW89_MAX_PATTERN_SIZE] = {0};
923 	const u8 *mask;
924 	const u8 *pattern;
925 	u8 mask_len;
926 	u16 count;
927 	u32 len;
928 	int i, ret;
929 
930 	pattern = pkt_pattern->pattern;
931 	len = pkt_pattern->pattern_len;
932 	mask = pkt_pattern->mask;
933 	mask_len = DIV_ROUND_UP(len, 8);
934 	memset(rtw_pattern, 0, sizeof(*rtw_pattern));
935 
936 	ret = rtw89_wow_pattern_get_type(rtwvif, rtw_pattern, pattern,
937 					 mask[0] & GENMASK(5, 0));
938 	if (ret)
939 		return ret;
940 
941 	/* translate mask from os to mask for hw
942 	 * pattern from OS uses 'ethenet frame', like this:
943 	 * |    6   |    6   |   2  |     20    |  Variable  |  4  |
944 	 * |--------+--------+------+-----------+------------+-----|
945 	 * |    802.3 Mac Header    | IP Header | TCP Packet | FCS |
946 	 * |   DA   |   SA   | Type |
947 	 *
948 	 * BUT, packet catched by our HW is in '802.11 frame', begin from LLC
949 	 * |     24 or 30      |    6   |   2  |     20    |  Variable  |  4  |
950 	 * |-------------------+--------+------+-----------+------------+-----|
951 	 * | 802.11 MAC Header |       LLC     | IP Header | TCP Packet | FCS |
952 	 *		       | Others | Tpye |
953 	 *
954 	 * Therefore, we need translate mask_from_OS to mask_to_hw.
955 	 * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0,
956 	 * because new mask[0~5] means 'SA', but our HW packet begins from LLC,
957 	 * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match.
958 	 */
959 
960 	/* Shift 6 bits */
961 	for (i = 0; i < mask_len - 1; i++) {
962 		mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6)) |
963 			     u8_get_bits(mask[i + 1], GENMASK(5, 0)) << 2;
964 	}
965 	mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6));
966 
967 	/* Set bit 0-5 to zero */
968 	mask_hw[0] &= ~GENMASK(5, 0);
969 
970 	memcpy(rtw_pattern->mask, mask_hw, sizeof(rtw_pattern->mask));
971 
972 	/* To get the wake up pattern from the mask.
973 	 * We do not count first 12 bits which means
974 	 * DA[6] and SA[6] in the pattern to match HW design.
975 	 */
976 	count = 0;
977 	for (i = 12; i < len; i++) {
978 		if ((mask[i / 8] >> (i % 8)) & 0x01) {
979 			content[count] = pattern[i];
980 			count++;
981 		}
982 	}
983 
984 	rtw_pattern->crc = rtw89_calc_crc(content, count);
985 
986 	return 0;
987 }
988 
rtw89_wow_parse_patterns(struct rtw89_dev * rtwdev,struct rtw89_vif * rtwvif,struct cfg80211_wowlan * wowlan)989 static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev,
990 				    struct rtw89_vif *rtwvif,
991 				    struct cfg80211_wowlan *wowlan)
992 {
993 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
994 	struct rtw89_wow_cam_info *rtw_pattern = rtw_wow->patterns;
995 	int i;
996 	int ret;
997 
998 	if (!wowlan->n_patterns || !wowlan->patterns)
999 		return 0;
1000 
1001 	for (i = 0; i < wowlan->n_patterns; i++) {
1002 		rtw_pattern = &rtw_wow->patterns[i];
1003 		ret = rtw89_wow_pattern_generate(rtwdev, rtwvif,
1004 						 &wowlan->patterns[i],
1005 						 rtw_pattern);
1006 		if (ret) {
1007 			rtw89_err(rtwdev, "failed to generate pattern(%d)\n", i);
1008 			rtw_wow->pattern_cnt = 0;
1009 			return ret;
1010 		}
1011 
1012 		rtw_pattern->r_w = true;
1013 		rtw_pattern->idx = i;
1014 		rtw_pattern->negative_pattern_match = false;
1015 		rtw_pattern->skip_mac_hdr = true;
1016 		rtw_pattern->valid = true;
1017 	}
1018 	rtw_wow->pattern_cnt = wowlan->n_patterns;
1019 
1020 	return 0;
1021 }
1022 
rtw89_wow_pattern_clear_cam(struct rtw89_dev * rtwdev)1023 static void rtw89_wow_pattern_clear_cam(struct rtw89_dev *rtwdev)
1024 {
1025 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1026 	struct rtw89_wow_cam_info *rtw_pattern = rtw_wow->patterns;
1027 	int i = 0;
1028 
1029 	for (i = 0; i < rtw_wow->pattern_cnt; i++) {
1030 		rtw_pattern = &rtw_wow->patterns[i];
1031 		rtw_pattern->valid = false;
1032 		rtw89_fw_wow_cam_update(rtwdev, rtw_pattern);
1033 	}
1034 }
1035 
rtw89_wow_pattern_write(struct rtw89_dev * rtwdev)1036 static void rtw89_wow_pattern_write(struct rtw89_dev *rtwdev)
1037 {
1038 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1039 	struct rtw89_wow_cam_info *rtw_pattern = rtw_wow->patterns;
1040 	int i;
1041 
1042 	for (i = 0; i < rtw_wow->pattern_cnt; i++)
1043 		rtw89_fw_wow_cam_update(rtwdev, rtw_pattern + i);
1044 }
1045 
rtw89_wow_pattern_clear(struct rtw89_dev * rtwdev)1046 static void rtw89_wow_pattern_clear(struct rtw89_dev *rtwdev)
1047 {
1048 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1049 
1050 	rtw89_wow_pattern_clear_cam(rtwdev);
1051 
1052 	rtw_wow->pattern_cnt = 0;
1053 	memset(rtw_wow->patterns, 0, sizeof(rtw_wow->patterns));
1054 }
1055 
rtw89_wow_clear_wakeups(struct rtw89_dev * rtwdev)1056 static void rtw89_wow_clear_wakeups(struct rtw89_dev *rtwdev)
1057 {
1058 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1059 
1060 	rtw_wow->wow_vif = NULL;
1061 	rtw89_core_release_all_bits_map(rtw_wow->flags, RTW89_WOW_FLAG_NUM);
1062 	rtw_wow->pattern_cnt = 0;
1063 }
1064 
rtw89_wow_set_wakeups(struct rtw89_dev * rtwdev,struct cfg80211_wowlan * wowlan)1065 static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev,
1066 				 struct cfg80211_wowlan *wowlan)
1067 {
1068 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1069 	struct rtw89_vif *rtwvif;
1070 
1071 	if (wowlan->disconnect)
1072 		set_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags);
1073 	if (wowlan->magic_pkt)
1074 		set_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags);
1075 
1076 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
1077 		rtw89_wow_vif_iter(rtwdev, rtwvif);
1078 
1079 	if (!rtw_wow->wow_vif)
1080 		return -EPERM;
1081 
1082 	rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv;
1083 	return rtw89_wow_parse_patterns(rtwdev, rtwvif, wowlan);
1084 }
1085 
rtw89_wow_cfg_wake(struct rtw89_dev * rtwdev,bool wow)1086 static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow)
1087 {
1088 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1089 	struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
1090 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
1091 	struct ieee80211_sta *wow_sta;
1092 	struct rtw89_sta *rtwsta = NULL;
1093 	int ret;
1094 
1095 	wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid);
1096 	if (wow_sta)
1097 		rtwsta = (struct rtw89_sta *)wow_sta->drv_priv;
1098 
1099 	if (wow) {
1100 		if (rtw_wow->pattern_cnt)
1101 			rtwvif->wowlan_pattern = true;
1102 		if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags))
1103 			rtwvif->wowlan_magic = true;
1104 	} else {
1105 		rtwvif->wowlan_pattern = false;
1106 		rtwvif->wowlan_magic = false;
1107 	}
1108 
1109 	ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow);
1110 	if (ret) {
1111 		rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n");
1112 		return ret;
1113 	}
1114 
1115 	if (wow) {
1116 		ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta);
1117 		if (ret) {
1118 			rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n",
1119 				  ret);
1120 			return ret;
1121 		}
1122 	}
1123 
1124 	ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
1125 	if (ret) {
1126 		rtw89_warn(rtwdev, "failed to send h2c cam\n");
1127 		return ret;
1128 	}
1129 
1130 	ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow);
1131 	if (ret) {
1132 		rtw89_err(rtwdev, "failed to fw wow global\n");
1133 		return ret;
1134 	}
1135 
1136 	return 0;
1137 }
1138 
rtw89_wow_check_fw_status(struct rtw89_dev * rtwdev,bool wow_enable)1139 static int rtw89_wow_check_fw_status(struct rtw89_dev *rtwdev, bool wow_enable)
1140 {
1141 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
1142 	u8 polling;
1143 	int ret;
1144 
1145 	ret = read_poll_timeout_atomic(rtw89_read8_mask, polling,
1146 				       wow_enable == !!polling,
1147 				       50, 50000, false, rtwdev,
1148 				       mac->wow_ctrl.addr, mac->wow_ctrl.mask);
1149 	if (ret)
1150 		rtw89_err(rtwdev, "failed to check wow status %s\n",
1151 			  wow_enable ? "enabled" : "disabled");
1152 	return ret;
1153 }
1154 
rtw89_wow_swap_fw(struct rtw89_dev * rtwdev,bool wow)1155 static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
1156 {
1157 	enum rtw89_fw_type fw_type = wow ? RTW89_FW_WOWLAN : RTW89_FW_NORMAL;
1158 	enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
1159 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1160 	struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
1161 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
1162 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
1163 	const struct rtw89_chip_info *chip = rtwdev->chip;
1164 	bool include_bb = !!chip->bbmcu_nr;
1165 	bool disable_intr_for_dlfw = false;
1166 	struct ieee80211_sta *wow_sta;
1167 	struct rtw89_sta *rtwsta = NULL;
1168 	bool is_conn = true;
1169 	int ret;
1170 
1171 	if (chip_id == RTL8852C || chip_id == RTL8922A)
1172 		disable_intr_for_dlfw = true;
1173 
1174 	wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid);
1175 	if (wow_sta)
1176 		rtwsta = (struct rtw89_sta *)wow_sta->drv_priv;
1177 	else
1178 		is_conn = false;
1179 
1180 	if (disable_intr_for_dlfw)
1181 		rtw89_hci_disable_intr(rtwdev);
1182 
1183 	ret = rtw89_fw_download(rtwdev, fw_type, include_bb);
1184 	if (ret) {
1185 		rtw89_warn(rtwdev, "download fw failed\n");
1186 		return ret;
1187 	}
1188 
1189 	if (disable_intr_for_dlfw)
1190 		rtw89_hci_enable_intr(rtwdev);
1191 
1192 	rtw89_phy_init_rf_reg(rtwdev, true);
1193 
1194 	ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta,
1195 					 RTW89_ROLE_FW_RESTORE);
1196 	if (ret) {
1197 		rtw89_warn(rtwdev, "failed to send h2c role maintain\n");
1198 		return ret;
1199 	}
1200 
1201 	ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, wow_vif, wow_sta);
1202 	if (ret) {
1203 		rtw89_warn(rtwdev, "failed to send h2c assoc cmac tbl\n");
1204 		return ret;
1205 	}
1206 
1207 	if (!is_conn)
1208 		rtw89_cam_reset_keys(rtwdev);
1209 
1210 	ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, !is_conn);
1211 	if (ret) {
1212 		rtw89_warn(rtwdev, "failed to send h2c join info\n");
1213 		return ret;
1214 	}
1215 
1216 	ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL);
1217 	if (ret) {
1218 		rtw89_warn(rtwdev, "failed to send h2c cam\n");
1219 		return ret;
1220 	}
1221 
1222 	if (is_conn) {
1223 		ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id);
1224 		if (ret) {
1225 			rtw89_warn(rtwdev, "failed to send h2c general packet\n");
1226 			return ret;
1227 		}
1228 		rtw89_phy_ra_assoc(rtwdev, wow_sta);
1229 		rtw89_phy_set_bss_color(rtwdev, wow_vif);
1230 		rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, wow_vif);
1231 	}
1232 
1233 	if (chip_gen == RTW89_CHIP_BE)
1234 		rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, RTW89_PHY_0, 5);
1235 
1236 	rtw89_mac_hw_mgnt_sec(rtwdev, wow);
1237 
1238 	return 0;
1239 }
1240 
rtw89_wow_enable_trx_pre(struct rtw89_dev * rtwdev)1241 static int rtw89_wow_enable_trx_pre(struct rtw89_dev *rtwdev)
1242 {
1243 	int ret;
1244 
1245 	rtw89_hci_ctrl_txdma_ch(rtwdev, false);
1246 	rtw89_hci_ctrl_txdma_fw_ch(rtwdev, true);
1247 
1248 	rtw89_mac_ptk_drop_by_band_and_wait(rtwdev, RTW89_MAC_0);
1249 
1250 	ret = rtw89_hci_poll_txdma_ch_idle(rtwdev);
1251 	if (ret) {
1252 		rtw89_err(rtwdev, "txdma ch busy\n");
1253 		return ret;
1254 	}
1255 	rtw89_wow_set_rx_filter(rtwdev, true);
1256 
1257 	ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false);
1258 	if (ret) {
1259 		rtw89_err(rtwdev, "cfg ppdu status\n");
1260 		return ret;
1261 	}
1262 
1263 	return 0;
1264 }
1265 
rtw89_wow_enable_trx_post(struct rtw89_dev * rtwdev)1266 static int rtw89_wow_enable_trx_post(struct rtw89_dev *rtwdev)
1267 {
1268 	int ret;
1269 
1270 	rtw89_hci_disable_intr(rtwdev);
1271 	rtw89_hci_ctrl_trxhci(rtwdev, false);
1272 
1273 	ret = rtw89_hci_poll_txdma_ch_idle(rtwdev);
1274 	if (ret) {
1275 		rtw89_err(rtwdev, "failed to poll txdma ch idle pcie\n");
1276 		return ret;
1277 	}
1278 
1279 	ret = rtw89_wow_config_mac(rtwdev, true);
1280 	if (ret) {
1281 		rtw89_err(rtwdev, "failed to config mac\n");
1282 		return ret;
1283 	}
1284 
1285 	rtw89_wow_set_rx_filter(rtwdev, false);
1286 	rtw89_hci_reset(rtwdev);
1287 
1288 	return 0;
1289 }
1290 
rtw89_wow_disable_trx_pre(struct rtw89_dev * rtwdev)1291 static int rtw89_wow_disable_trx_pre(struct rtw89_dev *rtwdev)
1292 {
1293 	int ret;
1294 
1295 	rtw89_hci_clr_idx_all(rtwdev);
1296 
1297 	ret = rtw89_hci_rst_bdram(rtwdev);
1298 	if (ret) {
1299 		rtw89_warn(rtwdev, "reset bdram busy\n");
1300 		return ret;
1301 	}
1302 
1303 	rtw89_hci_ctrl_trxhci(rtwdev, true);
1304 	rtw89_hci_ctrl_txdma_ch(rtwdev, true);
1305 
1306 	ret = rtw89_wow_config_mac(rtwdev, false);
1307 	if (ret) {
1308 		rtw89_err(rtwdev, "failed to config mac\n");
1309 		return ret;
1310 	}
1311 
1312 	/* Before enabling interrupt, we need to get AOAC report by reg due to RX
1313 	 * not enabled yet. Also, we need to sync RX related IV from firmware to
1314 	 * mac80211 before receiving RX packets from driver.
1315 	 * After enabling interrupt, we can get AOAC report from h2c and c2h, and
1316 	 * can get TX IV and complete rekey info. We need to update TX related IV
1317 	 * and new GTK info if rekey happened.
1318 	 */
1319 	ret = rtw89_wow_get_aoac_rpt(rtwdev, false);
1320 	if (!ret)
1321 		rtw89_wow_update_key_info(rtwdev, false);
1322 
1323 	rtw89_hci_enable_intr(rtwdev);
1324 	ret = rtw89_wow_get_aoac_rpt(rtwdev, true);
1325 	if (!ret)
1326 		rtw89_wow_update_key_info(rtwdev, true);
1327 
1328 	return 0;
1329 }
1330 
rtw89_wow_disable_trx_post(struct rtw89_dev * rtwdev)1331 static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev)
1332 {
1333 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1334 	struct ieee80211_vif *vif = rtw_wow->wow_vif;
1335 	int ret;
1336 
1337 	ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
1338 	if (ret)
1339 		rtw89_err(rtwdev, "cfg ppdu status\n");
1340 
1341 	rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
1342 
1343 	return ret;
1344 }
1345 
rtw89_wow_fw_start(struct rtw89_dev * rtwdev)1346 static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev)
1347 {
1348 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1349 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv;
1350 	int ret;
1351 
1352 	rtw89_wow_pattern_write(rtwdev);
1353 	rtw89_wow_construct_key_info(rtwdev);
1354 
1355 	ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, true);
1356 	if (ret) {
1357 		rtw89_err(rtwdev, "wow: failed to enable keep alive\n");
1358 		return ret;
1359 	}
1360 
1361 	ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, true);
1362 	if (ret) {
1363 		rtw89_err(rtwdev, "wow: failed to enable disconnect detect\n");
1364 		goto out;
1365 	}
1366 
1367 	ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, true);
1368 	if (ret) {
1369 		rtw89_err(rtwdev, "wow: failed to enable GTK offload\n");
1370 		goto out;
1371 	}
1372 
1373 	ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, true);
1374 	if (ret)
1375 		rtw89_warn(rtwdev, "wow: failed to enable arp offload\n");
1376 
1377 	ret = rtw89_wow_cfg_wake(rtwdev, true);
1378 	if (ret) {
1379 		rtw89_err(rtwdev, "wow: failed to config wake\n");
1380 		goto out;
1381 	}
1382 
1383 	ret = rtw89_wow_check_fw_status(rtwdev, true);
1384 	if (ret) {
1385 		rtw89_err(rtwdev, "wow: failed to check enable fw ready\n");
1386 		goto out;
1387 	}
1388 
1389 out:
1390 	return ret;
1391 }
1392 
rtw89_wow_fw_stop(struct rtw89_dev * rtwdev)1393 static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev)
1394 {
1395 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
1396 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv;
1397 	int ret;
1398 
1399 	rtw89_wow_pattern_clear(rtwdev);
1400 
1401 	ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, false);
1402 	if (ret) {
1403 		rtw89_err(rtwdev, "wow: failed to disable keep alive\n");
1404 		goto out;
1405 	}
1406 
1407 	ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, false);
1408 	if (ret) {
1409 		rtw89_err(rtwdev, "wow: failed to disable disconnect detect\n");
1410 		goto out;
1411 	}
1412 
1413 	ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, false);
1414 	if (ret) {
1415 		rtw89_err(rtwdev, "wow: failed to disable GTK offload\n");
1416 		goto out;
1417 	}
1418 
1419 	ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, false);
1420 	if (ret)
1421 		rtw89_warn(rtwdev, "wow: failed to disable arp offload\n");
1422 
1423 	rtw89_wow_key_clear(rtwdev);
1424 	rtw89_fw_release_general_pkt_list(rtwdev, true);
1425 
1426 	ret = rtw89_wow_cfg_wake(rtwdev, false);
1427 	if (ret) {
1428 		rtw89_err(rtwdev, "wow: failed to disable config wake\n");
1429 		goto out;
1430 	}
1431 
1432 	ret = rtw89_wow_check_fw_status(rtwdev, false);
1433 	if (ret) {
1434 		rtw89_err(rtwdev, "wow: failed to check disable fw ready\n");
1435 		goto out;
1436 	}
1437 
1438 out:
1439 	return ret;
1440 }
1441 
rtw89_wow_enable(struct rtw89_dev * rtwdev)1442 static int rtw89_wow_enable(struct rtw89_dev *rtwdev)
1443 {
1444 	int ret;
1445 
1446 	set_bit(RTW89_FLAG_WOWLAN, rtwdev->flags);
1447 
1448 	ret = rtw89_wow_enable_trx_pre(rtwdev);
1449 	if (ret) {
1450 		rtw89_err(rtwdev, "wow: failed to enable trx_pre\n");
1451 		goto out;
1452 	}
1453 
1454 	rtw89_fw_release_general_pkt_list(rtwdev, true);
1455 
1456 	ret = rtw89_wow_swap_fw(rtwdev, true);
1457 	if (ret) {
1458 		rtw89_err(rtwdev, "wow: failed to swap to wow fw\n");
1459 		goto out;
1460 	}
1461 
1462 	ret = rtw89_wow_fw_start(rtwdev);
1463 	if (ret) {
1464 		rtw89_err(rtwdev, "wow: failed to let wow fw start\n");
1465 		goto out;
1466 	}
1467 
1468 	rtw89_wow_enter_lps(rtwdev);
1469 
1470 	ret = rtw89_wow_enable_trx_post(rtwdev);
1471 	if (ret) {
1472 		rtw89_err(rtwdev, "wow: failed to enable trx_post\n");
1473 		goto out;
1474 	}
1475 
1476 	return 0;
1477 
1478 out:
1479 	clear_bit(RTW89_FLAG_WOWLAN, rtwdev->flags);
1480 	return ret;
1481 }
1482 
rtw89_wow_disable(struct rtw89_dev * rtwdev)1483 static int rtw89_wow_disable(struct rtw89_dev *rtwdev)
1484 {
1485 	int ret;
1486 
1487 	ret = rtw89_wow_disable_trx_pre(rtwdev);
1488 	if (ret) {
1489 		rtw89_err(rtwdev, "wow: failed to disable trx_pre\n");
1490 		goto out;
1491 	}
1492 
1493 	rtw89_wow_leave_lps(rtwdev);
1494 
1495 	ret = rtw89_wow_fw_stop(rtwdev);
1496 	if (ret) {
1497 		rtw89_err(rtwdev, "wow: failed to swap to normal fw\n");
1498 		goto out;
1499 	}
1500 
1501 	ret = rtw89_wow_swap_fw(rtwdev, false);
1502 	if (ret) {
1503 		rtw89_err(rtwdev, "wow: failed to disable trx_post\n");
1504 		goto out;
1505 	}
1506 
1507 	ret = rtw89_wow_disable_trx_post(rtwdev);
1508 	if (ret) {
1509 		rtw89_err(rtwdev, "wow: failed to disable trx_pre\n");
1510 		goto out;
1511 	}
1512 
1513 out:
1514 	clear_bit(RTW89_FLAG_WOWLAN, rtwdev->flags);
1515 	return ret;
1516 }
1517 
rtw89_wow_resume(struct rtw89_dev * rtwdev)1518 int rtw89_wow_resume(struct rtw89_dev *rtwdev)
1519 {
1520 	int ret;
1521 
1522 	if (!test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags)) {
1523 		rtw89_err(rtwdev, "wow is not enabled\n");
1524 		ret = -EPERM;
1525 		goto out;
1526 	}
1527 
1528 	if (!rtw89_mac_get_power_state(rtwdev)) {
1529 		rtw89_err(rtwdev, "chip is no power when resume\n");
1530 		ret = -EPERM;
1531 		goto out;
1532 	}
1533 
1534 	rtw89_wow_leave_deep_ps(rtwdev);
1535 
1536 	rtw89_wow_show_wakeup_reason(rtwdev);
1537 
1538 	ret = rtw89_wow_disable(rtwdev);
1539 	if (ret)
1540 		rtw89_err(rtwdev, "failed to disable wow\n");
1541 
1542 out:
1543 	rtw89_wow_clear_wakeups(rtwdev);
1544 	return ret;
1545 }
1546 
rtw89_wow_suspend(struct rtw89_dev * rtwdev,struct cfg80211_wowlan * wowlan)1547 int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan)
1548 {
1549 	int ret;
1550 
1551 	ret = rtw89_wow_set_wakeups(rtwdev, wowlan);
1552 	if (ret) {
1553 		rtw89_err(rtwdev, "failed to set wakeup event\n");
1554 		return ret;
1555 	}
1556 
1557 	rtw89_wow_leave_lps(rtwdev);
1558 
1559 	ret = rtw89_wow_enable(rtwdev);
1560 	if (ret) {
1561 		rtw89_err(rtwdev, "failed to enable wow\n");
1562 		return ret;
1563 	}
1564 
1565 	rtw89_wow_enter_deep_ps(rtwdev);
1566 
1567 	return 0;
1568 }
1569