1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2018-2019 Realtek Corporation 3 */ 4 5 #include "main.h" 6 #include "reg.h" 7 #include "fw.h" 8 #include "ps.h" 9 #include "mac.h" 10 #include "coex.h" 11 #include "debug.h" 12 13 static int rtw_ips_pwr_up(struct rtw_dev *rtwdev) 14 { 15 int ret; 16 17 ret = rtw_core_start(rtwdev); 18 if (ret) 19 rtw_err(rtwdev, "leave idle state failed\n"); 20 21 rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); 22 rtw_set_channel(rtwdev); 23 24 return ret; 25 } 26 27 int rtw_enter_ips(struct rtw_dev *rtwdev) 28 { 29 if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags)) 30 return 0; 31 32 rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER); 33 34 rtw_core_stop(rtwdev); 35 rtw_hci_link_ps(rtwdev, true); 36 37 return 0; 38 } 39 40 static void rtw_restore_port_cfg_iter(void *data, struct ieee80211_vif *vif) 41 { 42 struct rtw_dev *rtwdev = data; 43 struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; 44 u32 config = ~0; 45 46 rtw_vif_port_config(rtwdev, rtwvif, config); 47 } 48 49 int rtw_leave_ips(struct rtw_dev *rtwdev) 50 { 51 int ret; 52 53 if (test_bit(RTW_FLAG_POWERON, rtwdev->flags)) 54 return 0; 55 56 rtw_hci_link_ps(rtwdev, false); 57 58 ret = rtw_ips_pwr_up(rtwdev); 59 if (ret) { 60 rtw_err(rtwdev, "failed to leave ips state\n"); 61 return ret; 62 } 63 64 rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev); 65 66 return 0; 67 } 68 69 void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter) 70 { 71 u8 request, confirm, polling; 72 int ret; 73 74 request = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr); 75 confirm = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr); 76 77 /* toggle to request power mode, others remain 0 */ 78 request ^= request | BIT_RPWM_TOGGLE; 79 if (enter) { 80 request |= POWER_MODE_LCLK; 81 if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG) 82 request |= POWER_MODE_PG; 83 } 84 /* Each request require an ack from firmware */ 85 request |= POWER_MODE_ACK; 86 87 if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE)) 88 request |= POWER_TX_WAKE; 89 90 rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, request); 91 92 /* Check firmware get the power requset and ack via cpwm register */ 93 ret = read_poll_timeout_atomic(rtw_read8, polling, 94 (polling ^ confirm) & BIT_RPWM_TOGGLE, 95 100, 15000, true, rtwdev, 96 rtwdev->hci.cpwm_addr); 97 if (ret) { 98 /* Hit here means that driver failed to get an ack from firmware. 99 * The reason could be that hardware is locked at Deep sleep, 100 * so most of the hardware circuits are not working, even 101 * register read/write; or firmware is locked in some state and 102 * cannot get the request. It should be treated as fatal error 103 * and requires an entire analysis about the firmware/hardware. 104 */ 105 WARN(1, "firmware failed to ack driver for %s Deep Power mode\n", 106 enter ? "entering" : "leaving"); 107 } 108 } 109 EXPORT_SYMBOL(rtw_power_mode_change); 110 111 static void __rtw_leave_lps_deep(struct rtw_dev *rtwdev) 112 { 113 rtw_hci_deep_ps(rtwdev, false); 114 } 115 116 static int __rtw_fw_leave_lps_check_reg(struct rtw_dev *rtwdev) 117 { 118 int i; 119 120 /* Driver needs to wait for firmware to leave LPS state 121 * successfully. Firmware will send null packet to inform AP, 122 * and see if AP sends an ACK back, then firmware will restore 123 * the REG_TCR register. 124 * 125 * If driver does not wait for firmware, null packet with 126 * PS bit could be sent due to incorrect REG_TCR setting. 127 * 128 * In our test, 100ms should be enough for firmware to finish 129 * the flow. If REG_TCR Register is still incorrect after 100ms, 130 * just modify it directly, and throw a warn message. 131 */ 132 for (i = 0 ; i < LEAVE_LPS_TRY_CNT; i++) { 133 if (rtw_read32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN) == 0) 134 return 0; 135 msleep(20); 136 } 137 138 return -EBUSY; 139 } 140 141 static int __rtw_fw_leave_lps_check_c2h(struct rtw_dev *rtwdev) 142 { 143 if (wait_for_completion_timeout(&rtwdev->lps_leave_check, 144 LEAVE_LPS_TIMEOUT)) 145 return 0; 146 return -EBUSY; 147 } 148 149 static void rtw_fw_leave_lps_check(struct rtw_dev *rtwdev) 150 { 151 bool ret = false; 152 struct rtw_fw_state *fw; 153 154 if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) 155 fw = &rtwdev->wow_fw; 156 else 157 fw = &rtwdev->fw; 158 159 if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H)) 160 ret = __rtw_fw_leave_lps_check_c2h(rtwdev); 161 else 162 ret = __rtw_fw_leave_lps_check_reg(rtwdev); 163 164 if (ret) { 165 rtw_write32_clr(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN); 166 rtw_warn(rtwdev, "firmware failed to leave lps state\n"); 167 } 168 } 169 170 static void rtw_fw_leave_lps_check_prepare(struct rtw_dev *rtwdev) 171 { 172 struct rtw_fw_state *fw; 173 174 if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) 175 fw = &rtwdev->wow_fw; 176 else 177 fw = &rtwdev->fw; 178 179 if (rtw_fw_feature_check(fw, FW_FEATURE_LPS_C2H)) 180 reinit_completion(&rtwdev->lps_leave_check); 181 } 182 183 static void rtw_leave_lps_core(struct rtw_dev *rtwdev) 184 { 185 struct rtw_lps_conf *conf = &rtwdev->lps_conf; 186 187 conf->state = RTW_ALL_ON; 188 conf->awake_interval = 1; 189 conf->rlbm = 0; 190 conf->smart_ps = 0; 191 192 rtw_hci_link_ps(rtwdev, false); 193 rtw_fw_leave_lps_check_prepare(rtwdev); 194 rtw_fw_set_pwr_mode(rtwdev); 195 rtw_fw_leave_lps_check(rtwdev); 196 197 clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags); 198 199 rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE); 200 } 201 202 enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev) 203 { 204 if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) 205 return rtwdev->lps_conf.wow_deep_mode; 206 else 207 return rtwdev->lps_conf.deep_mode; 208 } 209 210 static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev) 211 { 212 if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_NONE) 213 return; 214 215 if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) { 216 rtw_dbg(rtwdev, RTW_DBG_PS, 217 "Should enter LPS before entering deep PS\n"); 218 return; 219 } 220 221 if (rtw_get_lps_deep_mode(rtwdev) == LPS_DEEP_MODE_PG) 222 rtw_fw_set_pg_info(rtwdev); 223 224 rtw_hci_deep_ps(rtwdev, true); 225 } 226 227 static void rtw_enter_lps_core(struct rtw_dev *rtwdev) 228 { 229 struct rtw_lps_conf *conf = &rtwdev->lps_conf; 230 231 conf->state = RTW_RF_OFF; 232 conf->awake_interval = 1; 233 conf->rlbm = 1; 234 conf->smart_ps = 2; 235 236 rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE); 237 238 rtw_fw_set_pwr_mode(rtwdev); 239 rtw_hci_link_ps(rtwdev, true); 240 241 set_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags); 242 } 243 244 static void __rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id) 245 { 246 struct rtw_lps_conf *conf = &rtwdev->lps_conf; 247 248 if (test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) 249 return; 250 251 conf->mode = RTW_MODE_LPS; 252 conf->port_id = port_id; 253 254 rtw_enter_lps_core(rtwdev); 255 } 256 257 static void __rtw_leave_lps(struct rtw_dev *rtwdev) 258 { 259 struct rtw_lps_conf *conf = &rtwdev->lps_conf; 260 261 if (test_and_clear_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) { 262 rtw_dbg(rtwdev, RTW_DBG_PS, 263 "Should leave deep PS before leaving LPS\n"); 264 __rtw_leave_lps_deep(rtwdev); 265 } 266 267 if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) 268 return; 269 270 conf->mode = RTW_MODE_ACTIVE; 271 272 rtw_leave_lps_core(rtwdev); 273 } 274 275 void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id) 276 { 277 lockdep_assert_held(&rtwdev->mutex); 278 279 if (rtwdev->coex.stat.wl_force_lps_ctrl) 280 return; 281 282 __rtw_enter_lps(rtwdev, port_id); 283 __rtw_enter_lps_deep(rtwdev); 284 } 285 286 void rtw_leave_lps(struct rtw_dev *rtwdev) 287 { 288 lockdep_assert_held(&rtwdev->mutex); 289 290 __rtw_leave_lps_deep(rtwdev); 291 __rtw_leave_lps(rtwdev); 292 } 293 294 void rtw_leave_lps_deep(struct rtw_dev *rtwdev) 295 { 296 lockdep_assert_held(&rtwdev->mutex); 297 298 __rtw_leave_lps_deep(rtwdev); 299 } 300 301 struct rtw_vif_recalc_lps_iter_data { 302 struct rtw_dev *rtwdev; 303 struct ieee80211_vif *found_vif; 304 int count; 305 }; 306 307 static void __rtw_vif_recalc_lps(struct rtw_vif_recalc_lps_iter_data *data, 308 struct ieee80211_vif *vif) 309 { 310 if (data->count < 0) 311 return; 312 313 if (vif->type != NL80211_IFTYPE_STATION) { 314 data->count = -1; 315 return; 316 } 317 318 data->count++; 319 data->found_vif = vif; 320 } 321 322 static void rtw_vif_recalc_lps_iter(void *data, struct ieee80211_vif *vif) 323 { 324 __rtw_vif_recalc_lps(data, vif); 325 } 326 327 void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif) 328 { 329 struct rtw_vif_recalc_lps_iter_data data = { .rtwdev = rtwdev }; 330 331 if (new_vif) 332 __rtw_vif_recalc_lps(&data, new_vif); 333 rtw_iterate_vifs(rtwdev, rtw_vif_recalc_lps_iter, &data); 334 335 if (data.count == 1 && data.found_vif->cfg.ps) { 336 rtwdev->ps_enabled = true; 337 } else { 338 rtwdev->ps_enabled = false; 339 rtw_leave_lps(rtwdev); 340 } 341 } 342