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