aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-01-28 03:17:18 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-02-03 15:43:56 -0500
commitc1cb92fc1ecd2159b7fb148ed8d5f09d511ae030 (patch)
treec5c4838bfb83c9f2ee3123e2c8ced4e5ec29deb8 /drivers/net/wireless
parent474b50c30864a342d47e5d4a4a69df5750fa4254 (diff)
iwlwifi: mvm: remove support for legacy power API
If the driver detects old firmware, we disable support for power management. This greatly simplifies the code. Reviewed-by: Alexander Bondar <alexander.bondar@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/Makefile2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c7
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c31
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h62
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c54
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power_legacy.c319
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c2
11 files changed, 62 insertions, 434 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile
index f98ec2b23898..41d390fd2ac8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/mvm/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o
2iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o 2iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
3iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o 3iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
4iwlmvm-y += scan.o time-event.o rs.o 4iwlmvm-y += scan.o time-event.o rs.o
5iwlmvm-y += power.o power_legacy.o bt-coex.o 5iwlmvm-y += power.o bt-coex.o
6iwlmvm-y += led.o tt.o 6iwlmvm-y += led.o tt.o
7iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o 7iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
8iwlmvm-$(CONFIG_PM_SLEEP) += d3.o 8iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index f36a7ee0267f..a9850aa909d8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -1191,11 +1191,11 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1191 if (ret) 1191 if (ret)
1192 goto out; 1192 goto out;
1193 1193
1194 ret = iwl_mvm_power_update_device_mode(mvm); 1194 ret = iwl_mvm_power_update_device(mvm);
1195 if (ret) 1195 if (ret)
1196 goto out; 1196 goto out;
1197 1197
1198 ret = iwl_mvm_power_update_mode(mvm, vif); 1198 ret = iwl_mvm_power_mac_update_mode(mvm, vif);
1199 if (ret) 1199 if (ret)
1200 goto out; 1200 goto out;
1201 1201
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
index a46895eaa374..9c0708eb540c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
@@ -185,7 +185,7 @@ static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
185 185
186 mutex_lock(&mvm->mutex); 186 mutex_lock(&mvm->mutex);
187 iwl_dbgfs_update_pm(mvm, vif, param, val); 187 iwl_dbgfs_update_pm(mvm, vif, param, val);
188 ret = iwl_mvm_power_update_mode(mvm, vif); 188 ret = iwl_mvm_power_mac_update_mode(mvm, vif);
189 mutex_unlock(&mvm->mutex); 189 mutex_unlock(&mvm->mutex);
190 190
191 return ret ?: count; 191 return ret ?: count;
@@ -202,7 +202,7 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
202 int bufsz = sizeof(buf); 202 int bufsz = sizeof(buf);
203 int pos; 203 int pos;
204 204
205 pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz); 205 pos = iwl_mvm_power_mac_dbgfs_read(mvm, vif, buf, bufsz);
206 206
207 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 207 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
208} 208}
@@ -587,7 +587,8 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
587 return; 587 return;
588 } 588 }
589 589
590 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && 590 if ((mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT) &&
591 iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
591 ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) || 592 ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
592 (vif->type == NL80211_IFTYPE_STATION && vif->p2p && 593 (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
593 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS))) 594 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS)))
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index c116765ebe42..6853e5efe522 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -250,7 +250,7 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
250 } 250 }
251 251
252 mutex_lock(&mvm->mutex); 252 mutex_lock(&mvm->mutex);
253 ret = iwl_mvm_power_update_device_mode(mvm); 253 ret = iwl_mvm_power_update_device(mvm);
254 mutex_unlock(&mvm->mutex); 254 mutex_unlock(&mvm->mutex);
255 255
256 return ret ?: count; 256 return ret ?: count;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 212ffecf038b..155bb20519c2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -442,7 +442,13 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
442 /* Initialize tx backoffs to the minimal possible */ 442 /* Initialize tx backoffs to the minimal possible */
443 iwl_mvm_tt_tx_backoff(mvm, 0); 443 iwl_mvm_tt_tx_backoff(mvm, 0);
444 444
445 ret = iwl_mvm_power_update_device_mode(mvm); 445 if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) {
446 ret = iwl_power_legacy_set_cam_mode(mvm);
447 if (ret)
448 goto error;
449 }
450
451 ret = iwl_mvm_power_update_device(mvm);
446 if (ret) 452 if (ret)
447 goto error; 453 goto error;
448 454
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 43dd64409fc5..01b450039106 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -636,14 +636,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
636 cancel_work_sync(&mvm->async_handlers_wk); 636 cancel_work_sync(&mvm->async_handlers_wk);
637} 637}
638 638
639static void iwl_mvm_power_update_iterator(void *data, u8 *mac,
640 struct ieee80211_vif *vif)
641{
642 struct iwl_mvm *mvm = data;
643
644 iwl_mvm_power_update_mode(mvm, vif);
645}
646
647static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm) 639static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
648{ 640{
649 u16 i; 641 u16 i;
@@ -725,7 +717,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
725 if (ret) 717 if (ret)
726 goto out_release; 718 goto out_release;
727 719
728 iwl_mvm_power_disable(mvm, vif); 720 iwl_mvm_power_mac_disable(mvm, vif);
729 721
730 /* beacon filtering */ 722 /* beacon filtering */
731 ret = iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC); 723 ret = iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC);
@@ -787,11 +779,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
787 if (vif->type != NL80211_IFTYPE_P2P_DEVICE) 779 if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
788 mvm->vif_count--; 780 mvm->vif_count--;
789 781
790 /* TODO: remove this when legacy PM will be discarded */
791 ieee80211_iterate_active_interfaces(
792 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
793 iwl_mvm_power_update_iterator, mvm);
794
795 iwl_mvm_mac_ctxt_release(mvm, vif); 782 iwl_mvm_mac_ctxt_release(mvm, vif);
796 out_unlock: 783 out_unlock:
797 mutex_unlock(&mvm->mutex); 784 mutex_unlock(&mvm->mutex);
@@ -880,11 +867,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
880 if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE) 867 if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)
881 mvm->vif_count--; 868 mvm->vif_count--;
882 869
883 /* TODO: remove this when legacy PM will be discarded */
884 ieee80211_iterate_active_interfaces(
885 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
886 iwl_mvm_power_update_iterator, mvm);
887
888 iwl_mvm_mac_ctxt_remove(mvm, vif); 870 iwl_mvm_mac_ctxt_remove(mvm, vif);
889 871
890out_release: 872out_release:
@@ -1237,15 +1219,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
1237 /* reset rssi values */ 1219 /* reset rssi values */
1238 mvmvif->bf_data.ave_beacon_signal = 0; 1220 mvmvif->bf_data.ave_beacon_signal = 0;
1239 1221
1240 if (!(mvm->fw->ucode_capa.flags &
1241 IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) {
1242 /* Workaround for FW bug, otherwise FW disables device
1243 * power save upon disassociation
1244 */
1245 ret = iwl_mvm_power_update_mode(mvm, vif);
1246 if (ret)
1247 IWL_ERR(mvm, "failed to update power mode\n");
1248 }
1249 iwl_mvm_bt_coex_vif_change(mvm); 1222 iwl_mvm_bt_coex_vif_change(mvm);
1250 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, 1223 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT,
1251 IEEE80211_SMPS_AUTOMATIC); 1224 IEEE80211_SMPS_AUTOMATIC);
@@ -1258,7 +1231,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
1258 &mvmvif->time_event_data); 1231 &mvmvif->time_event_data);
1259 } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | 1232 } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
1260 BSS_CHANGED_QOS)) { 1233 BSS_CHANGED_QOS)) {
1261 ret = iwl_mvm_power_update_mode(mvm, vif); 1234 ret = iwl_mvm_power_mac_update_mode(mvm, vif);
1262 if (ret) 1235 if (ret)
1263 IWL_ERR(mvm, "failed to update power mode\n"); 1236 IWL_ERR(mvm, "failed to update power mode\n");
1264 } 1237 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 2d76e228c1cb..0c12c322eb89 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -92,7 +92,6 @@ enum iwl_mvm_tx_fifo {
92}; 92};
93 93
94extern struct ieee80211_ops iwl_mvm_hw_ops; 94extern struct ieee80211_ops iwl_mvm_hw_ops;
95extern const struct iwl_mvm_power_ops pm_legacy_ops;
96extern const struct iwl_mvm_power_ops pm_mac_ops; 95extern const struct iwl_mvm_power_ops pm_mac_ops;
97 96
98/** 97/**
@@ -159,20 +158,6 @@ enum iwl_power_scheme {
159 IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) 158 IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
160#define IWL_UAPSD_MAX_SP IEEE80211_WMM_IE_STA_QOSINFO_SP_2 159#define IWL_UAPSD_MAX_SP IEEE80211_WMM_IE_STA_QOSINFO_SP_2
161 160
162struct iwl_mvm_power_ops {
163 int (*power_update_mode)(struct iwl_mvm *mvm,
164 struct ieee80211_vif *vif);
165 int (*power_update_device_mode)(struct iwl_mvm *mvm);
166 int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
167 void (*power_update_binding)(struct iwl_mvm *mvm,
168 struct ieee80211_vif *vif, bool assign);
169#ifdef CONFIG_IWLWIFI_DEBUGFS
170 int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
171 char *buf, int bufsz);
172#endif
173};
174
175
176#ifdef CONFIG_IWLWIFI_DEBUGFS 161#ifdef CONFIG_IWLWIFI_DEBUGFS
177enum iwl_dbgfs_pm_mask { 162enum iwl_dbgfs_pm_mask {
178 MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0), 163 MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0),
@@ -590,8 +575,6 @@ struct iwl_mvm {
590 struct iwl_mvm_tt_mgmt thermal_throttle; 575 struct iwl_mvm_tt_mgmt thermal_throttle;
591 s32 temperature; /* Celsius */ 576 s32 temperature; /* Celsius */
592 577
593 const struct iwl_mvm_power_ops *pm_ops;
594
595#ifdef CONFIG_NL80211_TESTMODE 578#ifdef CONFIG_NL80211_TESTMODE
596 u32 noa_duration; 579 u32 noa_duration;
597 struct ieee80211_vif *noa_vif; 580 struct ieee80211_vif *noa_vif;
@@ -826,48 +809,23 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
826/* rate scaling */ 809/* rate scaling */
827int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init); 810int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init);
828 811
829/* power managment */ 812/* power management */
830static inline int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, 813int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm);
831 struct ieee80211_vif *vif)
832{
833 return mvm->pm_ops->power_update_mode(mvm, vif);
834}
835 814
836static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm, 815int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
837 struct ieee80211_vif *vif) 816 struct ieee80211_vif *vif);
838{ 817int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
839 return mvm->pm_ops->power_disable(mvm, vif); 818int iwl_mvm_power_update_device(struct iwl_mvm *mvm);
840} 819void iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
841 820 struct ieee80211_vif *vif, bool assign);
842static inline int iwl_mvm_power_update_device_mode(struct iwl_mvm *mvm) 821int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
843{ 822 char *buf, int bufsz);
844 if (mvm->pm_ops->power_update_device_mode)
845 return mvm->pm_ops->power_update_device_mode(mvm);
846 return 0;
847}
848
849static inline void iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
850 struct ieee80211_vif *vif,
851 bool assign)
852{
853 if (mvm->pm_ops->power_update_binding)
854 mvm->pm_ops->power_update_binding(mvm, vif, assign);
855}
856 823
857void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 824void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
858int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, 825int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
859 struct iwl_rx_cmd_buffer *rxb, 826 struct iwl_rx_cmd_buffer *rxb,
860 struct iwl_device_cmd *cmd); 827 struct iwl_device_cmd *cmd);
861 828
862#ifdef CONFIG_IWLWIFI_DEBUGFS
863static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm,
864 struct ieee80211_vif *vif,
865 char *buf, int bufsz)
866{
867 return mvm->pm_ops->power_dbgfs_read(mvm, vif, buf, bufsz);
868}
869#endif
870
871int iwl_mvm_leds_init(struct iwl_mvm *mvm); 829int iwl_mvm_leds_init(struct iwl_mvm *mvm);
872void iwl_mvm_leds_exit(struct iwl_mvm *mvm); 830void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
873 831
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index e268c15e5fea..a46f0b8b0870 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -496,11 +496,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
496 if (err) 496 if (err)
497 goto out_unregister; 497 goto out_unregister;
498 498
499 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)
500 mvm->pm_ops = &pm_mac_ops;
501 else
502 mvm->pm_ops = &pm_legacy_ops;
503
504 memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx)); 499 memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
505 500
506 /* rpm starts with a taken ref. only set the appropriate bit here. */ 501 /* rpm starts with a taken ref. only set the appropriate bit here. */
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index ac6d2c86e75c..2eea5b374ece 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -439,14 +439,17 @@ static int _iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
439 sizeof(cmd), &cmd); 439 sizeof(cmd), &cmd);
440} 440}
441 441
442static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm, 442int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
443 struct ieee80211_vif *vif) 443 struct ieee80211_vif *vif)
444 444
445{ 445{
446 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 446 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
447 bool ba_enable; 447 bool ba_enable;
448 int ret; 448 int ret;
449 449
450 if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
451 return 0;
452
450 ret = _iwl_mvm_power_mac_update_mode(mvm, vif); 453 ret = _iwl_mvm_power_mac_update_mode(mvm, vif);
451 if (ret) 454 if (ret)
452 return ret; 455 return ret;
@@ -458,13 +461,15 @@ static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
458 return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); 461 return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
459} 462}
460 463
461static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm, 464int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
462 struct ieee80211_vif *vif)
463{ 465{
464 struct iwl_mac_power_cmd cmd = {}; 466 struct iwl_mac_power_cmd cmd = {};
465 struct iwl_mvm_vif *mvmvif __maybe_unused = 467 struct iwl_mvm_vif *mvmvif __maybe_unused =
466 iwl_mvm_vif_from_mac80211(vif); 468 iwl_mvm_vif_from_mac80211(vif);
467 469
470 if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
471 return 0;
472
468 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) 473 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
469 return 0; 474 return 0;
470 475
@@ -513,8 +518,11 @@ static int _iwl_mvm_power_update_device(struct iwl_mvm *mvm, bool force_disable)
513 &cmd); 518 &cmd);
514} 519}
515 520
516static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) 521int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
517{ 522{
523 if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
524 return 0;
525
518 return _iwl_mvm_power_update_device(mvm, false); 526 return _iwl_mvm_power_update_device(mvm, false);
519} 527}
520 528
@@ -577,9 +585,8 @@ static void iwl_mvm_power_binding_iterator(void *_data, u8 *mac,
577 WARN_ONCE(ret, "Failed to update power parameters on a specific vif\n"); 585 WARN_ONCE(ret, "Failed to update power parameters on a specific vif\n");
578} 586}
579 587
580static void _iwl_mvm_power_update_binding(struct iwl_mvm *mvm, 588void iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
581 struct ieee80211_vif *vif, 589 struct ieee80211_vif *vif, bool assign)
582 bool assign)
583{ 590{
584 bool ba_enable; 591 bool ba_enable;
585 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 592 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -589,6 +596,9 @@ static void _iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
589 596
590 lockdep_assert_held(&mvm->mutex); 597 lockdep_assert_held(&mvm->mutex);
591 598
599 if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
600 return;
601
592 if (vif->type == NL80211_IFTYPE_MONITOR) { 602 if (vif->type == NL80211_IFTYPE_MONITOR) {
593 int ret = _iwl_mvm_power_update_device(mvm, assign); 603 int ret = _iwl_mvm_power_update_device(mvm, assign);
594 mvm->ps_prevented = assign; 604 mvm->ps_prevented = assign;
@@ -615,14 +625,18 @@ static void _iwl_mvm_power_update_binding(struct iwl_mvm *mvm,
615} 625}
616 626
617#ifdef CONFIG_IWLWIFI_DEBUGFS 627#ifdef CONFIG_IWLWIFI_DEBUGFS
618static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, 628int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
619 struct ieee80211_vif *vif, char *buf, 629 struct ieee80211_vif *vif, char *buf,
620 int bufsz) 630 int bufsz)
621{ 631{
622 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 632 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
623 struct iwl_mac_power_cmd cmd = {}; 633 struct iwl_mac_power_cmd cmd = {};
624 int pos = 0; 634 int pos = 0;
625 635
636 if (WARN_ON(!(mvm->fw->ucode_capa.flags &
637 IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)))
638 return 0;
639
626 mutex_lock(&mvm->mutex); 640 mutex_lock(&mvm->mutex);
627 memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd)); 641 memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
628 mutex_unlock(&mvm->mutex); 642 mutex_unlock(&mvm->mutex);
@@ -863,12 +877,12 @@ int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
863 return iwl_mvm_enable_beacon_filter(mvm, vif, flags); 877 return iwl_mvm_enable_beacon_filter(mvm, vif, flags);
864} 878}
865 879
866const struct iwl_mvm_power_ops pm_mac_ops = { 880int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm)
867 .power_update_mode = iwl_mvm_power_mac_update_mode, 881{
868 .power_update_device_mode = iwl_mvm_power_update_device, 882 struct iwl_powertable_cmd cmd = {
869 .power_disable = iwl_mvm_power_mac_disable, 883 .keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC,
870 .power_update_binding = _iwl_mvm_power_update_binding, 884 };
871#ifdef CONFIG_IWLWIFI_DEBUGFS 885
872 .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read, 886 return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
873#endif 887 sizeof(cmd), &cmd);
874}; 888}
diff --git a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
deleted file mode 100644
index ef712ae5bc62..000000000000
--- a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
+++ /dev/null
@@ -1,319 +0,0 @@
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 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22 * USA
23 *
24 * The full GNU General Public License is included in this distribution
25 * in the file called COPYING.
26 *
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 *
31 * BSD LICENSE
32 *
33 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
45 * distribution.
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *
62 *****************************************************************************/
63
64#include <linux/kernel.h>
65#include <linux/module.h>
66#include <linux/slab.h>
67#include <linux/init.h>
68
69#include <net/mac80211.h>
70
71#include "iwl-debug.h"
72#include "mvm.h"
73#include "iwl-modparams.h"
74#include "fw-api-power.h"
75
76#define POWER_KEEP_ALIVE_PERIOD_SEC 25
77
78static void iwl_mvm_power_log(struct iwl_mvm *mvm,
79 struct iwl_powertable_cmd *cmd)
80{
81 IWL_DEBUG_POWER(mvm,
82 "Sending power table command for power level %d, flags = 0x%X\n",
83 iwlmvm_mod_params.power_scheme,
84 le16_to_cpu(cmd->flags));
85 IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
86
87 if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
88 IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
89 le32_to_cpu(cmd->rx_data_timeout));
90 IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
91 le32_to_cpu(cmd->tx_data_timeout));
92 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
93 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
94 le32_to_cpu(cmd->skip_dtim_periods));
95 if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
96 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
97 le32_to_cpu(cmd->lprx_rssi_threshold));
98 }
99}
100
101static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
102 struct ieee80211_vif *vif,
103 struct iwl_powertable_cmd *cmd)
104{
105 struct ieee80211_hw *hw = mvm->hw;
106 struct ieee80211_chanctx_conf *chanctx_conf;
107 struct ieee80211_channel *chan;
108 int dtimper, dtimper_msec;
109 int keep_alive;
110 bool radar_detect = false;
111 struct iwl_mvm_vif *mvmvif __maybe_unused =
112 iwl_mvm_vif_from_mac80211(vif);
113
114 /*
115 * Regardless of power management state the driver must set
116 * keep alive period. FW will use it for sending keep alive NDPs
117 * immediately after association.
118 */
119 cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
120
121 if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
122 return;
123
124 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
125 if (!vif->bss_conf.assoc)
126 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
127
128#ifdef CONFIG_IWLWIFI_DEBUGFS
129 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
130 mvmvif->dbgfs_pm.disable_power_off)
131 cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
132#endif
133 if (!vif->bss_conf.ps)
134 return;
135
136 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
137
138 if (vif->bss_conf.beacon_rate &&
139 (vif->bss_conf.beacon_rate->bitrate == 10 ||
140 vif->bss_conf.beacon_rate->bitrate == 60)) {
141 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
142 cmd->lprx_rssi_threshold =
143 cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
144 }
145
146 dtimper = hw->conf.ps_dtim_period ?: 1;
147
148 /* Check if radar detection is required on current channel */
149 rcu_read_lock();
150 chanctx_conf = rcu_dereference(vif->chanctx_conf);
151 WARN_ON(!chanctx_conf);
152 if (chanctx_conf) {
153 chan = chanctx_conf->def.chan;
154 radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
155 }
156 rcu_read_unlock();
157
158 /* Check skip over DTIM conditions */
159 if (!radar_detect && (dtimper <= 10) &&
160 (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
161 mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
162 cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
163 cmd->skip_dtim_periods = cpu_to_le32(3);
164 }
165
166 /* Check that keep alive period is at least 3 * DTIM */
167 dtimper_msec = dtimper * vif->bss_conf.beacon_int;
168 keep_alive = max_t(int, 3 * dtimper_msec,
169 MSEC_PER_SEC * cmd->keep_alive_seconds);
170 keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
171 cmd->keep_alive_seconds = keep_alive;
172
173 if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
174 cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
175 cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
176 } else {
177 cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
178 cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
179 }
180
181#ifdef CONFIG_IWLWIFI_DEBUGFS
182 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
183 cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds;
184 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
185 if (mvmvif->dbgfs_pm.skip_over_dtim)
186 cmd->flags |=
187 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
188 else
189 cmd->flags &=
190 cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
191 }
192 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
193 cmd->rx_data_timeout =
194 cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
195 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
196 cmd->tx_data_timeout =
197 cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
198 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
199 cmd->skip_dtim_periods =
200 cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
201 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
202 if (mvmvif->dbgfs_pm.lprx_ena)
203 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
204 else
205 cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
206 }
207 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
208 cmd->lprx_rssi_threshold =
209 cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
210#endif /* CONFIG_IWLWIFI_DEBUGFS */
211}
212
213static int iwl_mvm_power_legacy_update_mode(struct iwl_mvm *mvm,
214 struct ieee80211_vif *vif)
215{
216 int ret;
217 bool ba_enable;
218 struct iwl_powertable_cmd cmd = {};
219
220 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
221 return 0;
222
223 /*
224 * TODO: The following vif_count verification is temporary condition.
225 * Avoid power mode update if more than one interface is currently
226 * active. Remove this condition when FW will support power management
227 * on multiple MACs.
228 */
229 IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n",
230 mvm->vif_count);
231 if (mvm->vif_count > 1)
232 return 0;
233
234 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
235 iwl_mvm_power_log(mvm, &cmd);
236
237 ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
238 sizeof(cmd), &cmd);
239 if (ret)
240 return ret;
241
242 ba_enable = !!(cmd.flags &
243 cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
244
245 return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
246}
247
248static int iwl_mvm_power_legacy_disable(struct iwl_mvm *mvm,
249 struct ieee80211_vif *vif)
250{
251 struct iwl_powertable_cmd cmd = {};
252 struct iwl_mvm_vif *mvmvif __maybe_unused =
253 iwl_mvm_vif_from_mac80211(vif);
254
255 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
256 return 0;
257
258 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
259 cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
260
261#ifdef CONFIG_IWLWIFI_DEBUGFS
262 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
263 mvmvif->dbgfs_pm.disable_power_off)
264 cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
265#endif
266 iwl_mvm_power_log(mvm, &cmd);
267
268 return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
269 sizeof(cmd), &cmd);
270}
271
272#ifdef CONFIG_IWLWIFI_DEBUGFS
273static int iwl_mvm_power_legacy_dbgfs_read(struct iwl_mvm *mvm,
274 struct ieee80211_vif *vif, char *buf,
275 int bufsz)
276{
277 struct iwl_powertable_cmd cmd = {};
278 int pos = 0;
279
280 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
281
282 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
283 (cmd.flags &
284 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
285 0 : 1);
286 pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
287 le32_to_cpu(cmd.skip_dtim_periods));
288 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
289 iwlmvm_mod_params.power_scheme);
290 pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
291 le16_to_cpu(cmd.flags));
292 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
293 cmd.keep_alive_seconds);
294
295 if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
296 pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
297 (cmd.flags &
298 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
299 1 : 0);
300 pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
301 le32_to_cpu(cmd.rx_data_timeout));
302 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
303 le32_to_cpu(cmd.tx_data_timeout));
304 if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
305 pos += scnprintf(buf+pos, bufsz-pos,
306 "lprx_rssi_threshold = %d\n",
307 le32_to_cpu(cmd.lprx_rssi_threshold));
308 }
309 return pos;
310}
311#endif
312
313const struct iwl_mvm_power_ops pm_legacy_ops = {
314 .power_update_mode = iwl_mvm_power_legacy_update_mode,
315 .power_disable = iwl_mvm_power_legacy_disable,
316#ifdef CONFIG_IWLWIFI_DEBUGFS
317 .power_dbgfs_read = iwl_mvm_power_legacy_dbgfs_read,
318#endif
319};
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index b2162328ac96..d4d901068e90 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -564,5 +564,5 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
564 564
565 iwl_mvm_bt_coex_vif_change(mvm); 565 iwl_mvm_bt_coex_vif_change(mvm);
566 566
567 return iwl_mvm_power_update_mode(mvm, vif); 567 return iwl_mvm_power_mac_update_mode(mvm, vif);
568} 568}