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