12774f206SBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 22774f206SBjoern A. Zeeb /* Copyright(c) 2018-2019 Realtek Corporation 32774f206SBjoern A. Zeeb */ 42774f206SBjoern A. Zeeb 52774f206SBjoern A. Zeeb #include "main.h" 62774f206SBjoern A. Zeeb #include "reg.h" 72774f206SBjoern A. Zeeb #include "fw.h" 82774f206SBjoern A. Zeeb #include "ps.h" 92774f206SBjoern A. Zeeb #include "mac.h" 102774f206SBjoern A. Zeeb #include "coex.h" 112774f206SBjoern A. Zeeb #include "debug.h" 122774f206SBjoern A. Zeeb 132774f206SBjoern A. Zeeb static int rtw_ips_pwr_up(struct rtw_dev *rtwdev) 142774f206SBjoern A. Zeeb { 152774f206SBjoern A. Zeeb int ret; 162774f206SBjoern A. Zeeb 172774f206SBjoern A. Zeeb ret = rtw_core_start(rtwdev); 182774f206SBjoern A. Zeeb if (ret) 192774f206SBjoern A. Zeeb rtw_err(rtwdev, "leave idle state failed\n"); 202774f206SBjoern A. Zeeb 21*90aac0d8SBjoern A. Zeeb rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); 222774f206SBjoern A. Zeeb rtw_set_channel(rtwdev); 232774f206SBjoern A. Zeeb 242774f206SBjoern A. Zeeb return ret; 252774f206SBjoern A. Zeeb } 262774f206SBjoern A. Zeeb 272774f206SBjoern A. Zeeb int rtw_enter_ips(struct rtw_dev *rtwdev) 282774f206SBjoern A. Zeeb { 29*90aac0d8SBjoern A. Zeeb if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags)) 30*90aac0d8SBjoern A. Zeeb return 0; 312774f206SBjoern A. Zeeb 322774f206SBjoern A. Zeeb rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER); 332774f206SBjoern A. Zeeb 342774f206SBjoern A. Zeeb rtw_core_stop(rtwdev); 352774f206SBjoern A. Zeeb rtw_hci_link_ps(rtwdev, true); 362774f206SBjoern A. Zeeb 372774f206SBjoern A. Zeeb return 0; 382774f206SBjoern A. Zeeb } 392774f206SBjoern A. Zeeb 40*90aac0d8SBjoern A. Zeeb static void rtw_restore_port_cfg_iter(void *data, struct ieee80211_vif *vif) 412774f206SBjoern A. Zeeb { 422774f206SBjoern A. Zeeb struct rtw_dev *rtwdev = data; 432774f206SBjoern A. Zeeb struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; 442774f206SBjoern A. Zeeb u32 config = ~0; 452774f206SBjoern A. Zeeb 462774f206SBjoern A. Zeeb rtw_vif_port_config(rtwdev, rtwvif, config); 472774f206SBjoern A. Zeeb } 482774f206SBjoern A. Zeeb 492774f206SBjoern A. Zeeb int rtw_leave_ips(struct rtw_dev *rtwdev) 502774f206SBjoern A. Zeeb { 512774f206SBjoern A. Zeeb int ret; 522774f206SBjoern A. Zeeb 53*90aac0d8SBjoern A. Zeeb if (test_bit(RTW_FLAG_POWERON, rtwdev->flags)) 54*90aac0d8SBjoern A. Zeeb return 0; 55*90aac0d8SBjoern A. Zeeb 562774f206SBjoern A. Zeeb rtw_hci_link_ps(rtwdev, false); 572774f206SBjoern A. Zeeb 582774f206SBjoern A. Zeeb ret = rtw_ips_pwr_up(rtwdev); 592774f206SBjoern A. Zeeb if (ret) { 602774f206SBjoern A. Zeeb rtw_err(rtwdev, "failed to leave ips state\n"); 612774f206SBjoern A. Zeeb return ret; 622774f206SBjoern A. Zeeb } 632774f206SBjoern A. Zeeb 64*90aac0d8SBjoern A. Zeeb rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev); 652774f206SBjoern A. Zeeb 662774f206SBjoern A. Zeeb return 0; 672774f206SBjoern A. Zeeb } 682774f206SBjoern A. Zeeb 692774f206SBjoern A. Zeeb void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter) 702774f206SBjoern A. Zeeb { 712774f206SBjoern A. Zeeb u8 request, confirm, polling; 722774f206SBjoern A. Zeeb int ret; 732774f206SBjoern A. Zeeb 742774f206SBjoern A. Zeeb request = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr); 752774f206SBjoern A. Zeeb confirm = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr); 762774f206SBjoern A. Zeeb 772774f206SBjoern A. Zeeb /* toggle to request power mode, others remain 0 */ 782774f206SBjoern A. Zeeb request ^= request | BIT_RPWM_TOGGLE; 792774f206SBjoern A. Zeeb if (enter) { 802774f206SBjoern A. Zeeb request |= POWER_MODE_LCLK; 812774f206SBjoern A. Zeeb if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG) 822774f206SBjoern A. Zeeb request |= POWER_MODE_PG; 832774f206SBjoern A. Zeeb } 842774f206SBjoern A. Zeeb /* Each request require an ack from firmware */ 852774f206SBjoern A. Zeeb request |= POWER_MODE_ACK; 862774f206SBjoern A. Zeeb 872774f206SBjoern A. Zeeb if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) 882774f206SBjoern A. Zeeb request |= POWER_TX_WAKE; 892774f206SBjoern A. Zeeb 902774f206SBjoern A. Zeeb rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, request); 912774f206SBjoern A. Zeeb 922774f206SBjoern A. Zeeb /* Check firmware get the power requset and ack via cpwm register */ 932774f206SBjoern A. Zeeb ret = read_poll_timeout_atomic(rtw_read8, polling, 942774f206SBjoern A. Zeeb (polling ^ confirm) & BIT_RPWM_TOGGLE, 952774f206SBjoern A. Zeeb 100, 15000, true, rtwdev, 962774f206SBjoern A. Zeeb rtwdev->hci.cpwm_addr); 972774f206SBjoern A. Zeeb if (ret) { 982774f206SBjoern A. Zeeb /* Hit here means that driver failed to get an ack from firmware. 992774f206SBjoern A. Zeeb * The reason could be that hardware is locked at Deep sleep, 1002774f206SBjoern A. Zeeb * so most of the hardware circuits are not working, even 1012774f206SBjoern A. Zeeb * register read/write; or firmware is locked in some state and 1022774f206SBjoern A. Zeeb * cannot get the request. It should be treated as fatal error 1032774f206SBjoern A. Zeeb * and requires an entire analysis about the firmware/hardware. 1042774f206SBjoern A. Zeeb */ 1052774f206SBjoern A. Zeeb WARN(1, "firmware failed to ack driver for %s Deep Power mode\n", 1062774f206SBjoern A. Zeeb enter ? "entering" : "leaving"); 1072774f206SBjoern A. Zeeb } 1082774f206SBjoern A. Zeeb } 1092774f206SBjoern A. Zeeb EXPORT_SYMBOL(rtw_power_mode_change); 1102774f206SBjoern A. Zeeb 1112774f206SBjoern A. Zeeb static void __rtw_leave_lps_deep(struct rtw_dev *rtwdev) 1122774f206SBjoern A. Zeeb { 1132774f206SBjoern A. Zeeb rtw_hci_deep_ps(rtwdev, false); 1142774f206SBjoern A. Zeeb } 1152774f206SBjoern A. Zeeb 1162774f206SBjoern A. Zeeb static int __rtw_fw_leave_lps_check_reg(struct rtw_dev *rtwdev) 1172774f206SBjoern A. Zeeb { 1182774f206SBjoern A. Zeeb int i; 1192774f206SBjoern A. Zeeb 1202774f206SBjoern A. Zeeb /* Driver needs to wait for firmware to leave LPS state 1212774f206SBjoern A. Zeeb * successfully. Firmware will send null packet to inform AP, 1222774f206SBjoern A. Zeeb * and see if AP sends an ACK back, then firmware will restore 1232774f206SBjoern A. Zeeb * the REG_TCR register. 1242774f206SBjoern A. Zeeb * 1252774f206SBjoern A. Zeeb * If driver does not wait for firmware, null packet with 1262774f206SBjoern A. Zeeb * PS bit could be sent due to incorrect REG_TCR setting. 1272774f206SBjoern A. Zeeb * 1282774f206SBjoern A. Zeeb * In our test, 100ms should be enough for firmware to finish 1292774f206SBjoern A. Zeeb * the flow. If REG_TCR Register is still incorrect after 100ms, 1302774f206SBjoern A. Zeeb * just modify it directly, and throw a warn message. 1312774f206SBjoern A. Zeeb */ 1322774f206SBjoern A. Zeeb for (i = 0 ; i < LEAVE_LPS_TRY_CNT; i++) { 1332774f206SBjoern A. Zeeb if (rtw_read32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN) == 0) 1342774f206SBjoern A. Zeeb return 0; 1352774f206SBjoern A. Zeeb msleep(20); 1362774f206SBjoern A. Zeeb } 1372774f206SBjoern A. Zeeb 1382774f206SBjoern A. Zeeb return -EBUSY; 1392774f206SBjoern A. Zeeb } 1402774f206SBjoern A. Zeeb 1412774f206SBjoern A. Zeeb static int __rtw_fw_leave_lps_check_c2h(struct rtw_dev *rtwdev) 1422774f206SBjoern A. Zeeb { 1432774f206SBjoern A. Zeeb if (wait_for_completion_timeout(&rtwdev->lps_leave_check, 1442774f206SBjoern A. Zeeb LEAVE_LPS_TIMEOUT)) 1452774f206SBjoern A. Zeeb return 0; 1462774f206SBjoern A. Zeeb return -EBUSY; 1472774f206SBjoern A. Zeeb } 1482774f206SBjoern A. Zeeb 1492774f206SBjoern A. Zeeb static void rtw_fw_leave_lps_check(struct rtw_dev *rtwdev) 1502774f206SBjoern A. Zeeb { 1512774f206SBjoern A. Zeeb bool ret = false; 1522774f206SBjoern A. Zeeb struct rtw_fw_state *fw; 1532774f206SBjoern A. Zeeb 1542774f206SBjoern A. Zeeb if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) 1552774f206SBjoern A. Zeeb fw = &rtwdev->wow_fw; 1562774f206SBjoern A. Zeeb else 1572774f206SBjoern A. Zeeb fw = &rtwdev->fw; 1582774f206SBjoern A. Zeeb 1592774f206SBjoern A. Zeeb if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H)) 1602774f206SBjoern A. Zeeb ret = __rtw_fw_leave_lps_check_c2h(rtwdev); 1612774f206SBjoern A. Zeeb else 1622774f206SBjoern A. Zeeb ret = __rtw_fw_leave_lps_check_reg(rtwdev); 1632774f206SBjoern A. Zeeb 1642774f206SBjoern A. Zeeb if (ret) { 1652774f206SBjoern A. Zeeb rtw_write32_clr(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN); 1662774f206SBjoern A. Zeeb rtw_warn(rtwdev, "firmware failed to leave lps state\n"); 1672774f206SBjoern A. Zeeb } 1682774f206SBjoern A. Zeeb } 1692774f206SBjoern A. Zeeb 1702774f206SBjoern A. Zeeb static void rtw_fw_leave_lps_check_prepare(struct rtw_dev *rtwdev) 1712774f206SBjoern A. Zeeb { 1722774f206SBjoern A. Zeeb struct rtw_fw_state *fw; 1732774f206SBjoern A. Zeeb 1742774f206SBjoern A. Zeeb if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) 1752774f206SBjoern A. Zeeb fw = &rtwdev->wow_fw; 1762774f206SBjoern A. Zeeb else 1772774f206SBjoern A. Zeeb fw = &rtwdev->fw; 1782774f206SBjoern A. Zeeb 1792774f206SBjoern A. Zeeb if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H)) 1802774f206SBjoern A. Zeeb reinit_completion(&rtwdev->lps_leave_check); 1812774f206SBjoern A. Zeeb } 1822774f206SBjoern A. Zeeb 1832774f206SBjoern A. Zeeb static void rtw_leave_lps_core(struct rtw_dev *rtwdev) 1842774f206SBjoern A. Zeeb { 1852774f206SBjoern A. Zeeb struct rtw_lps_conf *conf = &rtwdev->lps_conf; 1862774f206SBjoern A. Zeeb 1872774f206SBjoern A. Zeeb conf->state = RTW_ALL_ON; 1882774f206SBjoern A. Zeeb conf->awake_interval = 1; 1892774f206SBjoern A. Zeeb conf->rlbm = 0; 1902774f206SBjoern A. Zeeb conf->smart_ps = 0; 1912774f206SBjoern A. Zeeb 1922774f206SBjoern A. Zeeb rtw_hci_link_ps(rtwdev, false); 1932774f206SBjoern A. Zeeb rtw_fw_leave_lps_check_prepare(rtwdev); 1942774f206SBjoern A. Zeeb rtw_fw_set_pwr_mode(rtwdev); 1952774f206SBjoern A. Zeeb rtw_fw_leave_lps_check(rtwdev); 1962774f206SBjoern A. Zeeb 1972774f206SBjoern A. Zeeb clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags); 1982774f206SBjoern A. Zeeb 1992774f206SBjoern A. Zeeb rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE); 2002774f206SBjoern A. Zeeb } 2012774f206SBjoern A. Zeeb 2022774f206SBjoern A. Zeeb enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev) 2032774f206SBjoern A. Zeeb { 2042774f206SBjoern A. Zeeb if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) 2052774f206SBjoern A. Zeeb return rtwdev->lps_conf.wow_deep_mode; 2062774f206SBjoern A. Zeeb else 2072774f206SBjoern A. Zeeb return rtwdev->lps_conf.deep_mode; 2082774f206SBjoern A. Zeeb } 2092774f206SBjoern A. Zeeb 2102774f206SBjoern A. Zeeb static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev) 2112774f206SBjoern A. Zeeb { 2122774f206SBjoern A. Zeeb if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_NONE) 2132774f206SBjoern A. Zeeb return; 2142774f206SBjoern A. Zeeb 2152774f206SBjoern A. Zeeb if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) { 2162774f206SBjoern A. Zeeb rtw_dbg(rtwdev, RTW_DBG_PS, 2172774f206SBjoern A. Zeeb "Should enter LPS before entering deep PS\n"); 2182774f206SBjoern A. Zeeb return; 2192774f206SBjoern A. Zeeb } 2202774f206SBjoern A. Zeeb 2212774f206SBjoern A. Zeeb if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG) 2222774f206SBjoern A. Zeeb rtw_fw_set_pg_info(rtwdev); 2232774f206SBjoern A. Zeeb 2242774f206SBjoern A. Zeeb rtw_hci_deep_ps(rtwdev, true); 2252774f206SBjoern A. Zeeb } 2262774f206SBjoern A. Zeeb 2272774f206SBjoern A. Zeeb static void rtw_enter_lps_core(struct rtw_dev *rtwdev) 2282774f206SBjoern A. Zeeb { 2292774f206SBjoern A. Zeeb struct rtw_lps_conf *conf = &rtwdev->lps_conf; 2302774f206SBjoern A. Zeeb 2312774f206SBjoern A. Zeeb conf->state = RTW_RF_OFF; 2322774f206SBjoern A. Zeeb conf->awake_interval = 1; 2332774f206SBjoern A. Zeeb conf->rlbm = 1; 2342774f206SBjoern A. Zeeb conf->smart_ps = 2; 2352774f206SBjoern A. Zeeb 2362774f206SBjoern A. Zeeb rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE); 2372774f206SBjoern A. Zeeb 2382774f206SBjoern A. Zeeb rtw_fw_set_pwr_mode(rtwdev); 2392774f206SBjoern A. Zeeb rtw_hci_link_ps(rtwdev, true); 2402774f206SBjoern A. Zeeb 2412774f206SBjoern A. Zeeb set_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags); 2422774f206SBjoern A. Zeeb } 2432774f206SBjoern A. Zeeb 2442774f206SBjoern A. Zeeb static void __rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id) 2452774f206SBjoern A. Zeeb { 2462774f206SBjoern A. Zeeb struct rtw_lps_conf *conf = &rtwdev->lps_conf; 2472774f206SBjoern A. Zeeb 2482774f206SBjoern A. Zeeb if (test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) 2492774f206SBjoern A. Zeeb return; 2502774f206SBjoern A. Zeeb 2512774f206SBjoern A. Zeeb conf->mode = RTW_MODE_LPS; 2522774f206SBjoern A. Zeeb conf->port_id = port_id; 2532774f206SBjoern A. Zeeb 2542774f206SBjoern A. Zeeb rtw_enter_lps_core(rtwdev); 2552774f206SBjoern A. Zeeb } 2562774f206SBjoern A. Zeeb 2572774f206SBjoern A. Zeeb static void __rtw_leave_lps(struct rtw_dev *rtwdev) 2582774f206SBjoern A. Zeeb { 2592774f206SBjoern A. Zeeb struct rtw_lps_conf *conf = &rtwdev->lps_conf; 2602774f206SBjoern A. Zeeb 2612774f206SBjoern A. Zeeb if (test_and_clear_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) { 2622774f206SBjoern A. Zeeb rtw_dbg(rtwdev, RTW_DBG_PS, 2632774f206SBjoern A. Zeeb "Should leave deep PS before leaving LPS\n"); 2642774f206SBjoern A. Zeeb __rtw_leave_lps_deep(rtwdev); 2652774f206SBjoern A. Zeeb } 2662774f206SBjoern A. Zeeb 2672774f206SBjoern A. Zeeb if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) 2682774f206SBjoern A. Zeeb return; 2692774f206SBjoern A. Zeeb 2702774f206SBjoern A. Zeeb conf->mode = RTW_MODE_ACTIVE; 2712774f206SBjoern A. Zeeb 2722774f206SBjoern A. Zeeb rtw_leave_lps_core(rtwdev); 2732774f206SBjoern A. Zeeb } 2742774f206SBjoern A. Zeeb 2752774f206SBjoern A. Zeeb void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id) 2762774f206SBjoern A. Zeeb { 2772774f206SBjoern A. Zeeb lockdep_assert_held(&rtwdev->mutex); 2782774f206SBjoern A. Zeeb 2792774f206SBjoern A. Zeeb if (rtwdev->coex.stat.wl_force_lps_ctrl) 2802774f206SBjoern A. Zeeb return; 2812774f206SBjoern A. Zeeb 2822774f206SBjoern A. Zeeb __rtw_enter_lps(rtwdev, port_id); 2832774f206SBjoern A. Zeeb __rtw_enter_lps_deep(rtwdev); 2842774f206SBjoern A. Zeeb } 2852774f206SBjoern A. Zeeb 2862774f206SBjoern A. Zeeb void rtw_leave_lps(struct rtw_dev *rtwdev) 2872774f206SBjoern A. Zeeb { 2882774f206SBjoern A. Zeeb lockdep_assert_held(&rtwdev->mutex); 2892774f206SBjoern A. Zeeb 2902774f206SBjoern A. Zeeb __rtw_leave_lps_deep(rtwdev); 2912774f206SBjoern A. Zeeb __rtw_leave_lps(rtwdev); 2922774f206SBjoern A. Zeeb } 2932774f206SBjoern A. Zeeb 2942774f206SBjoern A. Zeeb void rtw_leave_lps_deep(struct rtw_dev *rtwdev) 2952774f206SBjoern A. Zeeb { 2962774f206SBjoern A. Zeeb lockdep_assert_held(&rtwdev->mutex); 2972774f206SBjoern A. Zeeb 2982774f206SBjoern A. Zeeb __rtw_leave_lps_deep(rtwdev); 2992774f206SBjoern A. Zeeb } 300*90aac0d8SBjoern A. Zeeb 301*90aac0d8SBjoern A. Zeeb struct rtw_vif_recalc_lps_iter_data { 302*90aac0d8SBjoern A. Zeeb struct rtw_dev *rtwdev; 303*90aac0d8SBjoern A. Zeeb struct ieee80211_vif *found_vif; 304*90aac0d8SBjoern A. Zeeb int count; 305*90aac0d8SBjoern A. Zeeb }; 306*90aac0d8SBjoern A. Zeeb 307*90aac0d8SBjoern A. Zeeb static void __rtw_vif_recalc_lps(struct rtw_vif_recalc_lps_iter_data *data, 308*90aac0d8SBjoern A. Zeeb struct ieee80211_vif *vif) 309*90aac0d8SBjoern A. Zeeb { 310*90aac0d8SBjoern A. Zeeb if (data->count < 0) 311*90aac0d8SBjoern A. Zeeb return; 312*90aac0d8SBjoern A. Zeeb 313*90aac0d8SBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_STATION) { 314*90aac0d8SBjoern A. Zeeb data->count = -1; 315*90aac0d8SBjoern A. Zeeb return; 316*90aac0d8SBjoern A. Zeeb } 317*90aac0d8SBjoern A. Zeeb 318*90aac0d8SBjoern A. Zeeb data->count++; 319*90aac0d8SBjoern A. Zeeb data->found_vif = vif; 320*90aac0d8SBjoern A. Zeeb } 321*90aac0d8SBjoern A. Zeeb 322*90aac0d8SBjoern A. Zeeb static void rtw_vif_recalc_lps_iter(void *data, struct ieee80211_vif *vif) 323*90aac0d8SBjoern A. Zeeb { 324*90aac0d8SBjoern A. Zeeb __rtw_vif_recalc_lps(data, vif); 325*90aac0d8SBjoern A. Zeeb } 326*90aac0d8SBjoern A. Zeeb 327*90aac0d8SBjoern A. Zeeb void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif) 328*90aac0d8SBjoern A. Zeeb { 329*90aac0d8SBjoern A. Zeeb struct rtw_vif_recalc_lps_iter_data data = { .rtwdev = rtwdev }; 330*90aac0d8SBjoern A. Zeeb 331*90aac0d8SBjoern A. Zeeb if (new_vif) 332*90aac0d8SBjoern A. Zeeb __rtw_vif_recalc_lps(&data, new_vif); 333*90aac0d8SBjoern A. Zeeb rtw_iterate_vifs(rtwdev, rtw_vif_recalc_lps_iter, &data); 334*90aac0d8SBjoern A. Zeeb 335*90aac0d8SBjoern A. Zeeb if (data.count == 1 && data.found_vif->cfg.ps) { 336*90aac0d8SBjoern A. Zeeb rtwdev->ps_enabled = true; 337*90aac0d8SBjoern A. Zeeb } else { 338*90aac0d8SBjoern A. Zeeb rtwdev->ps_enabled = false; 339*90aac0d8SBjoern A. Zeeb rtw_leave_lps(rtwdev); 340*90aac0d8SBjoern A. Zeeb } 341*90aac0d8SBjoern A. Zeeb } 342