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 static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) 16 { 17 __rtw89_leave_ps_mode(rtwdev); 18 } 19 20 static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev) 21 { 22 struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; 23 struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; 24 25 __rtw89_enter_ps_mode(rtwdev, rtwvif); 26 } 27 28 static void rtw89_wow_enter_lps(struct rtw89_dev *rtwdev) 29 { 30 struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; 31 struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; 32 33 rtw89_enter_lps(rtwdev, rtwvif, false); 34 } 35 36 static void rtw89_wow_leave_lps(struct rtw89_dev *rtwdev) 37 { 38 rtw89_leave_lps(rtwdev); 39 } 40 41 static int rtw89_wow_config_mac(struct rtw89_dev *rtwdev, bool enable_wow) 42 { 43 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; 44 int ret; 45 46 if (enable_wow) { 47 ret = rtw89_mac_resize_ple_rx_quota(rtwdev, true); 48 if (ret) { 49 rtw89_err(rtwdev, "[ERR]patch rx qta %d\n", ret); 50 return ret; 51 } 52 rtw89_write32_set(rtwdev, R_AX_RX_FUNCTION_STOP, B_AX_HDR_RX_STOP); 53 rtw89_write32_clr(rtwdev, mac->rx_fltr, B_AX_SNIFFER_MODE); 54 rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false); 55 rtw89_write32(rtwdev, R_AX_ACTION_FWD0, 0); 56 rtw89_write32(rtwdev, R_AX_ACTION_FWD1, 0); 57 rtw89_write32(rtwdev, R_AX_TF_FWD, 0); 58 rtw89_write32(rtwdev, R_AX_HW_RPT_FWD, 0); 59 } else { 60 ret = rtw89_mac_resize_ple_rx_quota(rtwdev, false); 61 if (ret) { 62 rtw89_err(rtwdev, "[ERR]patch rx qta %d\n", ret); 63 return ret; 64 } 65 rtw89_write32_clr(rtwdev, R_AX_RX_FUNCTION_STOP, B_AX_HDR_RX_STOP); 66 rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); 67 rtw89_write32(rtwdev, R_AX_ACTION_FWD0, TRXCFG_MPDU_PROC_ACT_FRWD); 68 rtw89_write32(rtwdev, R_AX_TF_FWD, TRXCFG_MPDU_PROC_TF_FRWD); 69 } 70 71 return 0; 72 } 73 74 static void rtw89_wow_set_rx_filter(struct rtw89_dev *rtwdev, bool enable) 75 { 76 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; 77 enum rtw89_mac_fwd_target fwd_target = enable ? 78 RTW89_FWD_DONT_CARE : 79 RTW89_FWD_TO_HOST; 80 81 mac->typ_fltr_opt(rtwdev, RTW89_MGNT, fwd_target, RTW89_MAC_0); 82 mac->typ_fltr_opt(rtwdev, RTW89_CTRL, fwd_target, RTW89_MAC_0); 83 mac->typ_fltr_opt(rtwdev, RTW89_DATA, fwd_target, RTW89_MAC_0); 84 } 85 86 static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) 87 { 88 enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; 89 struct cfg80211_wowlan_nd_info nd_info; 90 struct cfg80211_wowlan_wakeup wakeup = { 91 .pattern_idx = -1, 92 }; 93 u32 wow_reason_reg; 94 u8 reason; 95 96 if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B) 97 wow_reason_reg = R_AX_C2HREG_DATA3 + 3; 98 else 99 wow_reason_reg = R_AX_C2HREG_DATA3_V1 + 3; 100 101 reason = rtw89_read8(rtwdev, wow_reason_reg); 102 103 switch (reason) { 104 case RTW89_WOW_RSN_RX_DEAUTH: 105 wakeup.disconnect = true; 106 rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx deauth\n"); 107 break; 108 case RTW89_WOW_RSN_DISCONNECT: 109 wakeup.disconnect = true; 110 rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: AP is off\n"); 111 break; 112 case RTW89_WOW_RSN_RX_MAGIC_PKT: 113 wakeup.magic_pkt = true; 114 rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx magic packet\n"); 115 break; 116 case RTW89_WOW_RSN_RX_GTK_REKEY: 117 wakeup.gtk_rekey_failure = true; 118 rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx gtk rekey\n"); 119 break; 120 case RTW89_WOW_RSN_RX_PATTERN_MATCH: 121 /* Current firmware and driver don't report pattern index 122 * Use pattern_idx to 0 defaultly. 123 */ 124 wakeup.pattern_idx = 0; 125 rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx pattern match packet\n"); 126 break; 127 case RTW89_WOW_RSN_RX_NLO: 128 /* Current firmware and driver don't report ssid index. 129 * Use 0 for n_matches based on its comment. 130 */ 131 nd_info.n_matches = 0; 132 wakeup.net_detect = &nd_info; 133 rtw89_debug(rtwdev, RTW89_DBG_WOW, "Rx NLO\n"); 134 break; 135 default: 136 rtw89_warn(rtwdev, "Unknown wakeup reason %x\n", reason); 137 ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL, 138 GFP_KERNEL); 139 return; 140 } 141 142 ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup, 143 GFP_KERNEL); 144 } 145 146 static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) 147 { 148 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 149 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 150 151 /* Current wowlan function support setting of only one STATION vif. 152 * So when one suitable vif is found, stop the iteration. 153 */ 154 if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION) 155 return; 156 157 switch (rtwvif->net_type) { 158 case RTW89_NET_TYPE_INFRA: 159 rtw_wow->wow_vif = vif; 160 break; 161 case RTW89_NET_TYPE_NO_LINK: 162 default: 163 break; 164 } 165 } 166 167 static u16 __rtw89_cal_crc16(u8 data, u16 crc) 168 { 169 u8 shift_in, data_bit; 170 u8 crc_bit4, crc_bit11, crc_bit15; 171 u16 crc_result; 172 int index; 173 174 for (index = 0; index < 8; index++) { 175 crc_bit15 = crc & BIT(15) ? 1 : 0; 176 data_bit = data & BIT(index) ? 1 : 0; 177 shift_in = crc_bit15 ^ data_bit; 178 179 crc_result = crc << 1; 180 181 if (shift_in == 0) 182 crc_result &= ~BIT(0); 183 else 184 crc_result |= BIT(0); 185 186 crc_bit11 = (crc & BIT(11) ? 1 : 0) ^ shift_in; 187 188 if (crc_bit11 == 0) 189 crc_result &= ~BIT(12); 190 else 191 crc_result |= BIT(12); 192 193 crc_bit4 = (crc & BIT(4) ? 1 : 0) ^ shift_in; 194 195 if (crc_bit4 == 0) 196 crc_result &= ~BIT(5); 197 else 198 crc_result |= BIT(5); 199 200 crc = crc_result; 201 } 202 return crc; 203 } 204 205 static u16 rtw89_calc_crc(u8 *pdata, int length) 206 { 207 u16 crc = 0xffff; 208 int i; 209 210 for (i = 0; i < length; i++) 211 crc = __rtw89_cal_crc16(pdata[i], crc); 212 213 /* get 1' complement */ 214 return ~crc; 215 } 216 217 static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, 218 struct rtw89_wow_cam_info *rtw_pattern, 219 const u8 *pattern, u8 da_mask) 220 { 221 u8 da[ETH_ALEN]; 222 223 ether_addr_copy_mask(da, pattern, da_mask); 224 225 /* Each pattern is divided into different kinds by DA address 226 * a. DA is broadcast address: set bc = 0; 227 * b. DA is multicast address: set mc = 0 228 * c. DA is unicast address same as dev's mac address: set uc = 0 229 * d. DA is unmasked. Also called wildcard type: set uc = bc = mc = 0 230 * e. Others is invalid type. 231 */ 232 233 if (is_broadcast_ether_addr(da)) 234 rtw_pattern->bc = true; 235 else if (is_multicast_ether_addr(da)) 236 rtw_pattern->mc = true; 237 else if (ether_addr_equal(da, rtwvif->mac_addr) && 238 da_mask == GENMASK(5, 0)) 239 rtw_pattern->uc = true; 240 else if (!da_mask) /*da_mask == 0 mean wildcard*/ 241 return 0; 242 else 243 return -EPERM; 244 245 return 0; 246 } 247 248 static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, 249 struct rtw89_vif *rtwvif, 250 const struct cfg80211_pkt_pattern *pkt_pattern, 251 struct rtw89_wow_cam_info *rtw_pattern) 252 { 253 u8 mask_hw[RTW89_MAX_PATTERN_MASK_SIZE * 4] = {0}; 254 u8 content[RTW89_MAX_PATTERN_SIZE] = {0}; 255 const u8 *mask; 256 const u8 *pattern; 257 u8 mask_len; 258 u16 count; 259 u32 len; 260 int i, ret; 261 262 pattern = pkt_pattern->pattern; 263 len = pkt_pattern->pattern_len; 264 mask = pkt_pattern->mask; 265 mask_len = DIV_ROUND_UP(len, 8); 266 memset(rtw_pattern, 0, sizeof(*rtw_pattern)); 267 268 ret = rtw89_wow_pattern_get_type(rtwvif, rtw_pattern, pattern, 269 mask[0] & GENMASK(5, 0)); 270 if (ret) 271 return ret; 272 273 /* translate mask from os to mask for hw 274 * pattern from OS uses 'ethenet frame', like this: 275 * | 6 | 6 | 2 | 20 | Variable | 4 | 276 * |--------+--------+------+-----------+------------+-----| 277 * | 802.3 Mac Header | IP Header | TCP Packet | FCS | 278 * | DA | SA | Type | 279 * 280 * BUT, packet catched by our HW is in '802.11 frame', begin from LLC 281 * | 24 or 30 | 6 | 2 | 20 | Variable | 4 | 282 * |-------------------+--------+------+-----------+------------+-----| 283 * | 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS | 284 * | Others | Tpye | 285 * 286 * Therefore, we need translate mask_from_OS to mask_to_hw. 287 * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0, 288 * because new mask[0~5] means 'SA', but our HW packet begins from LLC, 289 * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match. 290 */ 291 292 /* Shift 6 bits */ 293 for (i = 0; i < mask_len - 1; i++) { 294 mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6)) | 295 u8_get_bits(mask[i + 1], GENMASK(5, 0)) << 2; 296 } 297 mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6)); 298 299 /* Set bit 0-5 to zero */ 300 mask_hw[0] &= ~GENMASK(5, 0); 301 302 memcpy(rtw_pattern->mask, mask_hw, sizeof(rtw_pattern->mask)); 303 304 /* To get the wake up pattern from the mask. 305 * We do not count first 12 bits which means 306 * DA[6] and SA[6] in the pattern to match HW design. 307 */ 308 count = 0; 309 for (i = 12; i < len; i++) { 310 if ((mask[i / 8] >> (i % 8)) & 0x01) { 311 content[count] = pattern[i]; 312 count++; 313 } 314 } 315 316 rtw_pattern->crc = rtw89_calc_crc(content, count); 317 318 return 0; 319 } 320 321 static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev, 322 struct rtw89_vif *rtwvif, 323 struct cfg80211_wowlan *wowlan) 324 { 325 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 326 struct rtw89_wow_cam_info *rtw_pattern = rtw_wow->patterns; 327 int i; 328 int ret; 329 330 if (!wowlan->n_patterns || !wowlan->patterns) 331 return 0; 332 333 for (i = 0; i < wowlan->n_patterns; i++) { 334 rtw_pattern = &rtw_wow->patterns[i]; 335 ret = rtw89_wow_pattern_generate(rtwdev, rtwvif, 336 &wowlan->patterns[i], 337 rtw_pattern); 338 if (ret) { 339 rtw89_err(rtwdev, "failed to generate pattern(%d)\n", i); 340 rtw_wow->pattern_cnt = 0; 341 return ret; 342 } 343 344 rtw_pattern->r_w = true; 345 rtw_pattern->idx = i; 346 rtw_pattern->negative_pattern_match = false; 347 rtw_pattern->skip_mac_hdr = true; 348 rtw_pattern->valid = true; 349 } 350 rtw_wow->pattern_cnt = wowlan->n_patterns; 351 352 return 0; 353 } 354 355 static void rtw89_wow_pattern_clear_cam(struct rtw89_dev *rtwdev) 356 { 357 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 358 struct rtw89_wow_cam_info *rtw_pattern = rtw_wow->patterns; 359 int i = 0; 360 361 for (i = 0; i < rtw_wow->pattern_cnt; i++) { 362 rtw_pattern = &rtw_wow->patterns[i]; 363 rtw_pattern->valid = false; 364 rtw89_fw_wow_cam_update(rtwdev, rtw_pattern); 365 } 366 } 367 368 static void rtw89_wow_pattern_write(struct rtw89_dev *rtwdev) 369 { 370 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 371 struct rtw89_wow_cam_info *rtw_pattern = rtw_wow->patterns; 372 int i; 373 374 for (i = 0; i < rtw_wow->pattern_cnt; i++) 375 rtw89_fw_wow_cam_update(rtwdev, rtw_pattern + i); 376 } 377 378 static void rtw89_wow_pattern_clear(struct rtw89_dev *rtwdev) 379 { 380 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 381 382 rtw89_wow_pattern_clear_cam(rtwdev); 383 384 rtw_wow->pattern_cnt = 0; 385 memset(rtw_wow->patterns, 0, sizeof(rtw_wow->patterns)); 386 } 387 388 static void rtw89_wow_clear_wakeups(struct rtw89_dev *rtwdev) 389 { 390 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 391 392 rtw_wow->wow_vif = NULL; 393 rtw89_core_release_all_bits_map(rtw_wow->flags, RTW89_WOW_FLAG_NUM); 394 rtw_wow->pattern_cnt = 0; 395 } 396 397 static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, 398 struct cfg80211_wowlan *wowlan) 399 { 400 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 401 struct rtw89_vif *rtwvif; 402 403 if (wowlan->disconnect) 404 set_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags); 405 if (wowlan->magic_pkt) 406 set_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags); 407 408 rtw89_for_each_rtwvif(rtwdev, rtwvif) 409 rtw89_wow_vif_iter(rtwdev, rtwvif); 410 411 if (!rtw_wow->wow_vif) 412 return -EPERM; 413 414 rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv; 415 return rtw89_wow_parse_patterns(rtwdev, rtwvif, wowlan); 416 } 417 418 static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) 419 { 420 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 421 struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; 422 struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; 423 struct ieee80211_sta *wow_sta; 424 struct rtw89_sta *rtwsta = NULL; 425 int ret; 426 427 wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); 428 if (wow_sta) 429 rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; 430 431 if (wow) { 432 if (rtw_wow->pattern_cnt) 433 rtwvif->wowlan_pattern = true; 434 if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags)) 435 rtwvif->wowlan_magic = true; 436 } else { 437 rtwvif->wowlan_pattern = false; 438 rtwvif->wowlan_magic = false; 439 } 440 441 ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow); 442 if (ret) { 443 rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n"); 444 return ret; 445 } 446 447 if (wow) { 448 ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); 449 if (ret) { 450 rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", 451 ret); 452 return ret; 453 } 454 } 455 456 ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); 457 if (ret) { 458 rtw89_warn(rtwdev, "failed to send h2c cam\n"); 459 return ret; 460 } 461 462 ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow); 463 if (ret) { 464 rtw89_err(rtwdev, "failed to fw wow global\n"); 465 return ret; 466 } 467 468 return 0; 469 } 470 471 static int rtw89_wow_check_fw_status(struct rtw89_dev *rtwdev, bool wow_enable) 472 { 473 u8 polling; 474 int ret; 475 476 ret = read_poll_timeout_atomic(rtw89_read8_mask, polling, 477 wow_enable == !!polling, 478 50, 50000, false, rtwdev, 479 R_AX_WOW_CTRL, B_AX_WOW_WOWEN); 480 if (ret) 481 rtw89_err(rtwdev, "failed to check wow status %s\n", 482 wow_enable ? "enabled" : "disabled"); 483 return ret; 484 } 485 486 static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) 487 { 488 enum rtw89_fw_type fw_type = wow ? RTW89_FW_WOWLAN : RTW89_FW_NORMAL; 489 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 490 struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; 491 struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; 492 const struct rtw89_chip_info *chip = rtwdev->chip; 493 bool include_bb = !!chip->bbmcu_nr; 494 struct ieee80211_sta *wow_sta; 495 struct rtw89_sta *rtwsta = NULL; 496 bool is_conn = true; 497 int ret; 498 499 rtw89_hci_disable_intr(rtwdev); 500 501 wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); 502 if (wow_sta) 503 rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; 504 else 505 is_conn = false; 506 507 ret = rtw89_fw_download(rtwdev, fw_type, include_bb); 508 if (ret) { 509 rtw89_warn(rtwdev, "download fw failed\n"); 510 return ret; 511 } 512 513 rtw89_phy_init_rf_reg(rtwdev, true); 514 515 ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, 516 RTW89_ROLE_FW_RESTORE); 517 if (ret) { 518 rtw89_warn(rtwdev, "failed to send h2c role maintain\n"); 519 return ret; 520 } 521 522 ret = rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, wow_vif, wow_sta); 523 if (ret) { 524 rtw89_warn(rtwdev, "failed to send h2c assoc cmac tbl\n"); 525 return ret; 526 } 527 528 if (!is_conn) 529 rtw89_cam_reset_keys(rtwdev); 530 531 ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, !is_conn); 532 if (ret) { 533 rtw89_warn(rtwdev, "failed to send h2c join info\n"); 534 return ret; 535 } 536 537 ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); 538 if (ret) { 539 rtw89_warn(rtwdev, "failed to send h2c cam\n"); 540 return ret; 541 } 542 543 if (is_conn) { 544 ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id); 545 if (ret) { 546 rtw89_warn(rtwdev, "failed to send h2c general packet\n"); 547 return ret; 548 } 549 rtw89_phy_ra_assoc(rtwdev, wow_sta); 550 rtw89_phy_set_bss_color(rtwdev, wow_vif); 551 rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, wow_vif); 552 } 553 554 rtw89_mac_hw_mgnt_sec(rtwdev, wow); 555 rtw89_hci_enable_intr(rtwdev); 556 557 return 0; 558 } 559 560 static int rtw89_wow_enable_trx_pre(struct rtw89_dev *rtwdev) 561 { 562 int ret; 563 564 rtw89_hci_ctrl_txdma_ch(rtwdev, false); 565 rtw89_hci_ctrl_txdma_fw_ch(rtwdev, true); 566 567 rtw89_mac_ptk_drop_by_band_and_wait(rtwdev, RTW89_MAC_0); 568 569 ret = rtw89_hci_poll_txdma_ch(rtwdev); 570 if (ret) { 571 rtw89_err(rtwdev, "txdma ch busy\n"); 572 return ret; 573 } 574 rtw89_wow_set_rx_filter(rtwdev, true); 575 576 ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false); 577 if (ret) { 578 rtw89_err(rtwdev, "cfg ppdu status\n"); 579 return ret; 580 } 581 582 return 0; 583 } 584 585 static int rtw89_wow_enable_trx_post(struct rtw89_dev *rtwdev) 586 { 587 int ret; 588 589 rtw89_hci_disable_intr(rtwdev); 590 rtw89_hci_ctrl_trxhci(rtwdev, false); 591 592 ret = rtw89_hci_poll_txdma_ch(rtwdev); 593 if (ret) { 594 rtw89_err(rtwdev, "failed to poll txdma ch idle pcie\n"); 595 return ret; 596 } 597 598 ret = rtw89_wow_config_mac(rtwdev, true); 599 if (ret) { 600 rtw89_err(rtwdev, "failed to config mac\n"); 601 return ret; 602 } 603 604 rtw89_wow_set_rx_filter(rtwdev, false); 605 rtw89_hci_reset(rtwdev); 606 607 return 0; 608 } 609 610 static int rtw89_wow_disable_trx_pre(struct rtw89_dev *rtwdev) 611 { 612 int ret; 613 614 rtw89_hci_clr_idx_all(rtwdev); 615 616 ret = rtw89_hci_rst_bdram(rtwdev); 617 if (ret) { 618 rtw89_warn(rtwdev, "reset bdram busy\n"); 619 return ret; 620 } 621 622 rtw89_hci_ctrl_trxhci(rtwdev, true); 623 rtw89_hci_ctrl_txdma_ch(rtwdev, true); 624 625 ret = rtw89_wow_config_mac(rtwdev, false); 626 if (ret) { 627 rtw89_err(rtwdev, "failed to config mac\n"); 628 return ret; 629 } 630 rtw89_hci_enable_intr(rtwdev); 631 632 return 0; 633 } 634 635 static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev) 636 { 637 int ret; 638 639 ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); 640 if (ret) 641 rtw89_err(rtwdev, "cfg ppdu status\n"); 642 643 return ret; 644 } 645 646 static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) 647 { 648 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 649 struct rtw89_vif *rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv; 650 int ret; 651 652 rtw89_wow_pattern_write(rtwdev); 653 654 ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, true); 655 if (ret) { 656 rtw89_err(rtwdev, "wow: failed to enable keep alive\n"); 657 return ret; 658 } 659 660 ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, true); 661 if (ret) { 662 rtw89_err(rtwdev, "wow: failed to enable disconnect detect\n"); 663 goto out; 664 } 665 666 ret = rtw89_wow_cfg_wake(rtwdev, true); 667 if (ret) { 668 rtw89_err(rtwdev, "wow: failed to config wake\n"); 669 goto out; 670 } 671 672 ret = rtw89_wow_check_fw_status(rtwdev, true); 673 if (ret) { 674 rtw89_err(rtwdev, "wow: failed to check enable fw ready\n"); 675 goto out; 676 } 677 678 out: 679 return ret; 680 } 681 682 static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) 683 { 684 struct rtw89_wow_param *rtw_wow = &rtwdev->wow; 685 struct rtw89_vif *rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv; 686 int ret; 687 688 rtw89_wow_pattern_clear(rtwdev); 689 690 ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, false); 691 if (ret) { 692 rtw89_err(rtwdev, "wow: failed to disable keep alive\n"); 693 goto out; 694 } 695 696 ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, false); 697 if (ret) { 698 rtw89_err(rtwdev, "wow: failed to disable disconnect detect\n"); 699 goto out; 700 } 701 702 ret = rtw89_wow_cfg_wake(rtwdev, false); 703 if (ret) { 704 rtw89_err(rtwdev, "wow: failed to disable config wake\n"); 705 goto out; 706 } 707 708 rtw89_fw_release_general_pkt_list(rtwdev, true); 709 710 ret = rtw89_wow_check_fw_status(rtwdev, false); 711 if (ret) { 712 rtw89_err(rtwdev, "wow: failed to check disable fw ready\n"); 713 goto out; 714 } 715 716 out: 717 return ret; 718 } 719 720 static int rtw89_wow_enable(struct rtw89_dev *rtwdev) 721 { 722 int ret; 723 724 set_bit(RTW89_FLAG_WOWLAN, rtwdev->flags); 725 726 ret = rtw89_wow_enable_trx_pre(rtwdev); 727 if (ret) { 728 rtw89_err(rtwdev, "wow: failed to enable trx_pre\n"); 729 goto out; 730 } 731 732 rtw89_fw_release_general_pkt_list(rtwdev, true); 733 734 ret = rtw89_wow_swap_fw(rtwdev, true); 735 if (ret) { 736 rtw89_err(rtwdev, "wow: failed to swap to wow fw\n"); 737 goto out; 738 } 739 740 ret = rtw89_wow_fw_start(rtwdev); 741 if (ret) { 742 rtw89_err(rtwdev, "wow: failed to let wow fw start\n"); 743 goto out; 744 } 745 746 rtw89_wow_enter_lps(rtwdev); 747 748 ret = rtw89_wow_enable_trx_post(rtwdev); 749 if (ret) { 750 rtw89_err(rtwdev, "wow: failed to enable trx_post\n"); 751 goto out; 752 } 753 754 return 0; 755 756 out: 757 clear_bit(RTW89_FLAG_WOWLAN, rtwdev->flags); 758 return ret; 759 } 760 761 static int rtw89_wow_disable(struct rtw89_dev *rtwdev) 762 { 763 int ret; 764 765 ret = rtw89_wow_disable_trx_pre(rtwdev); 766 if (ret) { 767 rtw89_err(rtwdev, "wow: failed to disable trx_pre\n"); 768 goto out; 769 } 770 771 rtw89_wow_leave_lps(rtwdev); 772 773 ret = rtw89_wow_fw_stop(rtwdev); 774 if (ret) { 775 rtw89_err(rtwdev, "wow: failed to swap to normal fw\n"); 776 goto out; 777 } 778 779 ret = rtw89_wow_swap_fw(rtwdev, false); 780 if (ret) { 781 rtw89_err(rtwdev, "wow: failed to disable trx_post\n"); 782 goto out; 783 } 784 785 ret = rtw89_wow_disable_trx_post(rtwdev); 786 if (ret) { 787 rtw89_err(rtwdev, "wow: failed to disable trx_pre\n"); 788 goto out; 789 } 790 791 out: 792 clear_bit(RTW89_FLAG_WOWLAN, rtwdev->flags); 793 return ret; 794 } 795 796 int rtw89_wow_resume(struct rtw89_dev *rtwdev) 797 { 798 int ret; 799 800 if (!test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags)) { 801 rtw89_err(rtwdev, "wow is not enabled\n"); 802 ret = -EPERM; 803 goto out; 804 } 805 806 if (!rtw89_mac_get_power_state(rtwdev)) { 807 rtw89_err(rtwdev, "chip is no power when resume\n"); 808 ret = -EPERM; 809 goto out; 810 } 811 812 rtw89_wow_leave_deep_ps(rtwdev); 813 814 rtw89_wow_show_wakeup_reason(rtwdev); 815 816 ret = rtw89_wow_disable(rtwdev); 817 if (ret) 818 rtw89_err(rtwdev, "failed to disable wow\n"); 819 820 out: 821 rtw89_wow_clear_wakeups(rtwdev); 822 return ret; 823 } 824 825 int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan) 826 { 827 int ret; 828 829 ret = rtw89_wow_set_wakeups(rtwdev, wowlan); 830 if (ret) { 831 rtw89_err(rtwdev, "failed to set wakeup event\n"); 832 return ret; 833 } 834 835 rtw89_wow_leave_lps(rtwdev); 836 837 ret = rtw89_wow_enable(rtwdev); 838 if (ret) { 839 rtw89_err(rtwdev, "failed to enable wow\n"); 840 return ret; 841 } 842 843 rtw89_wow_enter_deep_ps(rtwdev); 844 845 return 0; 846 } 847