0001
0002
0003
0004
0005 #include "coex.h"
0006 #include "core.h"
0007 #include "debug.h"
0008 #include "fw.h"
0009 #include "mac.h"
0010 #include "ps.h"
0011 #include "reg.h"
0012 #include "util.h"
0013
0014 static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid)
0015 {
0016 u32 pwr_en_bit = 0xE;
0017 u32 chk_msk = pwr_en_bit << (4 * macid);
0018 u32 polling;
0019 int ret;
0020
0021 ret = read_poll_timeout_atomic(rtw89_read32_mask, polling, !polling,
0022 1000, 50000, false, rtwdev,
0023 R_AX_PPWRBIT_SETTING, chk_msk);
0024 if (ret) {
0025 rtw89_info(rtwdev, "rtw89: failed to leave lps state\n");
0026 return -EBUSY;
0027 }
0028
0029 return 0;
0030 }
0031
0032 static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
0033 bool enter)
0034 {
0035 ieee80211_stop_queues(rtwdev->hw);
0036 rtwdev->hci.paused = true;
0037 flush_work(&rtwdev->txq_work);
0038 ieee80211_wake_queues(rtwdev->hw);
0039
0040 rtw89_hci_pause(rtwdev, true);
0041 rtw89_mac_power_mode_change(rtwdev, enter);
0042 rtw89_hci_switch_mode(rtwdev, enter);
0043 rtw89_hci_pause(rtwdev, false);
0044
0045 rtwdev->hci.paused = false;
0046
0047 if (!enter) {
0048 local_bh_disable();
0049 napi_schedule(&rtwdev->napi);
0050 local_bh_enable();
0051 }
0052 }
0053
0054 static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
0055 {
0056 if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode))
0057 rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
0058 else
0059 rtw89_mac_power_mode_change(rtwdev, enter);
0060 }
0061
0062 static void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev)
0063 {
0064 if (!rtwdev->ps_mode)
0065 return;
0066
0067 if (test_and_set_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags))
0068 return;
0069
0070 rtw89_ps_power_mode_change(rtwdev, true);
0071 }
0072
0073 void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
0074 {
0075 if (!rtwdev->ps_mode)
0076 return;
0077
0078 if (test_and_clear_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags))
0079 rtw89_ps_power_mode_change(rtwdev, false);
0080 }
0081
0082 static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, u8 mac_id)
0083 {
0084 struct rtw89_lps_parm lps_param = {
0085 .macid = mac_id,
0086 .psmode = RTW89_MAC_AX_PS_MODE_LEGACY,
0087 .lastrpwm = RTW89_LAST_RPWM_PS,
0088 };
0089
0090 rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL);
0091 rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
0092 }
0093
0094 static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, u8 mac_id)
0095 {
0096 struct rtw89_lps_parm lps_param = {
0097 .macid = mac_id,
0098 .psmode = RTW89_MAC_AX_PS_MODE_ACTIVE,
0099 .lastrpwm = RTW89_LAST_RPWM_ACTIVE,
0100 };
0101
0102 rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
0103 rtw89_fw_leave_lps_check(rtwdev, 0);
0104 rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON);
0105 }
0106
0107 void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
0108 {
0109 lockdep_assert_held(&rtwdev->mutex);
0110
0111 __rtw89_leave_ps_mode(rtwdev);
0112 }
0113
0114 void rtw89_enter_lps(struct rtw89_dev *rtwdev, u8 mac_id)
0115 {
0116 lockdep_assert_held(&rtwdev->mutex);
0117
0118 if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
0119 return;
0120
0121 __rtw89_enter_lps(rtwdev, mac_id);
0122 __rtw89_enter_ps_mode(rtwdev);
0123 }
0124
0125 static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
0126 {
0127 if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
0128 return;
0129
0130 __rtw89_leave_ps_mode(rtwdev);
0131 __rtw89_leave_lps(rtwdev, rtwvif->mac_id);
0132 }
0133
0134 void rtw89_leave_lps(struct rtw89_dev *rtwdev)
0135 {
0136 struct rtw89_vif *rtwvif;
0137
0138 lockdep_assert_held(&rtwdev->mutex);
0139
0140 if (!test_and_clear_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
0141 return;
0142
0143 rtw89_for_each_rtwvif(rtwdev, rtwvif)
0144 rtw89_leave_lps_vif(rtwdev, rtwvif);
0145 }
0146
0147 void rtw89_enter_ips(struct rtw89_dev *rtwdev)
0148 {
0149 struct rtw89_vif *rtwvif;
0150
0151 set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
0152
0153 rtw89_for_each_rtwvif(rtwdev, rtwvif)
0154 rtw89_mac_vif_deinit(rtwdev, rtwvif);
0155
0156 rtw89_core_stop(rtwdev);
0157 }
0158
0159 void rtw89_leave_ips(struct rtw89_dev *rtwdev)
0160 {
0161 struct rtw89_vif *rtwvif;
0162 int ret;
0163
0164 ret = rtw89_core_start(rtwdev);
0165 if (ret)
0166 rtw89_err(rtwdev, "failed to leave idle state\n");
0167
0168 rtw89_set_channel(rtwdev);
0169
0170 rtw89_for_each_rtwvif(rtwdev, rtwvif)
0171 rtw89_mac_vif_init(rtwdev, rtwvif);
0172
0173 clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
0174 }
0175
0176 void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl)
0177 {
0178 if (btc_ctrl)
0179 rtw89_leave_lps(rtwdev);
0180 }