power.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. /******************************************************************************
  2. *
  3. * This file is provided under a dual BSD/GPLv2 license. When using or
  4. * redistributing this file, you may do so under either license.
  5. *
  6. * GPL LICENSE SUMMARY
  7. *
  8. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  9. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
  10. * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of version 2 of the GNU General Public License as
  14. * published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful, but
  17. * WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  24. * USA
  25. *
  26. * The full GNU General Public License is included in this distribution
  27. * in the file called COPYING.
  28. *
  29. * Contact Information:
  30. * Intel Linux Wireless <linuxwifi@intel.com>
  31. * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  32. *
  33. * BSD LICENSE
  34. *
  35. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  36. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
  37. * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
  38. * All rights reserved.
  39. *
  40. * Redistribution and use in source and binary forms, with or without
  41. * modification, are permitted provided that the following conditions
  42. * are met:
  43. *
  44. * * Redistributions of source code must retain the above copyright
  45. * notice, this list of conditions and the following disclaimer.
  46. * * Redistributions in binary form must reproduce the above copyright
  47. * notice, this list of conditions and the following disclaimer in
  48. * the documentation and/or other materials provided with the
  49. * distribution.
  50. * * Neither the name Intel Corporation nor the names of its
  51. * contributors may be used to endorse or promote products derived
  52. * from this software without specific prior written permission.
  53. *
  54. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  55. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  56. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  57. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  58. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  59. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  60. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  61. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  62. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  63. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  64. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  65. *
  66. *****************************************************************************/
  67. #include <linux/kernel.h>
  68. #include <linux/module.h>
  69. #include <linux/slab.h>
  70. #include <linux/etherdevice.h>
  71. #include <net/mac80211.h>
  72. #include "iwl-debug.h"
  73. #include "mvm.h"
  74. #include "iwl-modparams.h"
  75. #include "fw-api-power.h"
  76. #define POWER_KEEP_ALIVE_PERIOD_SEC 25
  77. static
  78. int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
  79. struct iwl_beacon_filter_cmd *cmd,
  80. u32 flags)
  81. {
  82. IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
  83. le32_to_cpu(cmd->ba_enable_beacon_abort));
  84. IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
  85. le32_to_cpu(cmd->ba_escape_timer));
  86. IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
  87. le32_to_cpu(cmd->bf_debug_flag));
  88. IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
  89. le32_to_cpu(cmd->bf_enable_beacon_filter));
  90. IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
  91. le32_to_cpu(cmd->bf_energy_delta));
  92. IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
  93. le32_to_cpu(cmd->bf_escape_timer));
  94. IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
  95. le32_to_cpu(cmd->bf_roaming_energy_delta));
  96. IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
  97. le32_to_cpu(cmd->bf_roaming_state));
  98. IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
  99. le32_to_cpu(cmd->bf_temp_threshold));
  100. IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
  101. le32_to_cpu(cmd->bf_temp_fast_filter));
  102. IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
  103. le32_to_cpu(cmd->bf_temp_slow_filter));
  104. return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags,
  105. sizeof(struct iwl_beacon_filter_cmd), cmd);
  106. }
  107. static
  108. void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
  109. struct ieee80211_vif *vif,
  110. struct iwl_beacon_filter_cmd *cmd,
  111. bool d0i3)
  112. {
  113. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  114. if (vif->bss_conf.cqm_rssi_thold && !d0i3) {
  115. cmd->bf_energy_delta =
  116. cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
  117. /* fw uses an absolute value for this */
  118. cmd->bf_roaming_state =
  119. cpu_to_le32(-vif->bss_conf.cqm_rssi_thold);
  120. }
  121. cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled);
  122. }
  123. static void iwl_mvm_power_log(struct iwl_mvm *mvm,
  124. struct iwl_mac_power_cmd *cmd)
  125. {
  126. IWL_DEBUG_POWER(mvm,
  127. "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
  128. cmd->id_and_color, iwlmvm_mod_params.power_scheme,
  129. le16_to_cpu(cmd->flags));
  130. IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
  131. le16_to_cpu(cmd->keep_alive_seconds));
  132. if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
  133. IWL_DEBUG_POWER(mvm, "Disable power management\n");
  134. return;
  135. }
  136. IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
  137. le32_to_cpu(cmd->rx_data_timeout));
  138. IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
  139. le32_to_cpu(cmd->tx_data_timeout));
  140. if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
  141. IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
  142. cmd->skip_dtim_periods);
  143. if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
  144. IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
  145. cmd->lprx_rssi_threshold);
  146. if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
  147. IWL_DEBUG_POWER(mvm, "uAPSD enabled\n");
  148. IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n",
  149. le32_to_cpu(cmd->rx_data_timeout_uapsd));
  150. IWL_DEBUG_POWER(mvm, "Tx timeout (uAPSD) = %u usec\n",
  151. le32_to_cpu(cmd->tx_data_timeout_uapsd));
  152. IWL_DEBUG_POWER(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
  153. IWL_DEBUG_POWER(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
  154. IWL_DEBUG_POWER(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
  155. }
  156. }
  157. static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
  158. struct ieee80211_vif *vif,
  159. struct iwl_mac_power_cmd *cmd)
  160. {
  161. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  162. enum ieee80211_ac_numbers ac;
  163. bool tid_found = false;
  164. for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
  165. if (!mvmvif->queue_params[ac].uapsd)
  166. continue;
  167. if (mvm->cur_ucode != IWL_UCODE_WOWLAN)
  168. cmd->flags |=
  169. cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
  170. cmd->uapsd_ac_flags |= BIT(ac);
  171. /* QNDP TID - the highest TID with no admission control */
  172. if (!tid_found && !mvmvif->queue_params[ac].acm) {
  173. tid_found = true;
  174. switch (ac) {
  175. case IEEE80211_AC_VO:
  176. cmd->qndp_tid = 6;
  177. break;
  178. case IEEE80211_AC_VI:
  179. cmd->qndp_tid = 5;
  180. break;
  181. case IEEE80211_AC_BE:
  182. cmd->qndp_tid = 0;
  183. break;
  184. case IEEE80211_AC_BK:
  185. cmd->qndp_tid = 1;
  186. break;
  187. }
  188. }
  189. }
  190. if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
  191. #ifdef CONFIG_IWLWIFI_DEBUGFS
  192. /* set advanced pm flag with no uapsd ACs to enable ps-poll */
  193. if (mvmvif->dbgfs_pm.use_ps_poll)
  194. cmd->flags |=
  195. cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
  196. #endif
  197. return;
  198. }
  199. cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
  200. if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
  201. BIT(IEEE80211_AC_VI) |
  202. BIT(IEEE80211_AC_BE) |
  203. BIT(IEEE80211_AC_BK))) {
  204. cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
  205. cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
  206. cmd->snooze_window = (mvm->cur_ucode == IWL_UCODE_WOWLAN) ?
  207. cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
  208. cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
  209. }
  210. cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len;
  211. if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags &
  212. cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
  213. cmd->rx_data_timeout_uapsd =
  214. cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
  215. cmd->tx_data_timeout_uapsd =
  216. cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
  217. } else {
  218. cmd->rx_data_timeout_uapsd =
  219. cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
  220. cmd->tx_data_timeout_uapsd =
  221. cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
  222. }
  223. if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
  224. cmd->heavy_tx_thld_packets =
  225. IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
  226. cmd->heavy_rx_thld_packets =
  227. IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
  228. } else {
  229. cmd->heavy_tx_thld_packets =
  230. IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
  231. cmd->heavy_rx_thld_packets =
  232. IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
  233. }
  234. cmd->heavy_tx_thld_percentage =
  235. IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
  236. cmd->heavy_rx_thld_percentage =
  237. IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
  238. }
  239. static void iwl_mvm_p2p_standalone_iterator(void *_data, u8 *mac,
  240. struct ieee80211_vif *vif)
  241. {
  242. bool *is_p2p_standalone = _data;
  243. switch (ieee80211_vif_type_p2p(vif)) {
  244. case NL80211_IFTYPE_P2P_GO:
  245. case NL80211_IFTYPE_AP:
  246. *is_p2p_standalone = false;
  247. break;
  248. case NL80211_IFTYPE_STATION:
  249. if (vif->bss_conf.assoc)
  250. *is_p2p_standalone = false;
  251. break;
  252. default:
  253. break;
  254. }
  255. }
  256. static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
  257. struct ieee80211_vif *vif)
  258. {
  259. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  260. if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
  261. ETH_ALEN))
  262. return false;
  263. /*
  264. * Avoid using uAPSD if P2P client is associated to GO that uses
  265. * opportunistic power save. This is due to current FW limitation.
  266. */
  267. if (vif->p2p &&
  268. (vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
  269. IEEE80211_P2P_OPPPS_ENABLE_BIT))
  270. return false;
  271. /*
  272. * Avoid using uAPSD if client is in DCM -
  273. * low latency issue in Miracast
  274. */
  275. if (iwl_mvm_phy_ctx_count(mvm) >= 2)
  276. return false;
  277. if (vif->p2p) {
  278. /* Allow U-APSD only if p2p is stand alone */
  279. bool is_p2p_standalone = true;
  280. if (!iwl_mvm_is_p2p_scm_uapsd_supported(mvm))
  281. return false;
  282. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  283. IEEE80211_IFACE_ITER_NORMAL,
  284. iwl_mvm_p2p_standalone_iterator,
  285. &is_p2p_standalone);
  286. if (!is_p2p_standalone)
  287. return false;
  288. }
  289. return true;
  290. }
  291. static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
  292. {
  293. struct ieee80211_chanctx_conf *chanctx_conf;
  294. struct ieee80211_channel *chan;
  295. bool radar_detect = false;
  296. rcu_read_lock();
  297. chanctx_conf = rcu_dereference(vif->chanctx_conf);
  298. WARN_ON(!chanctx_conf);
  299. if (chanctx_conf) {
  300. chan = chanctx_conf->def.chan;
  301. radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
  302. }
  303. rcu_read_unlock();
  304. return radar_detect;
  305. }
  306. static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
  307. struct ieee80211_vif *vif,
  308. struct iwl_mac_power_cmd *cmd,
  309. bool host_awake)
  310. {
  311. int dtimper = vif->bss_conf.dtim_period ?: 1;
  312. int skip;
  313. /* disable, in case we're supposed to override */
  314. cmd->skip_dtim_periods = 0;
  315. cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
  316. if (iwl_mvm_power_is_radar(vif))
  317. return;
  318. if (dtimper >= 10)
  319. return;
  320. /* TODO: check that multicast wake lock is off */
  321. if (host_awake) {
  322. if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP)
  323. return;
  324. skip = 2;
  325. } else {
  326. int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
  327. if (WARN_ON(!dtimper_tu))
  328. return;
  329. /* configure skip over dtim up to 306TU - 314 msec */
  330. skip = max_t(u8, 1, 306 / dtimper_tu);
  331. }
  332. /* the firmware really expects "look at every X DTIMs", so add 1 */
  333. cmd->skip_dtim_periods = 1 + skip;
  334. cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
  335. }
  336. static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
  337. struct ieee80211_vif *vif,
  338. struct iwl_mac_power_cmd *cmd,
  339. bool host_awake)
  340. {
  341. int dtimper, bi;
  342. int keep_alive;
  343. struct iwl_mvm_vif *mvmvif __maybe_unused =
  344. iwl_mvm_vif_from_mac80211(vif);
  345. cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
  346. mvmvif->color));
  347. dtimper = vif->bss_conf.dtim_period;
  348. bi = vif->bss_conf.beacon_int;
  349. /*
  350. * Regardless of power management state the driver must set
  351. * keep alive period. FW will use it for sending keep alive NDPs
  352. * immediately after association. Check that keep alive period
  353. * is at least 3 * DTIM
  354. */
  355. keep_alive = DIV_ROUND_UP(ieee80211_tu_to_usec(3 * dtimper * bi),
  356. USEC_PER_SEC);
  357. keep_alive = max(keep_alive, POWER_KEEP_ALIVE_PERIOD_SEC);
  358. cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
  359. if (mvm->ps_disabled)
  360. return;
  361. cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
  362. if (!vif->bss_conf.ps || !mvmvif->pm_enabled)
  363. return;
  364. if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
  365. (!fw_has_capa(&mvm->fw->ucode_capa,
  366. IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
  367. !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE))
  368. return;
  369. cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
  370. if (vif->bss_conf.beacon_rate &&
  371. (vif->bss_conf.beacon_rate->bitrate == 10 ||
  372. vif->bss_conf.beacon_rate->bitrate == 60)) {
  373. cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
  374. cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
  375. }
  376. iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake);
  377. if (!host_awake) {
  378. cmd->rx_data_timeout =
  379. cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
  380. cmd->tx_data_timeout =
  381. cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
  382. } else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
  383. fw_has_capa(&mvm->fw->ucode_capa,
  384. IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) {
  385. cmd->tx_data_timeout =
  386. cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT);
  387. cmd->rx_data_timeout =
  388. cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT);
  389. } else {
  390. cmd->rx_data_timeout =
  391. cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
  392. cmd->tx_data_timeout =
  393. cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
  394. }
  395. if (iwl_mvm_power_allow_uapsd(mvm, vif))
  396. iwl_mvm_power_configure_uapsd(mvm, vif, cmd);
  397. #ifdef CONFIG_IWLWIFI_DEBUGFS
  398. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
  399. cmd->keep_alive_seconds =
  400. cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
  401. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
  402. if (mvmvif->dbgfs_pm.skip_over_dtim)
  403. cmd->flags |=
  404. cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
  405. else
  406. cmd->flags &=
  407. cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
  408. }
  409. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
  410. cmd->rx_data_timeout =
  411. cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
  412. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
  413. cmd->tx_data_timeout =
  414. cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
  415. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
  416. cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
  417. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
  418. if (mvmvif->dbgfs_pm.lprx_ena)
  419. cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
  420. else
  421. cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
  422. }
  423. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
  424. cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
  425. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) {
  426. if (mvmvif->dbgfs_pm.snooze_ena)
  427. cmd->flags |=
  428. cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
  429. else
  430. cmd->flags &=
  431. cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
  432. }
  433. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_UAPSD_MISBEHAVING) {
  434. u16 flag = POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK;
  435. if (mvmvif->dbgfs_pm.uapsd_misbehaving)
  436. cmd->flags |= cpu_to_le16(flag);
  437. else
  438. cmd->flags &= cpu_to_le16(flag);
  439. }
  440. #endif /* CONFIG_IWLWIFI_DEBUGFS */
  441. }
  442. static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
  443. struct ieee80211_vif *vif)
  444. {
  445. struct iwl_mac_power_cmd cmd = {};
  446. iwl_mvm_power_build_cmd(mvm, vif, &cmd,
  447. mvm->cur_ucode != IWL_UCODE_WOWLAN);
  448. iwl_mvm_power_log(mvm, &cmd);
  449. #ifdef CONFIG_IWLWIFI_DEBUGFS
  450. memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
  451. #endif
  452. return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0,
  453. sizeof(cmd), &cmd);
  454. }
  455. int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
  456. {
  457. struct iwl_device_power_cmd cmd = {
  458. .flags = 0,
  459. };
  460. if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
  461. mvm->ps_disabled = true;
  462. if (!mvm->ps_disabled)
  463. cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
  464. #ifdef CONFIG_IWLWIFI_DEBUGFS
  465. if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 :
  466. mvm->disable_power_off)
  467. cmd.flags &=
  468. cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
  469. #endif
  470. IWL_DEBUG_POWER(mvm,
  471. "Sending device power command with flags = 0x%X\n",
  472. cmd.flags);
  473. return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, 0, sizeof(cmd),
  474. &cmd);
  475. }
  476. void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
  477. {
  478. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  479. if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid,
  480. ETH_ALEN))
  481. eth_zero_addr(mvmvif->uapsd_misbehaving_bssid);
  482. }
  483. static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
  484. struct ieee80211_vif *vif)
  485. {
  486. u8 *ap_sta_id = _data;
  487. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  488. /* The ap_sta_id is not expected to change during current association
  489. * so no explicit protection is needed
  490. */
  491. if (mvmvif->ap_sta_id == *ap_sta_id)
  492. memcpy(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
  493. ETH_ALEN);
  494. }
  495. void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
  496. struct iwl_rx_cmd_buffer *rxb)
  497. {
  498. struct iwl_rx_packet *pkt = rxb_addr(rxb);
  499. struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
  500. u8 ap_sta_id = le32_to_cpu(notif->sta_id);
  501. ieee80211_iterate_active_interfaces_atomic(
  502. mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
  503. iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
  504. }
  505. struct iwl_power_vifs {
  506. struct iwl_mvm *mvm;
  507. struct ieee80211_vif *bss_vif;
  508. struct ieee80211_vif *p2p_vif;
  509. struct ieee80211_vif *ap_vif;
  510. struct ieee80211_vif *monitor_vif;
  511. bool p2p_active;
  512. bool bss_active;
  513. bool ap_active;
  514. bool monitor_active;
  515. };
  516. static void iwl_mvm_power_disable_pm_iterator(void *_data, u8* mac,
  517. struct ieee80211_vif *vif)
  518. {
  519. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  520. mvmvif->pm_enabled = false;
  521. }
  522. static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
  523. struct ieee80211_vif *vif)
  524. {
  525. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  526. bool *disable_ps = _data;
  527. if (mvmvif->phy_ctxt)
  528. if (mvmvif->phy_ctxt->id < MAX_PHYS)
  529. *disable_ps |= mvmvif->ps_disabled;
  530. }
  531. static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
  532. struct ieee80211_vif *vif)
  533. {
  534. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  535. struct iwl_power_vifs *power_iterator = _data;
  536. switch (ieee80211_vif_type_p2p(vif)) {
  537. case NL80211_IFTYPE_P2P_DEVICE:
  538. break;
  539. case NL80211_IFTYPE_P2P_GO:
  540. case NL80211_IFTYPE_AP:
  541. /* only a single MAC of the same type */
  542. WARN_ON(power_iterator->ap_vif);
  543. power_iterator->ap_vif = vif;
  544. if (mvmvif->phy_ctxt)
  545. if (mvmvif->phy_ctxt->id < MAX_PHYS)
  546. power_iterator->ap_active = true;
  547. break;
  548. case NL80211_IFTYPE_MONITOR:
  549. /* only a single MAC of the same type */
  550. WARN_ON(power_iterator->monitor_vif);
  551. power_iterator->monitor_vif = vif;
  552. if (mvmvif->phy_ctxt)
  553. if (mvmvif->phy_ctxt->id < MAX_PHYS)
  554. power_iterator->monitor_active = true;
  555. break;
  556. case NL80211_IFTYPE_P2P_CLIENT:
  557. /* only a single MAC of the same type */
  558. WARN_ON(power_iterator->p2p_vif);
  559. power_iterator->p2p_vif = vif;
  560. if (mvmvif->phy_ctxt)
  561. if (mvmvif->phy_ctxt->id < MAX_PHYS)
  562. power_iterator->p2p_active = true;
  563. break;
  564. case NL80211_IFTYPE_STATION:
  565. power_iterator->bss_vif = vif;
  566. if (mvmvif->phy_ctxt)
  567. if (mvmvif->phy_ctxt->id < MAX_PHYS)
  568. power_iterator->bss_active = true;
  569. break;
  570. default:
  571. break;
  572. }
  573. }
  574. static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
  575. struct iwl_power_vifs *vifs)
  576. {
  577. struct iwl_mvm_vif *bss_mvmvif = NULL;
  578. struct iwl_mvm_vif *p2p_mvmvif = NULL;
  579. struct iwl_mvm_vif *ap_mvmvif = NULL;
  580. bool client_same_channel = false;
  581. bool ap_same_channel = false;
  582. lockdep_assert_held(&mvm->mutex);
  583. /* set pm_enable to false */
  584. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  585. IEEE80211_IFACE_ITER_NORMAL,
  586. iwl_mvm_power_disable_pm_iterator,
  587. NULL);
  588. if (vifs->bss_vif)
  589. bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif);
  590. if (vifs->p2p_vif)
  591. p2p_mvmvif = iwl_mvm_vif_from_mac80211(vifs->p2p_vif);
  592. if (vifs->ap_vif)
  593. ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
  594. /* don't allow PM if any TDLS stations exist */
  595. if (iwl_mvm_tdls_sta_count(mvm, NULL))
  596. return;
  597. /* enable PM on bss if bss stand alone */
  598. if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
  599. bss_mvmvif->pm_enabled = true;
  600. return;
  601. }
  602. /* enable PM on p2p if p2p stand alone */
  603. if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
  604. p2p_mvmvif->pm_enabled = true;
  605. return;
  606. }
  607. if (vifs->bss_active && vifs->p2p_active)
  608. client_same_channel = (bss_mvmvif->phy_ctxt->id ==
  609. p2p_mvmvif->phy_ctxt->id);
  610. if (vifs->bss_active && vifs->ap_active)
  611. ap_same_channel = (bss_mvmvif->phy_ctxt->id ==
  612. ap_mvmvif->phy_ctxt->id);
  613. /* clients are not stand alone: enable PM if DCM */
  614. if (!(client_same_channel || ap_same_channel)) {
  615. if (vifs->bss_active)
  616. bss_mvmvif->pm_enabled = true;
  617. if (vifs->p2p_active)
  618. p2p_mvmvif->pm_enabled = true;
  619. return;
  620. }
  621. /*
  622. * There is only one channel in the system and there are only
  623. * bss and p2p clients that share it
  624. */
  625. if (client_same_channel && !vifs->ap_active) {
  626. /* share same channel*/
  627. bss_mvmvif->pm_enabled = true;
  628. p2p_mvmvif->pm_enabled = true;
  629. }
  630. }
  631. #ifdef CONFIG_IWLWIFI_DEBUGFS
  632. int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
  633. struct ieee80211_vif *vif, char *buf,
  634. int bufsz)
  635. {
  636. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  637. struct iwl_mac_power_cmd cmd = {};
  638. int pos = 0;
  639. mutex_lock(&mvm->mutex);
  640. memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
  641. mutex_unlock(&mvm->mutex);
  642. pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
  643. iwlmvm_mod_params.power_scheme);
  644. pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
  645. le16_to_cpu(cmd.flags));
  646. pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
  647. le16_to_cpu(cmd.keep_alive_seconds));
  648. if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)))
  649. return pos;
  650. pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
  651. (cmd.flags &
  652. cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0);
  653. pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
  654. cmd.skip_dtim_periods);
  655. if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
  656. pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
  657. le32_to_cpu(cmd.rx_data_timeout));
  658. pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
  659. le32_to_cpu(cmd.tx_data_timeout));
  660. }
  661. if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
  662. pos += scnprintf(buf+pos, bufsz-pos,
  663. "lprx_rssi_threshold = %d\n",
  664. cmd.lprx_rssi_threshold);
  665. if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
  666. return pos;
  667. pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n",
  668. le32_to_cpu(cmd.rx_data_timeout_uapsd));
  669. pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n",
  670. le32_to_cpu(cmd.tx_data_timeout_uapsd));
  671. pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid);
  672. pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n",
  673. cmd.uapsd_ac_flags);
  674. pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n",
  675. cmd.uapsd_max_sp);
  676. pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n",
  677. cmd.heavy_tx_thld_packets);
  678. pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n",
  679. cmd.heavy_rx_thld_packets);
  680. pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n",
  681. cmd.heavy_tx_thld_percentage);
  682. pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n",
  683. cmd.heavy_rx_thld_percentage);
  684. pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n",
  685. (cmd.flags &
  686. cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ?
  687. 1 : 0);
  688. if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)))
  689. return pos;
  690. pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n",
  691. cmd.snooze_interval);
  692. pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n",
  693. cmd.snooze_window);
  694. return pos;
  695. }
  696. void
  697. iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
  698. struct iwl_beacon_filter_cmd *cmd)
  699. {
  700. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  701. struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
  702. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
  703. cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
  704. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
  705. cmd->bf_roaming_energy_delta =
  706. cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
  707. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
  708. cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
  709. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
  710. cmd->bf_temp_threshold =
  711. cpu_to_le32(dbgfs_bf->bf_temp_threshold);
  712. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
  713. cmd->bf_temp_fast_filter =
  714. cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
  715. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
  716. cmd->bf_temp_slow_filter =
  717. cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
  718. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
  719. cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
  720. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
  721. cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
  722. if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
  723. cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
  724. if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
  725. cmd->ba_enable_beacon_abort =
  726. cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
  727. }
  728. #endif
  729. static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
  730. struct ieee80211_vif *vif,
  731. struct iwl_beacon_filter_cmd *cmd,
  732. u32 cmd_flags,
  733. bool d0i3)
  734. {
  735. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  736. int ret;
  737. if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period ||
  738. vif->type != NL80211_IFTYPE_STATION || vif->p2p)
  739. return 0;
  740. iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd, d0i3);
  741. if (!d0i3)
  742. iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
  743. ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
  744. /* don't change bf_enabled in case of temporary d0i3 configuration */
  745. if (!ret && !d0i3)
  746. mvmvif->bf_data.bf_enabled = true;
  747. return ret;
  748. }
  749. int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
  750. struct ieee80211_vif *vif,
  751. u32 flags)
  752. {
  753. struct iwl_beacon_filter_cmd cmd = {
  754. IWL_BF_CMD_CONFIG_DEFAULTS,
  755. .bf_enable_beacon_filter = cpu_to_le32(1),
  756. };
  757. return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false);
  758. }
  759. static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
  760. struct ieee80211_vif *vif,
  761. u32 flags, bool d0i3)
  762. {
  763. struct iwl_beacon_filter_cmd cmd = {};
  764. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  765. int ret;
  766. if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
  767. return 0;
  768. ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
  769. /* don't change bf_enabled in case of temporary d0i3 configuration */
  770. if (!ret && !d0i3)
  771. mvmvif->bf_data.bf_enabled = false;
  772. return ret;
  773. }
  774. int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
  775. struct ieee80211_vif *vif,
  776. u32 flags)
  777. {
  778. return _iwl_mvm_disable_beacon_filter(mvm, vif, flags, false);
  779. }
  780. static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
  781. {
  782. bool disable_ps;
  783. int ret;
  784. /* disable PS if CAM */
  785. disable_ps = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
  786. /* ...or if any of the vifs require PS to be off */
  787. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  788. IEEE80211_IFACE_ITER_NORMAL,
  789. iwl_mvm_power_ps_disabled_iterator,
  790. &disable_ps);
  791. /* update device power state if it has changed */
  792. if (mvm->ps_disabled != disable_ps) {
  793. bool old_ps_disabled = mvm->ps_disabled;
  794. mvm->ps_disabled = disable_ps;
  795. ret = iwl_mvm_power_update_device(mvm);
  796. if (ret) {
  797. mvm->ps_disabled = old_ps_disabled;
  798. return ret;
  799. }
  800. }
  801. return 0;
  802. }
  803. static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
  804. struct ieee80211_vif *vif)
  805. {
  806. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  807. struct iwl_beacon_filter_cmd cmd = {
  808. IWL_BF_CMD_CONFIG_DEFAULTS,
  809. .bf_enable_beacon_filter = cpu_to_le32(1),
  810. };
  811. if (!mvmvif->bf_data.bf_enabled)
  812. return 0;
  813. if (mvm->cur_ucode == IWL_UCODE_WOWLAN)
  814. cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
  815. mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled ||
  816. mvm->ps_disabled ||
  817. !vif->bss_conf.ps ||
  818. iwl_mvm_vif_low_latency(mvmvif));
  819. return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false);
  820. }
  821. int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
  822. {
  823. struct iwl_power_vifs vifs = {
  824. .mvm = mvm,
  825. };
  826. int ret;
  827. lockdep_assert_held(&mvm->mutex);
  828. /* get vifs info */
  829. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  830. IEEE80211_IFACE_ITER_NORMAL,
  831. iwl_mvm_power_get_vifs_iterator, &vifs);
  832. ret = iwl_mvm_power_set_ps(mvm);
  833. if (ret)
  834. return ret;
  835. if (vifs.bss_vif)
  836. return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
  837. return 0;
  838. }
  839. int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
  840. {
  841. struct iwl_power_vifs vifs = {
  842. .mvm = mvm,
  843. };
  844. int ret;
  845. lockdep_assert_held(&mvm->mutex);
  846. /* get vifs info */
  847. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  848. IEEE80211_IFACE_ITER_NORMAL,
  849. iwl_mvm_power_get_vifs_iterator, &vifs);
  850. iwl_mvm_power_set_pm(mvm, &vifs);
  851. ret = iwl_mvm_power_set_ps(mvm);
  852. if (ret)
  853. return ret;
  854. if (vifs.bss_vif) {
  855. ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
  856. if (ret)
  857. return ret;
  858. }
  859. if (vifs.p2p_vif) {
  860. ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
  861. if (ret)
  862. return ret;
  863. }
  864. if (vifs.bss_vif)
  865. return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
  866. return 0;
  867. }
  868. int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
  869. struct ieee80211_vif *vif,
  870. bool enable, u32 flags)
  871. {
  872. int ret;
  873. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  874. struct iwl_mac_power_cmd cmd = {};
  875. if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
  876. return 0;
  877. if (!vif->bss_conf.assoc)
  878. return 0;
  879. iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable);
  880. iwl_mvm_power_log(mvm, &cmd);
  881. #ifdef CONFIG_IWLWIFI_DEBUGFS
  882. memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd));
  883. #endif
  884. ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags,
  885. sizeof(cmd), &cmd);
  886. if (ret)
  887. return ret;
  888. /* configure beacon filtering */
  889. if (mvmvif != mvm->bf_allowed_vif)
  890. return 0;
  891. if (enable) {
  892. struct iwl_beacon_filter_cmd cmd_bf = {
  893. IWL_BF_CMD_CONFIG_D0I3,
  894. .bf_enable_beacon_filter = cpu_to_le32(1),
  895. };
  896. /*
  897. * When beacon storing is supported - disable beacon filtering
  898. * altogether - the latest beacon will be sent when exiting d0i3
  899. */
  900. if (fw_has_capa(&mvm->fw->ucode_capa,
  901. IWL_UCODE_TLV_CAPA_BEACON_STORING))
  902. ret = _iwl_mvm_disable_beacon_filter(mvm, vif, flags,
  903. true);
  904. else
  905. ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf,
  906. flags, true);
  907. } else {
  908. if (mvmvif->bf_data.bf_enabled)
  909. ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags);
  910. else
  911. ret = iwl_mvm_disable_beacon_filter(mvm, vif, flags);
  912. }
  913. return ret;
  914. }