ps.c 7.9 KB

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