power.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  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 - 2017 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 - 2017 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. #ifdef CONFIG_IWLWIFI_DEBUGFS
  165. /* set advanced pm flag with no uapsd ACs to enable ps-poll */
  166. if (mvmvif->dbgfs_pm.use_ps_poll) {
  167. cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
  168. return;
  169. }
  170. #endif
  171. for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
  172. if (!mvmvif->queue_params[ac].uapsd)
  173. continue;
  174. if (mvm->fwrt.cur_fw_img != IWL_UCODE_WOWLAN)
  175. cmd->flags |=
  176. cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
  177. cmd->uapsd_ac_flags |= BIT(ac);
  178. /* QNDP TID - the highest TID with no admission control */
  179. if (!tid_found && !mvmvif->queue_params[ac].acm) {
  180. tid_found = true;
  181. switch (ac) {
  182. case IEEE80211_AC_VO:
  183. cmd->qndp_tid = 6;
  184. break;
  185. case IEEE80211_AC_VI:
  186. cmd->qndp_tid = 5;
  187. break;
  188. case IEEE80211_AC_BE:
  189. cmd->qndp_tid = 0;
  190. break;
  191. case IEEE80211_AC_BK:
  192. cmd->qndp_tid = 1;
  193. break;
  194. }
  195. }
  196. }
  197. cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
  198. if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
  199. BIT(IEEE80211_AC_VI) |
  200. BIT(IEEE80211_AC_BE) |
  201. BIT(IEEE80211_AC_BK))) {
  202. cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
  203. cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
  204. cmd->snooze_window =
  205. (mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN) ?
  206. cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
  207. cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
  208. }
  209. cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len;
  210. if (mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN || cmd->flags &
  211. cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
  212. cmd->rx_data_timeout_uapsd =
  213. cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
  214. cmd->tx_data_timeout_uapsd =
  215. cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
  216. } else {
  217. cmd->rx_data_timeout_uapsd =
  218. cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
  219. cmd->tx_data_timeout_uapsd =
  220. cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
  221. }
  222. if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
  223. cmd->heavy_tx_thld_packets =
  224. IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
  225. cmd->heavy_rx_thld_packets =
  226. IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
  227. } else {
  228. cmd->heavy_tx_thld_packets =
  229. IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
  230. cmd->heavy_rx_thld_packets =
  231. IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
  232. }
  233. cmd->heavy_tx_thld_percentage =
  234. IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
  235. cmd->heavy_rx_thld_percentage =
  236. IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
  237. }
  238. static void iwl_mvm_p2p_standalone_iterator(void *_data, u8 *mac,
  239. struct ieee80211_vif *vif)
  240. {
  241. bool *is_p2p_standalone = _data;
  242. switch (ieee80211_vif_type_p2p(vif)) {
  243. case NL80211_IFTYPE_P2P_GO:
  244. case NL80211_IFTYPE_AP:
  245. *is_p2p_standalone = false;
  246. break;
  247. case NL80211_IFTYPE_STATION:
  248. if (vif->bss_conf.assoc)
  249. *is_p2p_standalone = false;
  250. break;
  251. default:
  252. break;
  253. }
  254. }
  255. static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
  256. struct ieee80211_vif *vif)
  257. {
  258. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  259. if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
  260. ETH_ALEN))
  261. return false;
  262. /*
  263. * Avoid using uAPSD if P2P client is associated to GO that uses
  264. * opportunistic power save. This is due to current FW limitation.
  265. */
  266. if (vif->p2p &&
  267. (vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
  268. IEEE80211_P2P_OPPPS_ENABLE_BIT))
  269. return false;
  270. /*
  271. * Avoid using uAPSD if client is in DCM -
  272. * low latency issue in Miracast
  273. */
  274. if (iwl_mvm_phy_ctx_count(mvm) >= 2)
  275. return false;
  276. if (vif->p2p) {
  277. /* Allow U-APSD only if p2p is stand alone */
  278. bool is_p2p_standalone = true;
  279. if (!iwl_mvm_is_p2p_scm_uapsd_supported(mvm))
  280. return false;
  281. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  282. IEEE80211_IFACE_ITER_NORMAL,
  283. iwl_mvm_p2p_standalone_iterator,
  284. &is_p2p_standalone);
  285. if (!is_p2p_standalone)
  286. return false;
  287. }
  288. return true;
  289. }
  290. static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
  291. {
  292. struct ieee80211_chanctx_conf *chanctx_conf;
  293. struct ieee80211_channel *chan;
  294. bool radar_detect = false;
  295. rcu_read_lock();
  296. chanctx_conf = rcu_dereference(vif->chanctx_conf);
  297. WARN_ON(!chanctx_conf);
  298. if (chanctx_conf) {
  299. chan = chanctx_conf->def.chan;
  300. radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
  301. }
  302. rcu_read_unlock();
  303. return radar_detect;
  304. }
  305. static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
  306. struct ieee80211_vif *vif,
  307. struct iwl_mac_power_cmd *cmd,
  308. bool host_awake)
  309. {
  310. int dtimper = vif->bss_conf.dtim_period ?: 1;
  311. int skip;
  312. /* disable, in case we're supposed to override */
  313. cmd->skip_dtim_periods = 0;
  314. cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
  315. if (iwl_mvm_power_is_radar(vif))
  316. return;
  317. if (dtimper >= 10)
  318. return;
  319. /* TODO: check that multicast wake lock is off */
  320. if (host_awake) {
  321. if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP)
  322. return;
  323. skip = 2;
  324. } else {
  325. int dtimper_tu = dtimper * vif->bss_conf.beacon_int;
  326. if (WARN_ON(!dtimper_tu))
  327. return;
  328. /* configure skip over dtim up to 306TU - 314 msec */
  329. skip = max_t(u8, 1, 306 / dtimper_tu);
  330. }
  331. /* the firmware really expects "look at every X DTIMs", so add 1 */
  332. cmd->skip_dtim_periods = 1 + skip;
  333. cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
  334. }
  335. static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
  336. struct ieee80211_vif *vif,
  337. struct iwl_mac_power_cmd *cmd,
  338. bool host_awake)
  339. {
  340. int dtimper, bi;
  341. int keep_alive;
  342. struct iwl_mvm_vif *mvmvif __maybe_unused =
  343. iwl_mvm_vif_from_mac80211(vif);
  344. cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
  345. mvmvif->color));
  346. dtimper = vif->bss_conf.dtim_period;
  347. bi = vif->bss_conf.beacon_int;
  348. /*
  349. * Regardless of power management state the driver must set
  350. * keep alive period. FW will use it for sending keep alive NDPs
  351. * immediately after association. Check that keep alive period
  352. * is at least 3 * DTIM
  353. */
  354. keep_alive = DIV_ROUND_UP(ieee80211_tu_to_usec(3 * dtimper * bi),
  355. USEC_PER_SEC);
  356. keep_alive = max(keep_alive, POWER_KEEP_ALIVE_PERIOD_SEC);
  357. cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
  358. if (mvm->ps_disabled)
  359. return;
  360. cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
  361. if (!vif->bss_conf.ps || !mvmvif->pm_enabled)
  362. return;
  363. if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
  364. (!fw_has_capa(&mvm->fw->ucode_capa,
  365. IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
  366. !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE))
  367. return;
  368. cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
  369. if (vif->bss_conf.beacon_rate &&
  370. (vif->bss_conf.beacon_rate->bitrate == 10 ||
  371. vif->bss_conf.beacon_rate->bitrate == 60)) {
  372. cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
  373. cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
  374. }
  375. iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake);
  376. if (!host_awake) {
  377. cmd->rx_data_timeout =
  378. cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
  379. cmd->tx_data_timeout =
  380. cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
  381. } else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
  382. fw_has_capa(&mvm->fw->ucode_capa,
  383. IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) {
  384. cmd->tx_data_timeout =
  385. cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT);
  386. cmd->rx_data_timeout =
  387. cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT);
  388. } else {
  389. cmd->rx_data_timeout =
  390. cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
  391. cmd->tx_data_timeout =
  392. cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
  393. }
  394. if (iwl_mvm_power_allow_uapsd(mvm, vif))
  395. iwl_mvm_power_configure_uapsd(mvm, vif, cmd);
  396. #ifdef CONFIG_IWLWIFI_DEBUGFS
  397. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
  398. cmd->keep_alive_seconds =
  399. cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
  400. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
  401. if (mvmvif->dbgfs_pm.skip_over_dtim)
  402. cmd->flags |=
  403. cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
  404. else
  405. cmd->flags &=
  406. cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
  407. }
  408. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
  409. cmd->rx_data_timeout =
  410. cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
  411. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
  412. cmd->tx_data_timeout =
  413. cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
  414. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
  415. cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
  416. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
  417. if (mvmvif->dbgfs_pm.lprx_ena)
  418. cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
  419. else
  420. cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
  421. }
  422. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
  423. cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
  424. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) {
  425. if (mvmvif->dbgfs_pm.snooze_ena)
  426. cmd->flags |=
  427. cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
  428. else
  429. cmd->flags &=
  430. cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
  431. }
  432. if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_UAPSD_MISBEHAVING) {
  433. u16 flag = POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK;
  434. if (mvmvif->dbgfs_pm.uapsd_misbehaving)
  435. cmd->flags |= cpu_to_le16(flag);
  436. else
  437. cmd->flags &= cpu_to_le16(flag);
  438. }
  439. #endif /* CONFIG_IWLWIFI_DEBUGFS */
  440. }
  441. static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
  442. struct ieee80211_vif *vif)
  443. {
  444. struct iwl_mac_power_cmd cmd = {};
  445. iwl_mvm_power_build_cmd(mvm, vif, &cmd,
  446. mvm->fwrt.cur_fw_img != IWL_UCODE_WOWLAN);
  447. iwl_mvm_power_log(mvm, &cmd);
  448. #ifdef CONFIG_IWLWIFI_DEBUGFS
  449. memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
  450. #endif
  451. return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0,
  452. sizeof(cmd), &cmd);
  453. }
  454. int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
  455. {
  456. struct iwl_device_power_cmd cmd = {
  457. .flags = 0,
  458. };
  459. if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
  460. mvm->ps_disabled = true;
  461. if (!mvm->ps_disabled)
  462. cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
  463. #ifdef CONFIG_IWLWIFI_DEBUGFS
  464. if ((mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN) ?
  465. mvm->disable_power_off_d3 : mvm->disable_power_off)
  466. cmd.flags &=
  467. cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
  468. #endif
  469. IWL_DEBUG_POWER(mvm,
  470. "Sending device power command with flags = 0x%X\n",
  471. cmd.flags);
  472. return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, 0, sizeof(cmd),
  473. &cmd);
  474. }
  475. void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
  476. {
  477. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  478. if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid,
  479. ETH_ALEN))
  480. eth_zero_addr(mvmvif->uapsd_misbehaving_bssid);
  481. }
  482. static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
  483. struct ieee80211_vif *vif)
  484. {
  485. u8 *ap_sta_id = _data;
  486. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  487. /* The ap_sta_id is not expected to change during current association
  488. * so no explicit protection is needed
  489. */
  490. if (mvmvif->ap_sta_id == *ap_sta_id)
  491. memcpy(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
  492. ETH_ALEN);
  493. }
  494. void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
  495. struct iwl_rx_cmd_buffer *rxb)
  496. {
  497. struct iwl_rx_packet *pkt = rxb_addr(rxb);
  498. struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
  499. u8 ap_sta_id = le32_to_cpu(notif->sta_id);
  500. ieee80211_iterate_active_interfaces_atomic(
  501. mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
  502. iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
  503. }
  504. struct iwl_power_vifs {
  505. struct iwl_mvm *mvm;
  506. struct ieee80211_vif *bss_vif;
  507. struct ieee80211_vif *p2p_vif;
  508. struct ieee80211_vif *ap_vif;
  509. struct ieee80211_vif *monitor_vif;
  510. bool p2p_active;
  511. bool bss_active;
  512. bool ap_active;
  513. bool monitor_active;
  514. };
  515. static void iwl_mvm_power_disable_pm_iterator(void *_data, u8* mac,
  516. struct ieee80211_vif *vif)
  517. {
  518. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  519. mvmvif->pm_enabled = false;
  520. }
  521. static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
  522. struct ieee80211_vif *vif)
  523. {
  524. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  525. bool *disable_ps = _data;
  526. if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX)
  527. *disable_ps |= mvmvif->ps_disabled;
  528. }
  529. static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
  530. struct ieee80211_vif *vif)
  531. {
  532. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  533. struct iwl_power_vifs *power_iterator = _data;
  534. bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX;
  535. switch (ieee80211_vif_type_p2p(vif)) {
  536. case NL80211_IFTYPE_P2P_DEVICE:
  537. break;
  538. case NL80211_IFTYPE_P2P_GO:
  539. case NL80211_IFTYPE_AP:
  540. /* only a single MAC of the same type */
  541. WARN_ON(power_iterator->ap_vif);
  542. power_iterator->ap_vif = vif;
  543. if (active)
  544. power_iterator->ap_active = true;
  545. break;
  546. case NL80211_IFTYPE_MONITOR:
  547. /* only a single MAC of the same type */
  548. WARN_ON(power_iterator->monitor_vif);
  549. power_iterator->monitor_vif = vif;
  550. if (active)
  551. power_iterator->monitor_active = true;
  552. break;
  553. case NL80211_IFTYPE_P2P_CLIENT:
  554. /* only a single MAC of the same type */
  555. WARN_ON(power_iterator->p2p_vif);
  556. power_iterator->p2p_vif = vif;
  557. if (active)
  558. power_iterator->p2p_active = true;
  559. break;
  560. case NL80211_IFTYPE_STATION:
  561. power_iterator->bss_vif = vif;
  562. if (active)
  563. power_iterator->bss_active = true;
  564. break;
  565. default:
  566. break;
  567. }
  568. }
  569. static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
  570. struct iwl_power_vifs *vifs)
  571. {
  572. struct iwl_mvm_vif *bss_mvmvif = NULL;
  573. struct iwl_mvm_vif *p2p_mvmvif = NULL;
  574. struct iwl_mvm_vif *ap_mvmvif = NULL;
  575. bool client_same_channel = false;
  576. bool ap_same_channel = false;
  577. lockdep_assert_held(&mvm->mutex);
  578. /* set pm_enable to false */
  579. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  580. IEEE80211_IFACE_ITER_NORMAL,
  581. iwl_mvm_power_disable_pm_iterator,
  582. NULL);
  583. if (vifs->bss_vif)
  584. bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif);
  585. if (vifs->p2p_vif)
  586. p2p_mvmvif = iwl_mvm_vif_from_mac80211(vifs->p2p_vif);
  587. if (vifs->ap_vif)
  588. ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
  589. /* don't allow PM if any TDLS stations exist */
  590. if (iwl_mvm_tdls_sta_count(mvm, NULL))
  591. return;
  592. /* enable PM on bss if bss stand alone */
  593. if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
  594. bss_mvmvif->pm_enabled = true;
  595. return;
  596. }
  597. /* enable PM on p2p if p2p stand alone */
  598. if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
  599. p2p_mvmvif->pm_enabled = true;
  600. return;
  601. }
  602. if (vifs->bss_active && vifs->p2p_active)
  603. client_same_channel = (bss_mvmvif->phy_ctxt->id ==
  604. p2p_mvmvif->phy_ctxt->id);
  605. if (vifs->bss_active && vifs->ap_active)
  606. ap_same_channel = (bss_mvmvif->phy_ctxt->id ==
  607. ap_mvmvif->phy_ctxt->id);
  608. /* clients are not stand alone: enable PM if DCM */
  609. if (!(client_same_channel || ap_same_channel)) {
  610. if (vifs->bss_active)
  611. bss_mvmvif->pm_enabled = true;
  612. if (vifs->p2p_active)
  613. p2p_mvmvif->pm_enabled = true;
  614. return;
  615. }
  616. /*
  617. * There is only one channel in the system and there are only
  618. * bss and p2p clients that share it
  619. */
  620. if (client_same_channel && !vifs->ap_active) {
  621. /* share same channel*/
  622. bss_mvmvif->pm_enabled = true;
  623. p2p_mvmvif->pm_enabled = true;
  624. }
  625. }
  626. #ifdef CONFIG_IWLWIFI_DEBUGFS
  627. int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
  628. struct ieee80211_vif *vif, char *buf,
  629. int bufsz)
  630. {
  631. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  632. struct iwl_mac_power_cmd cmd = {};
  633. int pos = 0;
  634. mutex_lock(&mvm->mutex);
  635. memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
  636. mutex_unlock(&mvm->mutex);
  637. pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
  638. iwlmvm_mod_params.power_scheme);
  639. pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
  640. le16_to_cpu(cmd.flags));
  641. pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
  642. le16_to_cpu(cmd.keep_alive_seconds));
  643. if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)))
  644. return pos;
  645. pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
  646. (cmd.flags &
  647. cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0);
  648. pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
  649. cmd.skip_dtim_periods);
  650. if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
  651. pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
  652. le32_to_cpu(cmd.rx_data_timeout));
  653. pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
  654. le32_to_cpu(cmd.tx_data_timeout));
  655. }
  656. if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
  657. pos += scnprintf(buf+pos, bufsz-pos,
  658. "lprx_rssi_threshold = %d\n",
  659. cmd.lprx_rssi_threshold);
  660. if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
  661. return pos;
  662. pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n",
  663. le32_to_cpu(cmd.rx_data_timeout_uapsd));
  664. pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n",
  665. le32_to_cpu(cmd.tx_data_timeout_uapsd));
  666. pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid);
  667. pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n",
  668. cmd.uapsd_ac_flags);
  669. pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n",
  670. cmd.uapsd_max_sp);
  671. pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n",
  672. cmd.heavy_tx_thld_packets);
  673. pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n",
  674. cmd.heavy_rx_thld_packets);
  675. pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n",
  676. cmd.heavy_tx_thld_percentage);
  677. pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n",
  678. cmd.heavy_rx_thld_percentage);
  679. pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n",
  680. (cmd.flags &
  681. cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ?
  682. 1 : 0);
  683. if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)))
  684. return pos;
  685. pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n",
  686. cmd.snooze_interval);
  687. pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n",
  688. cmd.snooze_window);
  689. return pos;
  690. }
  691. void
  692. iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
  693. struct iwl_beacon_filter_cmd *cmd)
  694. {
  695. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  696. struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
  697. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
  698. cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
  699. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
  700. cmd->bf_roaming_energy_delta =
  701. cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
  702. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
  703. cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
  704. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
  705. cmd->bf_temp_threshold =
  706. cpu_to_le32(dbgfs_bf->bf_temp_threshold);
  707. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
  708. cmd->bf_temp_fast_filter =
  709. cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
  710. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
  711. cmd->bf_temp_slow_filter =
  712. cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
  713. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
  714. cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
  715. if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
  716. cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
  717. if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
  718. cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
  719. if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
  720. cmd->ba_enable_beacon_abort =
  721. cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
  722. }
  723. #endif
  724. static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
  725. struct ieee80211_vif *vif,
  726. struct iwl_beacon_filter_cmd *cmd,
  727. u32 cmd_flags,
  728. bool d0i3)
  729. {
  730. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  731. int ret;
  732. if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period ||
  733. vif->type != NL80211_IFTYPE_STATION || vif->p2p)
  734. return 0;
  735. iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd, d0i3);
  736. if (!d0i3)
  737. iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
  738. ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
  739. /* don't change bf_enabled in case of temporary d0i3 configuration */
  740. if (!ret && !d0i3)
  741. mvmvif->bf_data.bf_enabled = true;
  742. return ret;
  743. }
  744. int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
  745. struct ieee80211_vif *vif,
  746. u32 flags)
  747. {
  748. struct iwl_beacon_filter_cmd cmd = {
  749. IWL_BF_CMD_CONFIG_DEFAULTS,
  750. .bf_enable_beacon_filter = cpu_to_le32(1),
  751. };
  752. return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false);
  753. }
  754. static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
  755. struct ieee80211_vif *vif,
  756. u32 flags, bool d0i3)
  757. {
  758. struct iwl_beacon_filter_cmd cmd = {};
  759. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  760. int ret;
  761. if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
  762. return 0;
  763. ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
  764. /* don't change bf_enabled in case of temporary d0i3 configuration */
  765. if (!ret && !d0i3)
  766. mvmvif->bf_data.bf_enabled = false;
  767. return ret;
  768. }
  769. int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
  770. struct ieee80211_vif *vif,
  771. u32 flags)
  772. {
  773. return _iwl_mvm_disable_beacon_filter(mvm, vif, flags, false);
  774. }
  775. static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
  776. {
  777. bool disable_ps;
  778. int ret;
  779. /* disable PS if CAM */
  780. disable_ps = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
  781. /* ...or if any of the vifs require PS to be off */
  782. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  783. IEEE80211_IFACE_ITER_NORMAL,
  784. iwl_mvm_power_ps_disabled_iterator,
  785. &disable_ps);
  786. /* update device power state if it has changed */
  787. if (mvm->ps_disabled != disable_ps) {
  788. bool old_ps_disabled = mvm->ps_disabled;
  789. mvm->ps_disabled = disable_ps;
  790. ret = iwl_mvm_power_update_device(mvm);
  791. if (ret) {
  792. mvm->ps_disabled = old_ps_disabled;
  793. return ret;
  794. }
  795. }
  796. return 0;
  797. }
  798. static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
  799. struct ieee80211_vif *vif)
  800. {
  801. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  802. struct iwl_beacon_filter_cmd cmd = {
  803. IWL_BF_CMD_CONFIG_DEFAULTS,
  804. .bf_enable_beacon_filter = cpu_to_le32(1),
  805. };
  806. if (!mvmvif->bf_data.bf_enabled)
  807. return 0;
  808. if (mvm->fwrt.cur_fw_img == IWL_UCODE_WOWLAN)
  809. cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
  810. mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled ||
  811. mvm->ps_disabled ||
  812. !vif->bss_conf.ps ||
  813. iwl_mvm_vif_low_latency(mvmvif));
  814. return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false);
  815. }
  816. int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
  817. {
  818. struct iwl_power_vifs vifs = {
  819. .mvm = mvm,
  820. };
  821. int ret;
  822. lockdep_assert_held(&mvm->mutex);
  823. /* get vifs info */
  824. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  825. IEEE80211_IFACE_ITER_NORMAL,
  826. iwl_mvm_power_get_vifs_iterator, &vifs);
  827. ret = iwl_mvm_power_set_ps(mvm);
  828. if (ret)
  829. return ret;
  830. if (vifs.bss_vif)
  831. return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
  832. return 0;
  833. }
  834. int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
  835. {
  836. struct iwl_power_vifs vifs = {
  837. .mvm = mvm,
  838. };
  839. int ret;
  840. lockdep_assert_held(&mvm->mutex);
  841. /* get vifs info */
  842. ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  843. IEEE80211_IFACE_ITER_NORMAL,
  844. iwl_mvm_power_get_vifs_iterator, &vifs);
  845. iwl_mvm_power_set_pm(mvm, &vifs);
  846. ret = iwl_mvm_power_set_ps(mvm);
  847. if (ret)
  848. return ret;
  849. if (vifs.bss_vif) {
  850. ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
  851. if (ret)
  852. return ret;
  853. }
  854. if (vifs.p2p_vif) {
  855. ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
  856. if (ret)
  857. return ret;
  858. }
  859. if (vifs.bss_vif)
  860. return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
  861. return 0;
  862. }
  863. int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
  864. struct ieee80211_vif *vif,
  865. bool enable, u32 flags)
  866. {
  867. int ret;
  868. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  869. struct iwl_mac_power_cmd cmd = {};
  870. if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
  871. return 0;
  872. if (!vif->bss_conf.assoc)
  873. return 0;
  874. iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable);
  875. iwl_mvm_power_log(mvm, &cmd);
  876. #ifdef CONFIG_IWLWIFI_DEBUGFS
  877. memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd));
  878. #endif
  879. ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags,
  880. sizeof(cmd), &cmd);
  881. if (ret)
  882. return ret;
  883. /* configure beacon filtering */
  884. if (mvmvif != mvm->bf_allowed_vif)
  885. return 0;
  886. if (enable) {
  887. struct iwl_beacon_filter_cmd cmd_bf = {
  888. IWL_BF_CMD_CONFIG_D0I3,
  889. .bf_enable_beacon_filter = cpu_to_le32(1),
  890. };
  891. /*
  892. * When beacon storing is supported - disable beacon filtering
  893. * altogether - the latest beacon will be sent when exiting d0i3
  894. */
  895. if (fw_has_capa(&mvm->fw->ucode_capa,
  896. IWL_UCODE_TLV_CAPA_BEACON_STORING))
  897. ret = _iwl_mvm_disable_beacon_filter(mvm, vif, flags,
  898. true);
  899. else
  900. ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf,
  901. flags, true);
  902. } else {
  903. if (mvmvif->bf_data.bf_enabled)
  904. ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags);
  905. else
  906. ret = iwl_mvm_disable_beacon_filter(mvm, vif, flags);
  907. }
  908. return ret;
  909. }