iwlwifi: mvm: don't ask for beacons when AP vif and no assoc sta
authorGregory Greenman <gregory.greenman@intel.com>
Mon, 24 Aug 2015 11:38:35 +0000 (14:38 +0300)
committerLuciano Coelho <luciano.coelho@intel.com>
Fri, 28 Aug 2015 10:26:34 +0000 (13:26 +0300)
When in AP mode, we need beacons from other APs for HT protection.
However, when there's no any associated station we will not do
any Tx and thus don't really need beacons. On the other hand, these
beacons will cause a lot of unnecessary wakeups which increase our
power consumption. Handle this by asking FW to pass beacons only when
there's at least one associated station.

Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/sta.c

index 3424315dd876de13f9a64da6b7703f51103ce87e..5af0090ffb6e0f60d3a8db5675936f3f94f3e4f3 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -33,6 +34,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015 Intel Deutschland GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -1124,10 +1126,11 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
        ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id);
 }
 
-static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
-                                  struct ieee80211_vif *vif,
-                                  u32 action)
+int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
+                           struct ieee80211_vif *vif,
+                           u32 action)
 {
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mac_ctx_cmd cmd = {};
 
        WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p);
@@ -1137,10 +1140,16 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
 
        /*
         * pass probe requests and beacons from other APs (needed
-        * for ht protection)
+        * for ht protection); when there're no any associated station
+        * don't ask FW to pass beacons to prevent unnecessary wake-ups.
         */
-       cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
-                                       MAC_FILTER_IN_BEACON);
+       cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
+       if (mvmvif->ap_assoc_sta_count) {
+               cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
+               IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
+       } else {
+               IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
+       }
 
        /* Fill the data specific for ap mode */
        iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
index aa8c2b7f23c73862f0526f109ad647cc0c80a259..f9f88e913e03a41f3faa99701f778b8f454aa0d9 100644 (file)
@@ -2319,6 +2319,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
        if (vif->type == NL80211_IFTYPE_AP)
                iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
 
+       mvmvif->ap_assoc_sta_count = 0;
+
        /* Add the mac context */
        ret = iwl_mvm_mac_ctxt_add(mvm, vif);
        if (ret)
@@ -2613,6 +2615,7 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
                                       struct ieee80211_sta *sta)
 {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
 
        /*
@@ -2627,6 +2630,12 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
        if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id]))
                rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
                                   ERR_PTR(-ENOENT));
+
+       if (mvm_sta->vif->type == NL80211_IFTYPE_AP) {
+               mvmvif->ap_assoc_sta_count--;
+               iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, FW_CTXT_ACTION_MODIFY);
+       }
+
        mutex_unlock(&mvm->mutex);
 }
 
index 72cd67eab06ff78833eb96577d779b18eeb9c9b2..ed9b0cc14edd03578c66b3a332812b9cbded884d 100644 (file)
@@ -338,6 +338,8 @@ struct iwl_mvm_vif_bf_data {
  * @bssid: BSSID for this (client) interface
  * @associated: indicates that we're currently associated, used only for
  *     managing the firmware state in iwl_mvm_bss_info_changed_station()
+ * @ap_assoc_sta_count: count of stations associated to us - valid only
+ *     if VIF type is AP
  * @uploaded: indicates the MAC context has been added to the device
  * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface
  *     should get quota etc.
@@ -367,6 +369,7 @@ struct iwl_mvm_vif {
 
        u8 bssid[ETH_ALEN];
        bool associated;
+       u8 ap_assoc_sta_count;
 
        bool uploaded;
        bool ap_ibss_active;
@@ -1131,6 +1134,9 @@ void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
                                    struct ieee80211_vif *vif);
 unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
                                         struct ieee80211_vif *exclude_vif);
+int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
+                           struct ieee80211_vif *vif,
+                           u32 action);
 
 /* Bindings */
 int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
index df216cd0c98f4659d1c00d7d07c8adb31c8244c6..fe2f53850d36f6b306b0d543fb8a26ed8777a79e 100644 (file)
@@ -275,6 +275,11 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
        if (sta_id == IWL_MVM_STATION_COUNT)
                return -ENOSPC;
 
+       if (vif->type == NL80211_IFTYPE_AP) {
+               mvmvif->ap_assoc_sta_count++;
+               iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, FW_CTXT_ACTION_MODIFY);
+       }
+
        spin_lock_init(&mvm_sta->lock);
 
        mvm_sta->sta_id = sta_id;