summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bondar <alexander.bondar@intel.com>2013-05-06 13:03:59 +0300
committerJohannes Berg <johannes.berg@intel.com>2013-05-27 13:30:10 +0200
commit071d4990fd9fe6fe27b47f1587ba11db3111c3fd (patch)
tree04142cd9b8d05e6911f23134859b789647949d2b
parent129219c0fd234164ebc19e8694641927317eda13 (diff)
downloadlinux-stable-071d4990fd9fe6fe27b47f1587ba11db3111c3fd.tar.gz
linux-stable-071d4990fd9fe6fe27b47f1587ba11db3111c3fd.tar.bz2
linux-stable-071d4990fd9fe6fe27b47f1587ba11db3111c3fd.zip
iwlwifi: mvm: Add beacon abort enablement
Beacon abort is used by device to increase idle dwell time when system is idle. This algorithm is on top of beacon filtering feature. Enable beacon abort only if power management is enabled. Signed-off-by: Alexander Bondar <alexander.bondar@intel.com> Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h9
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c121
3 files changed, 86 insertions, 46 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index 05e51927b848..b6bdfd36bebe 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -193,4 +193,13 @@ struct iwl_beacon_filter_cmd {
#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
+#define IWL_BF_CMD_CONFIG_DEFAULTS \
+ .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, \
+ .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, \
+ .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, \
+ .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, \
+ .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, \
+ .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \
+ .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT)
+
#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 712c39ae748f..02ba8303a09f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -173,6 +173,8 @@ struct iwl_mvm_vif {
bool uploaded;
bool ap_active;
bool monitor_active;
+ /* indicate whether beacon filtering is enabled */
+ bool bf_enabled;
u32 ap_beacon_time;
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index f5bdfb71c790..c818d6d6aee6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -75,6 +75,53 @@
#define POWER_KEEP_ALIVE_PERIOD_SEC 25
+static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
+ struct iwl_beacon_filter_cmd *cmd)
+{
+ int ret;
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, CMD_SYNC,
+ sizeof(struct iwl_beacon_filter_cmd), cmd);
+
+ if (!ret) {
+ IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
+ cmd->ba_enable_beacon_abort);
+ IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
+ cmd->ba_escape_timer);
+ IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
+ cmd->bf_debug_flag);
+ IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
+ cmd->bf_enable_beacon_filter);
+ IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
+ cmd->bf_energy_delta);
+ IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
+ cmd->bf_escape_timer);
+ IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
+ cmd->bf_roaming_energy_delta);
+ IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
+ cmd->bf_roaming_state);
+ IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n",
+ cmd->bf_temperature_delta);
+ }
+ return ret;
+}
+
+static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif, bool enable)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_beacon_filter_cmd cmd = {
+ IWL_BF_CMD_CONFIG_DEFAULTS,
+ .bf_enable_beacon_filter = 1,
+ .ba_enable_beacon_abort = enable,
+ };
+
+ if (!mvmvif->bf_enabled)
+ return 0;
+
+ return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
+}
+
static void iwl_mvm_power_log(struct iwl_mvm *mvm,
struct iwl_powertable_cmd *cmd)
{
@@ -162,6 +209,8 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
+ int ret;
+ bool ba_enable;
struct iwl_powertable_cmd cmd = {};
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
@@ -170,8 +219,15 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
iwl_mvm_power_log(mvm, &cmd);
- return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
- sizeof(cmd), &cmd);
+ ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
+ sizeof(cmd), &cmd);
+ if (ret)
+ return ret;
+
+ ba_enable = !!(cmd.flags &
+ cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
+
+ return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
}
int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -190,69 +246,42 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
sizeof(cmd), &cmd);
}
-static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
- struct iwl_beacon_filter_cmd *cmd)
-{
- int ret;
-
- ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, CMD_SYNC,
- sizeof(struct iwl_beacon_filter_cmd), cmd);
-
- if (!ret) {
- IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
- cmd->ba_enable_beacon_abort);
- IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
- cmd->ba_escape_timer);
- IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
- cmd->bf_debug_flag);
- IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
- cmd->bf_enable_beacon_filter);
- IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
- cmd->bf_energy_delta);
- IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
- cmd->bf_escape_timer);
- IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
- cmd->bf_roaming_energy_delta);
- IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
- cmd->bf_roaming_state);
- IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n",
- cmd->bf_temperature_delta);
- }
- return ret;
-}
-
int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_beacon_filter_cmd cmd = {
+ IWL_BF_CMD_CONFIG_DEFAULTS,
.bf_enable_beacon_filter = 1,
- .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT,
- .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT,
- .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT,
- .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT,
- .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT,
- .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),
- .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT),
- .ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT,
};
+ int ret;
if (mvmvif != mvm->bf_allowed_vif ||
vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0;
- return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
+ ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
+
+ if (!ret)
+ mvmvif->bf_enabled = true;
+
+ return ret;
}
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
- struct iwl_beacon_filter_cmd cmd = {
- .bf_enable_beacon_filter = 0,
- };
+ struct iwl_beacon_filter_cmd cmd = {};
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int ret;
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0;
- return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
+ ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
+
+ if (!ret)
+ mvmvif->bf_enabled = false;
+
+ return ret;
}