pm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. // SPDX-License-Identifier: ISC
  2. /*
  3. * Copyright (c) 2014,2017 Qualcomm Atheros, Inc.
  4. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  5. */
  6. #include "wil6210.h"
  7. #include <linux/jiffies.h>
  8. #include <linux/pm_runtime.h>
  9. #define WIL6210_AUTOSUSPEND_DELAY_MS (1000)
  10. static void wil_pm_wake_connected_net_queues(struct wil6210_priv *wil)
  11. {
  12. int i;
  13. mutex_lock(&wil->vif_mutex);
  14. for (i = 0; i < GET_MAX_VIFS(wil); i++) {
  15. struct wil6210_vif *vif = wil->vifs[i];
  16. if (vif && test_bit(wil_vif_fwconnected, vif->status))
  17. wil_update_net_queues_bh(wil, vif, NULL, false);
  18. }
  19. mutex_unlock(&wil->vif_mutex);
  20. }
  21. static void wil_pm_stop_all_net_queues(struct wil6210_priv *wil)
  22. {
  23. int i;
  24. mutex_lock(&wil->vif_mutex);
  25. for (i = 0; i < GET_MAX_VIFS(wil); i++) {
  26. struct wil6210_vif *vif = wil->vifs[i];
  27. if (vif)
  28. wil_update_net_queues_bh(wil, vif, NULL, true);
  29. }
  30. mutex_unlock(&wil->vif_mutex);
  31. }
  32. static bool
  33. wil_can_suspend_vif(struct wil6210_priv *wil, struct wil6210_vif *vif,
  34. bool is_runtime)
  35. {
  36. struct wireless_dev *wdev = vif_to_wdev(vif);
  37. switch (wdev->iftype) {
  38. case NL80211_IFTYPE_MONITOR:
  39. wil_dbg_pm(wil, "Sniffer\n");
  40. return false;
  41. /* for STA-like interface, don't runtime suspend */
  42. case NL80211_IFTYPE_STATION:
  43. case NL80211_IFTYPE_P2P_CLIENT:
  44. if (test_bit(wil_vif_fwconnecting, vif->status)) {
  45. wil_dbg_pm(wil, "Delay suspend when connecting\n");
  46. return false;
  47. }
  48. if (is_runtime) {
  49. wil_dbg_pm(wil, "STA-like interface\n");
  50. return false;
  51. }
  52. break;
  53. /* AP-like interface - can't suspend */
  54. default:
  55. wil_dbg_pm(wil, "AP-like interface\n");
  56. return false;
  57. }
  58. return true;
  59. }
  60. int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
  61. {
  62. int rc = 0, i;
  63. bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY,
  64. wil->fw_capabilities);
  65. bool active_ifaces;
  66. wil_dbg_pm(wil, "can_suspend: %s\n", is_runtime ? "runtime" : "system");
  67. if (wmi_only || debug_fw) {
  68. wil_dbg_pm(wil, "Deny any suspend - %s mode\n",
  69. wmi_only ? "wmi_only" : "debug_fw");
  70. rc = -EBUSY;
  71. goto out;
  72. }
  73. if (is_runtime && !wil->platform_ops.suspend) {
  74. rc = -EBUSY;
  75. goto out;
  76. }
  77. mutex_lock(&wil->vif_mutex);
  78. active_ifaces = wil_has_active_ifaces(wil, true, false);
  79. mutex_unlock(&wil->vif_mutex);
  80. if (!active_ifaces) {
  81. /* can always sleep when down */
  82. wil_dbg_pm(wil, "Interface is down\n");
  83. goto out;
  84. }
  85. if (test_bit(wil_status_resetting, wil->status)) {
  86. wil_dbg_pm(wil, "Delay suspend when resetting\n");
  87. rc = -EBUSY;
  88. goto out;
  89. }
  90. if (wil->recovery_state != fw_recovery_idle) {
  91. wil_dbg_pm(wil, "Delay suspend during recovery\n");
  92. rc = -EBUSY;
  93. goto out;
  94. }
  95. /* interface is running */
  96. mutex_lock(&wil->vif_mutex);
  97. for (i = 0; i < GET_MAX_VIFS(wil); i++) {
  98. struct wil6210_vif *vif = wil->vifs[i];
  99. if (!vif)
  100. continue;
  101. if (!wil_can_suspend_vif(wil, vif, is_runtime)) {
  102. rc = -EBUSY;
  103. mutex_unlock(&wil->vif_mutex);
  104. goto out;
  105. }
  106. }
  107. mutex_unlock(&wil->vif_mutex);
  108. out:
  109. wil_dbg_pm(wil, "can_suspend: %s => %s (%d)\n",
  110. is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc);
  111. if (rc)
  112. wil->suspend_stats.rejected_by_host++;
  113. return rc;
  114. }
  115. static int wil_resume_keep_radio_on(struct wil6210_priv *wil)
  116. {
  117. int rc = 0;
  118. /* wil_status_resuming will be cleared when getting
  119. * WMI_TRAFFIC_RESUME_EVENTID
  120. */
  121. set_bit(wil_status_resuming, wil->status);
  122. clear_bit(wil_status_suspended, wil->status);
  123. wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
  124. wil_unmask_irq(wil);
  125. wil6210_bus_request(wil, wil->bus_request_kbps_pre_suspend);
  126. /* Send WMI resume request to the device */
  127. rc = wmi_resume(wil);
  128. if (rc) {
  129. wil_err(wil, "device failed to resume (%d)\n", rc);
  130. if (no_fw_recovery)
  131. goto out;
  132. rc = wil_down(wil);
  133. if (rc) {
  134. wil_err(wil, "wil_down failed (%d)\n", rc);
  135. goto out;
  136. }
  137. rc = wil_up(wil);
  138. if (rc) {
  139. wil_err(wil, "wil_up failed (%d)\n", rc);
  140. goto out;
  141. }
  142. }
  143. /* Wake all queues */
  144. wil_pm_wake_connected_net_queues(wil);
  145. out:
  146. if (rc)
  147. set_bit(wil_status_suspended, wil->status);
  148. return rc;
  149. }
  150. static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
  151. {
  152. int rc = 0;
  153. unsigned long data_comp_to;
  154. wil_dbg_pm(wil, "suspend keep radio on\n");
  155. /* Prevent handling of new tx and wmi commands */
  156. rc = down_write_trylock(&wil->mem_lock);
  157. if (!rc) {
  158. wil_err(wil,
  159. "device is busy. down_write_trylock failed, returned (0x%x)\n",
  160. rc);
  161. wil->suspend_stats.rejected_by_host++;
  162. return -EBUSY;
  163. }
  164. set_bit(wil_status_suspending, wil->status);
  165. up_write(&wil->mem_lock);
  166. wil_pm_stop_all_net_queues(wil);
  167. if (!wil_is_tx_idle(wil)) {
  168. wil_dbg_pm(wil, "Pending TX data, reject suspend\n");
  169. wil->suspend_stats.rejected_by_host++;
  170. goto reject_suspend;
  171. }
  172. if (!wil->txrx_ops.is_rx_idle(wil)) {
  173. wil_dbg_pm(wil, "Pending RX data, reject suspend\n");
  174. wil->suspend_stats.rejected_by_host++;
  175. goto reject_suspend;
  176. }
  177. if (!wil_is_wmi_idle(wil)) {
  178. wil_dbg_pm(wil, "Pending WMI events, reject suspend\n");
  179. wil->suspend_stats.rejected_by_host++;
  180. goto reject_suspend;
  181. }
  182. /* Send WMI suspend request to the device */
  183. rc = wmi_suspend(wil);
  184. if (rc) {
  185. wil_dbg_pm(wil, "wmi_suspend failed, reject suspend (%d)\n",
  186. rc);
  187. goto reject_suspend;
  188. }
  189. /* Wait for completion of the pending RX packets */
  190. data_comp_to = jiffies + msecs_to_jiffies(WIL_DATA_COMPLETION_TO_MS);
  191. if (test_bit(wil_status_napi_en, wil->status)) {
  192. while (!wil->txrx_ops.is_rx_idle(wil)) {
  193. if (time_after(jiffies, data_comp_to)) {
  194. if (wil->txrx_ops.is_rx_idle(wil))
  195. break;
  196. wil_err(wil,
  197. "TO waiting for idle RX, suspend failed\n");
  198. wil->suspend_stats.r_on.failed_suspends++;
  199. goto resume_after_fail;
  200. }
  201. wil_dbg_ratelimited(wil, "rx vring is not empty -> NAPI\n");
  202. napi_synchronize(&wil->napi_rx);
  203. msleep(20);
  204. }
  205. }
  206. /* In case of pending WMI events, reject the suspend
  207. * and resume the device.
  208. * This can happen if the device sent the WMI events before
  209. * approving the suspend.
  210. */
  211. if (!wil_is_wmi_idle(wil)) {
  212. wil_err(wil, "suspend failed due to pending WMI events\n");
  213. wil->suspend_stats.r_on.failed_suspends++;
  214. goto resume_after_fail;
  215. }
  216. wil_mask_irq(wil);
  217. /* Disable device reset on PERST */
  218. wil_s(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
  219. if (wil->platform_ops.suspend) {
  220. rc = wil->platform_ops.suspend(wil->platform_handle, true);
  221. if (rc) {
  222. wil_err(wil, "platform device failed to suspend (%d)\n",
  223. rc);
  224. wil->suspend_stats.r_on.failed_suspends++;
  225. wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
  226. wil_unmask_irq(wil);
  227. goto resume_after_fail;
  228. }
  229. }
  230. /* Save the current bus request to return to the same in resume */
  231. wil->bus_request_kbps_pre_suspend = wil->bus_request_kbps;
  232. wil6210_bus_request(wil, 0);
  233. set_bit(wil_status_suspended, wil->status);
  234. clear_bit(wil_status_suspending, wil->status);
  235. return rc;
  236. resume_after_fail:
  237. set_bit(wil_status_resuming, wil->status);
  238. clear_bit(wil_status_suspending, wil->status);
  239. rc = wmi_resume(wil);
  240. /* if resume succeeded, reject the suspend */
  241. if (!rc) {
  242. rc = -EBUSY;
  243. wil_pm_wake_connected_net_queues(wil);
  244. }
  245. return rc;
  246. reject_suspend:
  247. clear_bit(wil_status_suspending, wil->status);
  248. wil_pm_wake_connected_net_queues(wil);
  249. return -EBUSY;
  250. }
  251. static int wil_suspend_radio_off(struct wil6210_priv *wil)
  252. {
  253. int rc = 0;
  254. bool active_ifaces;
  255. wil_dbg_pm(wil, "suspend radio off\n");
  256. rc = down_write_trylock(&wil->mem_lock);
  257. if (!rc) {
  258. wil_err(wil,
  259. "device is busy. down_write_trylock failed, returned (0x%x)\n",
  260. rc);
  261. wil->suspend_stats.rejected_by_host++;
  262. return -EBUSY;
  263. }
  264. set_bit(wil_status_suspending, wil->status);
  265. up_write(&wil->mem_lock);
  266. /* if netif up, hardware is alive, shut it down */
  267. mutex_lock(&wil->vif_mutex);
  268. active_ifaces = wil_has_active_ifaces(wil, true, false);
  269. mutex_unlock(&wil->vif_mutex);
  270. if (active_ifaces) {
  271. rc = wil_down(wil);
  272. if (rc) {
  273. wil_err(wil, "wil_down : %d\n", rc);
  274. wil->suspend_stats.r_off.failed_suspends++;
  275. goto out;
  276. }
  277. }
  278. /* Disable PCIe IRQ to prevent sporadic IRQs when PCIe is suspending */
  279. wil_dbg_pm(wil, "Disabling PCIe IRQ before suspending\n");
  280. wil_disable_irq(wil);
  281. if (wil->platform_ops.suspend) {
  282. rc = wil->platform_ops.suspend(wil->platform_handle, false);
  283. if (rc) {
  284. wil_enable_irq(wil);
  285. wil->suspend_stats.r_off.failed_suspends++;
  286. goto out;
  287. }
  288. }
  289. set_bit(wil_status_suspended, wil->status);
  290. out:
  291. clear_bit(wil_status_suspending, wil->status);
  292. wil_dbg_pm(wil, "suspend radio off: %d\n", rc);
  293. return rc;
  294. }
  295. static int wil_resume_radio_off(struct wil6210_priv *wil)
  296. {
  297. int rc = 0;
  298. bool active_ifaces;
  299. wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
  300. wil_enable_irq(wil);
  301. /* if any netif up, bring hardware up
  302. * During open(), IFF_UP set after actual device method
  303. * invocation. This prevent recursive call to wil_up()
  304. * wil_status_suspended will be cleared in wil_reset
  305. */
  306. mutex_lock(&wil->vif_mutex);
  307. active_ifaces = wil_has_active_ifaces(wil, true, false);
  308. mutex_unlock(&wil->vif_mutex);
  309. if (active_ifaces)
  310. rc = wil_up(wil);
  311. else
  312. clear_bit(wil_status_suspended, wil->status);
  313. return rc;
  314. }
  315. int wil_suspend(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on)
  316. {
  317. int rc = 0;
  318. wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
  319. if (test_bit(wil_status_suspended, wil->status)) {
  320. wil_dbg_pm(wil, "trying to suspend while suspended\n");
  321. return 0;
  322. }
  323. if (!keep_radio_on)
  324. rc = wil_suspend_radio_off(wil);
  325. else
  326. rc = wil_suspend_keep_radio_on(wil);
  327. wil_dbg_pm(wil, "suspend: %s => %d\n",
  328. is_runtime ? "runtime" : "system", rc);
  329. return rc;
  330. }
  331. int wil_resume(struct wil6210_priv *wil, bool is_runtime, bool keep_radio_on)
  332. {
  333. int rc = 0;
  334. wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
  335. if (wil->platform_ops.resume) {
  336. rc = wil->platform_ops.resume(wil->platform_handle,
  337. keep_radio_on);
  338. if (rc) {
  339. wil_err(wil, "platform_ops.resume : %d\n", rc);
  340. goto out;
  341. }
  342. }
  343. if (keep_radio_on)
  344. rc = wil_resume_keep_radio_on(wil);
  345. else
  346. rc = wil_resume_radio_off(wil);
  347. out:
  348. wil_dbg_pm(wil, "resume: %s => %d\n", is_runtime ? "runtime" : "system",
  349. rc);
  350. return rc;
  351. }
  352. void wil_pm_runtime_allow(struct wil6210_priv *wil)
  353. {
  354. struct device *dev = wil_to_dev(wil);
  355. pm_runtime_put_noidle(dev);
  356. pm_runtime_set_autosuspend_delay(dev, WIL6210_AUTOSUSPEND_DELAY_MS);
  357. pm_runtime_use_autosuspend(dev);
  358. pm_runtime_allow(dev);
  359. }
  360. void wil_pm_runtime_forbid(struct wil6210_priv *wil)
  361. {
  362. struct device *dev = wil_to_dev(wil);
  363. pm_runtime_forbid(dev);
  364. pm_runtime_get_noresume(dev);
  365. }
  366. int wil_pm_runtime_get(struct wil6210_priv *wil)
  367. {
  368. int rc;
  369. struct device *dev = wil_to_dev(wil);
  370. rc = pm_runtime_resume_and_get(dev);
  371. if (rc < 0) {
  372. wil_err(wil, "pm_runtime_resume_and_get() failed, rc = %d\n", rc);
  373. return rc;
  374. }
  375. return 0;
  376. }
  377. void wil_pm_runtime_put(struct wil6210_priv *wil)
  378. {
  379. struct device *dev = wil_to_dev(wil);
  380. pm_runtime_mark_last_busy(dev);
  381. pm_runtime_put_autosuspend(dev);
  382. }