diff options
author | Alexander Bondar <alexander.bondar@intel.com> | 2013-10-23 05:50:34 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2013-12-17 12:39:42 -0500 |
commit | 92d8556250c81bd6d4df522926a2cb3711dd01e2 (patch) | |
tree | 5c1dcec1aa2344f2dc7299e713371f59508d2db3 /drivers/net/wireless/iwlwifi | |
parent | 1c2abf724b3397830e60596a6a41e2d9f870d1a6 (diff) |
iwlwifi: mvm: Disable power save for monitor interface
When monitor interface is activated device power save needs
to be disabled.
Re-consider power management status on other active
interfaces when monitor interface is bound or unbound.
Signed-off-by: Alexander Bondar <alexander.bondar@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/power.c | 22 |
3 files changed, 35 insertions, 12 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index e1c379a61d83..d36105fa4bf6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -1610,7 +1610,13 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
1610 | goto out_unlock; | 1610 | goto out_unlock; |
1611 | 1611 | ||
1612 | /* | 1612 | /* |
1613 | * Setting the quota at this stage is only required for monitor | 1613 | * Power state must be updated before quotas, |
1614 | * otherwise fw will complain. | ||
1615 | */ | ||
1616 | mvm->bound_vif_cnt++; | ||
1617 | iwl_mvm_power_update_binding(mvm, vif, true); | ||
1618 | |||
1619 | /* Setting the quota at this stage is only required for monitor | ||
1614 | * interfaces. For the other types, the bss_info changed flow | 1620 | * interfaces. For the other types, the bss_info changed flow |
1615 | * will handle quota settings. | 1621 | * will handle quota settings. |
1616 | */ | 1622 | */ |
@@ -1621,13 +1627,12 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
1621 | goto out_remove_binding; | 1627 | goto out_remove_binding; |
1622 | } | 1628 | } |
1623 | 1629 | ||
1624 | mvm->bound_vif_cnt++; | ||
1625 | iwl_mvm_power_update_binding(mvm, vif); | ||
1626 | |||
1627 | goto out_unlock; | 1630 | goto out_unlock; |
1628 | 1631 | ||
1629 | out_remove_binding: | 1632 | out_remove_binding: |
1630 | iwl_mvm_binding_remove_vif(mvm, vif); | 1633 | iwl_mvm_binding_remove_vif(mvm, vif); |
1634 | mvm->bound_vif_cnt--; | ||
1635 | iwl_mvm_power_update_binding(mvm, vif, false); | ||
1631 | out_unlock: | 1636 | out_unlock: |
1632 | mutex_unlock(&mvm->mutex); | 1637 | mutex_unlock(&mvm->mutex); |
1633 | if (ret) | 1638 | if (ret) |
@@ -1662,7 +1667,7 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
1662 | out_unlock: | 1667 | out_unlock: |
1663 | mvmvif->phy_ctxt = NULL; | 1668 | mvmvif->phy_ctxt = NULL; |
1664 | mvm->bound_vif_cnt--; | 1669 | mvm->bound_vif_cnt--; |
1665 | iwl_mvm_power_update_binding(mvm, vif); | 1670 | iwl_mvm_power_update_binding(mvm, vif, false); |
1666 | 1671 | ||
1667 | mutex_unlock(&mvm->mutex); | 1672 | mutex_unlock(&mvm->mutex); |
1668 | } | 1673 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 51b0e9a4883f..7295f8e42f3e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -164,7 +164,7 @@ struct iwl_mvm_power_ops { | |||
164 | int (*power_update_device_mode)(struct iwl_mvm *mvm); | 164 | int (*power_update_device_mode)(struct iwl_mvm *mvm); |
165 | int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 165 | int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
166 | void (*power_update_binding)(struct iwl_mvm *mvm, | 166 | void (*power_update_binding)(struct iwl_mvm *mvm, |
167 | struct ieee80211_vif *vif); | 167 | struct ieee80211_vif *vif, bool assign); |
168 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 168 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
169 | int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 169 | int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
170 | char *buf, int bufsz); | 170 | char *buf, int bufsz); |
@@ -568,6 +568,9 @@ struct iwl_mvm { | |||
568 | u8 last_agg_queue; | 568 | u8 last_agg_queue; |
569 | 569 | ||
570 | u8 bound_vif_cnt; | 570 | u8 bound_vif_cnt; |
571 | |||
572 | /* Indicate if device power save is allowed */ | ||
573 | bool ps_prevented; | ||
571 | }; | 574 | }; |
572 | 575 | ||
573 | /* Extract MVM priv from op_mode and _hw */ | 576 | /* Extract MVM priv from op_mode and _hw */ |
@@ -787,10 +790,11 @@ static inline int iwl_mvm_power_update_device_mode(struct iwl_mvm *mvm) | |||
787 | } | 790 | } |
788 | 791 | ||
789 | static inline void iwl_mvm_power_update_binding(struct iwl_mvm *mvm, | 792 | static inline void iwl_mvm_power_update_binding(struct iwl_mvm *mvm, |
790 | struct ieee80211_vif *vif) | 793 | struct ieee80211_vif *vif, |
794 | bool assign) | ||
791 | { | 795 | { |
792 | if (mvm->pm_ops->power_update_binding) | 796 | if (mvm->pm_ops->power_update_binding) |
793 | mvm->pm_ops->power_update_binding(mvm, vif); | 797 | mvm->pm_ops->power_update_binding(mvm, vif, assign); |
794 | } | 798 | } |
795 | 799 | ||
796 | void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 800 | void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index d5d4935bc0e9..cfed105b28b2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -301,7 +301,8 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
301 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); | 301 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); |
302 | cmd->keep_alive_seconds = cpu_to_le16(keep_alive); | 302 | cmd->keep_alive_seconds = cpu_to_le16(keep_alive); |
303 | 303 | ||
304 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | 304 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM || |
305 | mvm->ps_prevented) | ||
305 | return; | 306 | return; |
306 | 307 | ||
307 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 308 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
@@ -447,7 +448,7 @@ static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm, | |||
447 | sizeof(cmd), &cmd); | 448 | sizeof(cmd), &cmd); |
448 | } | 449 | } |
449 | 450 | ||
450 | static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | 451 | static int _iwl_mvm_power_update_device(struct iwl_mvm *mvm, bool force_disable) |
451 | { | 452 | { |
452 | struct iwl_device_power_cmd cmd = { | 453 | struct iwl_device_power_cmd cmd = { |
453 | .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), | 454 | .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), |
@@ -456,7 +457,8 @@ static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | |||
456 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) | 457 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) |
457 | return 0; | 458 | return 0; |
458 | 459 | ||
459 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | 460 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM || |
461 | force_disable) | ||
460 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK); | 462 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK); |
461 | 463 | ||
462 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 464 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -473,6 +475,11 @@ static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | |||
473 | &cmd); | 475 | &cmd); |
474 | } | 476 | } |
475 | 477 | ||
478 | static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | ||
479 | { | ||
480 | return _iwl_mvm_power_update_device(mvm, false); | ||
481 | } | ||
482 | |||
476 | void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 483 | void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
477 | { | 484 | { |
478 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 485 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
@@ -525,8 +532,15 @@ static void iwl_mvm_power_binding_iterator(void *_data, u8 *mac, | |||
525 | } | 532 | } |
526 | 533 | ||
527 | static void _iwl_mvm_power_update_binding(struct iwl_mvm *mvm, | 534 | static void _iwl_mvm_power_update_binding(struct iwl_mvm *mvm, |
528 | struct ieee80211_vif *vif) | 535 | struct ieee80211_vif *vif, |
536 | bool assign) | ||
529 | { | 537 | { |
538 | if (vif->type == NL80211_IFTYPE_MONITOR) { | ||
539 | int ret = _iwl_mvm_power_update_device(mvm, assign); | ||
540 | mvm->ps_prevented = assign; | ||
541 | WARN_ONCE(ret, "Failed to update power device state\n"); | ||
542 | } | ||
543 | |||
530 | ieee80211_iterate_active_interfaces(mvm->hw, | 544 | ieee80211_iterate_active_interfaces(mvm->hw, |
531 | IEEE80211_IFACE_ITER_NORMAL, | 545 | IEEE80211_IFACE_ITER_NORMAL, |
532 | iwl_mvm_power_binding_iterator, | 546 | iwl_mvm_power_binding_iterator, |