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 2190aac0d8SBjoern 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 { 2990aac0d8SBjoern A. Zeeb if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags)) 3090aac0d8SBjoern 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 4090aac0d8SBjoern 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 5390aac0d8SBjoern A. Zeeb if (test_bit(RTW_FLAG_POWERON, rtwdev->flags)) 5490aac0d8SBjoern A. Zeeb return 0; 5590aac0d8SBjoern 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 6490aac0d8SBjoern 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"); 107*11c53278SBjoern A. Zeeb rtw_fw_dump_dbg_info(rtwdev); 1082774f206SBjoern A. Zeeb } 1092774f206SBjoern A. Zeeb } 1102774f206SBjoern A. Zeeb EXPORT_SYMBOL(rtw_power_mode_change); 1112774f206SBjoern A. Zeeb 1122774f206SBjoern A. Zeeb static void __rtw_leave_lps_deep(struct rtw_dev *rtwdev) 1132774f206SBjoern A. Zeeb { 1142774f206SBjoern A. Zeeb rtw_hci_deep_ps(rtwdev, false); 1152774f206SBjoern A. Zeeb } 1162774f206SBjoern A. Zeeb 1172774f206SBjoern A. Zeeb static int __rtw_fw_leave_lps_check_reg(struct rtw_dev *rtwdev) 1182774f206SBjoern A. Zeeb { 1192774f206SBjoern A. Zeeb int i; 1202774f206SBjoern A. Zeeb 1212774f206SBjoern A. Zeeb /* Driver needs to wait for firmware to leave LPS state 1222774f206SBjoern A. Zeeb * successfully. Firmware will send null packet to inform AP, 1232774f206SBjoern A. Zeeb * and see if AP sends an ACK back, then firmware will restore 1242774f206SBjoern A. Zeeb * the REG_TCR register. 1252774f206SBjoern A. Zeeb * 1262774f206SBjoern A. Zeeb * If driver does not wait for firmware, null packet with 1272774f206SBjoern A. Zeeb * PS bit could be sent due to incorrect REG_TCR setting. 1282774f206SBjoern A. Zeeb * 1292774f206SBjoern A. Zeeb * In our test, 100ms should be enough for firmware to finish 1302774f206SBjoern A. Zeeb * the flow. If REG_TCR Register is still incorrect after 100ms, 1312774f206SBjoern A. Zeeb * just modify it directly, and throw a warn message. 1322774f206SBjoern A. Zeeb */ 1332774f206SBjoern A. Zeeb for (i = 0 ; i < LEAVE_LPS_TRY_CNT; i++) { 1342774f206SBjoern A. Zeeb if (rtw_read32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN) == 0) 1352774f206SBjoern A. Zeeb return 0; 1362774f206SBjoern A. Zeeb msleep(20); 1372774f206SBjoern A. Zeeb } 1382774f206SBjoern A. Zeeb 1392774f206SBjoern A. Zeeb return -EBUSY; 1402774f206SBjoern A. Zeeb } 1412774f206SBjoern A. Zeeb 1422774f206SBjoern A. Zeeb static int __rtw_fw_leave_lps_check_c2h(struct rtw_dev *rtwdev) 1432774f206SBjoern A. Zeeb { 1442774f206SBjoern A. Zeeb if (wait_for_completion_timeout(&rtwdev->lps_leave_check, 1452774f206SBjoern A. Zeeb LEAVE_LPS_TIMEOUT)) 1462774f206SBjoern A. Zeeb return 0; 1472774f206SBjoern A. Zeeb return -EBUSY; 1482774f206SBjoern A. Zeeb } 1492774f206SBjoern A. Zeeb 1502774f206SBjoern A. Zeeb static void rtw_fw_leave_lps_check(struct rtw_dev *rtwdev) 1512774f206SBjoern A. Zeeb { 1522774f206SBjoern A. Zeeb bool ret = false; 1532774f206SBjoern A. Zeeb struct rtw_fw_state *fw; 1542774f206SBjoern A. Zeeb 1552774f206SBjoern A. Zeeb if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) 1562774f206SBjoern A. Zeeb fw = &rtwdev->wow_fw; 1572774f206SBjoern A. Zeeb else 1582774f206SBjoern A. Zeeb fw = &rtwdev->fw; 1592774f206SBjoern A. Zeeb 1602774f206SBjoern A. Zeeb if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H)) 1612774f206SBjoern A. Zeeb ret = __rtw_fw_leave_lps_check_c2h(rtwdev); 1622774f206SBjoern A. Zeeb else 1632774f206SBjoern A. Zeeb ret = __rtw_fw_leave_lps_check_reg(rtwdev); 1642774f206SBjoern A. Zeeb 1652774f206SBjoern A. Zeeb if (ret) { 1662774f206SBjoern A. Zeeb rtw_write32_clr(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN); 1672774f206SBjoern A. Zeeb rtw_warn(rtwdev, "firmware failed to leave lps state\n"); 168*11c53278SBjoern A. Zeeb rtw_fw_dump_dbg_info(rtwdev); 1692774f206SBjoern A. Zeeb } 1702774f206SBjoern A. Zeeb } 1712774f206SBjoern A. Zeeb 1722774f206SBjoern A. Zeeb static void rtw_fw_leave_lps_check_prepare(struct rtw_dev *rtwdev) 1732774f206SBjoern A. Zeeb { 1742774f206SBjoern A. Zeeb struct rtw_fw_state *fw; 1752774f206SBjoern A. Zeeb 1762774f206SBjoern A. Zeeb if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) 1772774f206SBjoern A. Zeeb fw = &rtwdev->wow_fw; 1782774f206SBjoern A. Zeeb else 1792774f206SBjoern A. Zeeb fw = &rtwdev->fw; 1802774f206SBjoern A. Zeeb 1812774f206SBjoern A. Zeeb if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H)) 1822774f206SBjoern A. Zeeb reinit_completion(&rtwdev->lps_leave_check); 1832774f206SBjoern A. Zeeb } 1842774f206SBjoern A. Zeeb 1852774f206SBjoern A. Zeeb static void rtw_leave_lps_core(struct rtw_dev *rtwdev) 1862774f206SBjoern A. Zeeb { 1872774f206SBjoern A. Zeeb struct rtw_lps_conf *conf = &rtwdev->lps_conf; 1882774f206SBjoern A. Zeeb 1892774f206SBjoern A. Zeeb conf->state = RTW_ALL_ON; 1902774f206SBjoern A. Zeeb conf->awake_interval = 1; 1912774f206SBjoern A. Zeeb conf->rlbm = 0; 1922774f206SBjoern A. Zeeb conf->smart_ps = 0; 1932774f206SBjoern A. Zeeb 1942774f206SBjoern A. Zeeb rtw_hci_link_ps(rtwdev, false); 1952774f206SBjoern A. Zeeb rtw_fw_leave_lps_check_prepare(rtwdev); 1962774f206SBjoern A. Zeeb rtw_fw_set_pwr_mode(rtwdev); 1972774f206SBjoern A. Zeeb rtw_fw_leave_lps_check(rtwdev); 1982774f206SBjoern A. Zeeb 1992774f206SBjoern A. Zeeb clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags); 2002774f206SBjoern A. Zeeb 2012774f206SBjoern A. Zeeb rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE); 2022774f206SBjoern A. Zeeb } 2032774f206SBjoern A. Zeeb 2042774f206SBjoern A. Zeeb enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev) 2052774f206SBjoern A. Zeeb { 2062774f206SBjoern A. Zeeb if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) 2072774f206SBjoern A. Zeeb return rtwdev->lps_conf.wow_deep_mode; 2082774f206SBjoern A. Zeeb else 2092774f206SBjoern A. Zeeb return rtwdev->lps_conf.deep_mode; 2102774f206SBjoern A. Zeeb } 2112774f206SBjoern A. Zeeb 2122774f206SBjoern A. Zeeb static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev) 2132774f206SBjoern A. Zeeb { 2142774f206SBjoern A. Zeeb if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_NONE) 2152774f206SBjoern A. Zeeb return; 2162774f206SBjoern A. Zeeb 2172774f206SBjoern A. Zeeb if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) { 2182774f206SBjoern A. Zeeb rtw_dbg(rtwdev, RTW_DBG_PS, 2192774f206SBjoern A. Zeeb "Should enter LPS before entering deep PS\n"); 2202774f206SBjoern A. Zeeb return; 2212774f206SBjoern A. Zeeb } 2222774f206SBjoern A. Zeeb 2232774f206SBjoern A. Zeeb if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG) 2242774f206SBjoern A. Zeeb rtw_fw_set_pg_info(rtwdev); 2252774f206SBjoern A. Zeeb 2262774f206SBjoern A. Zeeb rtw_hci_deep_ps(rtwdev, true); 2272774f206SBjoern A. Zeeb } 2282774f206SBjoern A. Zeeb 2292774f206SBjoern A. Zeeb static void rtw_enter_lps_core(struct rtw_dev *rtwdev) 2302774f206SBjoern A. Zeeb { 2312774f206SBjoern A. Zeeb struct rtw_lps_conf *conf = &rtwdev->lps_conf; 2322774f206SBjoern A. Zeeb 2332774f206SBjoern A. Zeeb conf->state = RTW_RF_OFF; 2342774f206SBjoern A. Zeeb conf->awake_interval = 1; 2352774f206SBjoern A. Zeeb conf->rlbm = 1; 2362774f206SBjoern A. Zeeb conf->smart_ps = 2; 2372774f206SBjoern A. Zeeb 2382774f206SBjoern A. Zeeb rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE); 2392774f206SBjoern A. Zeeb 2402774f206SBjoern A. Zeeb rtw_fw_set_pwr_mode(rtwdev); 2412774f206SBjoern A. Zeeb rtw_hci_link_ps(rtwdev, true); 2422774f206SBjoern A. Zeeb 2432774f206SBjoern A. Zeeb set_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags); 2442774f206SBjoern A. Zeeb } 2452774f206SBjoern A. Zeeb 2462774f206SBjoern A. Zeeb static void __rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id) 2472774f206SBjoern A. Zeeb { 2482774f206SBjoern A. Zeeb struct rtw_lps_conf *conf = &rtwdev->lps_conf; 2492774f206SBjoern A. Zeeb 2502774f206SBjoern A. Zeeb if (test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) 2512774f206SBjoern A. Zeeb return; 2522774f206SBjoern A. Zeeb 2532774f206SBjoern A. Zeeb conf->mode = RTW_MODE_LPS; 2542774f206SBjoern A. Zeeb conf->port_id = port_id; 2552774f206SBjoern A. Zeeb 2562774f206SBjoern A. Zeeb rtw_enter_lps_core(rtwdev); 2572774f206SBjoern A. Zeeb } 2582774f206SBjoern A. Zeeb 2592774f206SBjoern A. Zeeb static void __rtw_leave_lps(struct rtw_dev *rtwdev) 2602774f206SBjoern A. Zeeb { 2612774f206SBjoern A. Zeeb struct rtw_lps_conf *conf = &rtwdev->lps_conf; 2622774f206SBjoern A. Zeeb 2632774f206SBjoern A. Zeeb if (test_and_clear_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) { 2642774f206SBjoern A. Zeeb rtw_dbg(rtwdev, RTW_DBG_PS, 2652774f206SBjoern A. Zeeb "Should leave deep PS before leaving LPS\n"); 2662774f206SBjoern A. Zeeb __rtw_leave_lps_deep(rtwdev); 2672774f206SBjoern A. Zeeb } 2682774f206SBjoern A. Zeeb 2692774f206SBjoern A. Zeeb if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) 2702774f206SBjoern A. Zeeb return; 2712774f206SBjoern A. Zeeb 2722774f206SBjoern A. Zeeb conf->mode = RTW_MODE_ACTIVE; 2732774f206SBjoern A. Zeeb 2742774f206SBjoern A. Zeeb rtw_leave_lps_core(rtwdev); 2752774f206SBjoern A. Zeeb } 2762774f206SBjoern A. Zeeb 2772774f206SBjoern A. Zeeb void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id) 2782774f206SBjoern A. Zeeb { 2792774f206SBjoern A. Zeeb lockdep_assert_held(&rtwdev->mutex); 2802774f206SBjoern A. Zeeb 2812774f206SBjoern A. Zeeb if (rtwdev->coex.stat.wl_force_lps_ctrl) 2822774f206SBjoern A. Zeeb return; 2832774f206SBjoern A. Zeeb 2842774f206SBjoern A. Zeeb __rtw_enter_lps(rtwdev, port_id); 2852774f206SBjoern A. Zeeb __rtw_enter_lps_deep(rtwdev); 2862774f206SBjoern A. Zeeb } 2872774f206SBjoern A. Zeeb 2882774f206SBjoern A. Zeeb void rtw_leave_lps(struct rtw_dev *rtwdev) 2892774f206SBjoern A. Zeeb { 2902774f206SBjoern A. Zeeb lockdep_assert_held(&rtwdev->mutex); 2912774f206SBjoern A. Zeeb 2922774f206SBjoern A. Zeeb __rtw_leave_lps_deep(rtwdev); 2932774f206SBjoern A. Zeeb __rtw_leave_lps(rtwdev); 2942774f206SBjoern A. Zeeb } 2952774f206SBjoern A. Zeeb 2962774f206SBjoern A. Zeeb void rtw_leave_lps_deep(struct rtw_dev *rtwdev) 2972774f206SBjoern A. Zeeb { 2982774f206SBjoern A. Zeeb lockdep_assert_held(&rtwdev->mutex); 2992774f206SBjoern A. Zeeb 3002774f206SBjoern A. Zeeb __rtw_leave_lps_deep(rtwdev); 3012774f206SBjoern A. Zeeb } 30290aac0d8SBjoern A. Zeeb 30390aac0d8SBjoern A. Zeeb struct rtw_vif_recalc_lps_iter_data { 30490aac0d8SBjoern A. Zeeb struct rtw_dev *rtwdev; 30590aac0d8SBjoern A. Zeeb struct ieee80211_vif *found_vif; 30690aac0d8SBjoern A. Zeeb int count; 30790aac0d8SBjoern A. Zeeb }; 30890aac0d8SBjoern A. Zeeb 30990aac0d8SBjoern A. Zeeb static void __rtw_vif_recalc_lps(struct rtw_vif_recalc_lps_iter_data *data, 31090aac0d8SBjoern A. Zeeb struct ieee80211_vif *vif) 31190aac0d8SBjoern A. Zeeb { 31290aac0d8SBjoern A. Zeeb if (data->count < 0) 31390aac0d8SBjoern A. Zeeb return; 31490aac0d8SBjoern A. Zeeb 31590aac0d8SBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_STATION) { 31690aac0d8SBjoern A. Zeeb data->count = -1; 31790aac0d8SBjoern A. Zeeb return; 31890aac0d8SBjoern A. Zeeb } 31990aac0d8SBjoern A. Zeeb 32090aac0d8SBjoern A. Zeeb data->count++; 32190aac0d8SBjoern A. Zeeb data->found_vif = vif; 32290aac0d8SBjoern A. Zeeb } 32390aac0d8SBjoern A. Zeeb 32490aac0d8SBjoern A. Zeeb static void rtw_vif_recalc_lps_iter(void *data, struct ieee80211_vif *vif) 32590aac0d8SBjoern A. Zeeb { 32690aac0d8SBjoern A. Zeeb __rtw_vif_recalc_lps(data, vif); 32790aac0d8SBjoern A. Zeeb } 32890aac0d8SBjoern A. Zeeb 32990aac0d8SBjoern A. Zeeb void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif) 33090aac0d8SBjoern A. Zeeb { 33190aac0d8SBjoern A. Zeeb struct rtw_vif_recalc_lps_iter_data data = { .rtwdev = rtwdev }; 33290aac0d8SBjoern A. Zeeb 33390aac0d8SBjoern A. Zeeb if (new_vif) 33490aac0d8SBjoern A. Zeeb __rtw_vif_recalc_lps(&data, new_vif); 33590aac0d8SBjoern A. Zeeb rtw_iterate_vifs(rtwdev, rtw_vif_recalc_lps_iter, &data); 33690aac0d8SBjoern A. Zeeb 33790aac0d8SBjoern A. Zeeb if (data.count == 1 && data.found_vif->cfg.ps) { 33890aac0d8SBjoern A. Zeeb rtwdev->ps_enabled = true; 33990aac0d8SBjoern A. Zeeb } else { 34090aac0d8SBjoern A. Zeeb rtwdev->ps_enabled = false; 34190aac0d8SBjoern A. Zeeb rtw_leave_lps(rtwdev); 34290aac0d8SBjoern A. Zeeb } 34390aac0d8SBjoern A. Zeeb } 344