mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
iwlwifi: mvm: Add beacon filtering support
Add iwl_beacon_filter_cmd struct, disable and enable beacon filtering as needed. Signed-off-by: Hila Gonen <hila.gonen@intel.com> Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
bd5f6a344d
commit
7df15b1e6f
|
|
@ -117,4 +117,80 @@ struct iwl_powertable_cmd {
|
|||
__le32 lprx_rssi_threshold;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_beacon_filter_cmd
|
||||
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
|
||||
* @id_and_color: MAC contex identifier
|
||||
* @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon
|
||||
* to driver if delta in Energy values calculated for this and last
|
||||
* passed beacon is greater than this threshold. Zero value means that
|
||||
* the Energy change is ignored for beacon filtering, and beacon will
|
||||
* not be forced to be sent to driver regardless of this delta. Typical
|
||||
* energy delta 5dB.
|
||||
* @bf_roaming_energy_delta: Used for RSSI filtering, if in 'roaming' state.
|
||||
* Send beacon to driver if delta in Energy values calculated for this
|
||||
* and last passed beacon is greater than this threshold. Zero value
|
||||
* means that the Energy change is ignored for beacon filtering while in
|
||||
* Roaming state, typical energy delta 1dB.
|
||||
* @bf_roaming_state: Used for RSSI filtering. If absolute Energy values
|
||||
* calculated for current beacon is less than the threshold, use
|
||||
* Roaming Energy Delta Threshold, otherwise use normal Energy Delta
|
||||
* Threshold. Typical energy threshold is -72dBm.
|
||||
* @bf_temperature_delta: Send Beacon to driver if delta in temperature values
|
||||
* calculated for this and the last passed beacon is greater than this
|
||||
* threshold. Zero value means that the temperature changeis ignored for
|
||||
* beacon filtering; beacons will not be forced to be sent to driver
|
||||
* regardless of whether its temerature has been changed.
|
||||
* @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
|
||||
* @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed
|
||||
* for a specific period of time. Units: Beacons.
|
||||
* @ba_escape_timer: Fully receive and parse beacon if no beacons were passed
|
||||
* for a longer period of time then this escape-timeout. Units: Beacons.
|
||||
* @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
|
||||
*/
|
||||
struct iwl_beacon_filter_cmd {
|
||||
u8 bf_energy_delta;
|
||||
u8 bf_roaming_energy_delta;
|
||||
u8 bf_roaming_state;
|
||||
u8 bf_temperature_delta;
|
||||
u8 bf_enable_beacon_filter;
|
||||
u8 bf_debug_flag;
|
||||
__le16 reserved1;
|
||||
__le32 bf_escape_timer;
|
||||
__le32 ba_escape_timer;
|
||||
u8 ba_enable_beacon_abort;
|
||||
u8 reserved2[3];
|
||||
} __packed;
|
||||
|
||||
/* Beacon filtering and beacon abort */
|
||||
#define IWL_BF_ENERGY_DELTA_DEFAULT 5
|
||||
#define IWL_BF_ENERGY_DELTA_MAX 255
|
||||
#define IWL_BF_ENERGY_DELTA_MIN 0
|
||||
|
||||
#define IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT 1
|
||||
#define IWL_BF_ROAMING_ENERGY_DELTA_MAX 255
|
||||
#define IWL_BF_ROAMING_ENERGY_DELTA_MIN 0
|
||||
|
||||
#define IWL_BF_ROAMING_STATE_DEFAULT 72
|
||||
#define IWL_BF_ROAMING_STATE_MAX 255
|
||||
#define IWL_BF_ROAMING_STATE_MIN 0
|
||||
|
||||
#define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5
|
||||
#define IWL_BF_TEMPERATURE_DELTA_MAX 255
|
||||
#define IWL_BF_TEMPERATURE_DELTA_MIN 0
|
||||
|
||||
#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1
|
||||
|
||||
#define IWL_BF_DEBUG_FLAG_DEFAULT 0
|
||||
|
||||
#define IWL_BF_ESCAPE_TIMER_DEFAULT 50
|
||||
#define IWL_BF_ESCAPE_TIMER_MAX 1024
|
||||
#define IWL_BF_ESCAPE_TIMER_MIN 0
|
||||
|
||||
#define IWL_BA_ESCAPE_TIMER_DEFAULT 3
|
||||
#define IWL_BA_ESCAPE_TIMER_MAX 1024
|
||||
#define IWL_BA_ESCAPE_TIMER_MIN 0
|
||||
|
||||
#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -170,6 +170,8 @@ enum {
|
|||
BT_COEX_PROT_ENV = 0xcd,
|
||||
BT_PROFILE_NOTIFICATION = 0xce,
|
||||
|
||||
REPLY_BEACON_FILTERING_CMD = 0xd2,
|
||||
|
||||
REPLY_DEBUG_CMD = 0xf0,
|
||||
DEBUG_LOG_MSG = 0xf7,
|
||||
|
||||
|
|
|
|||
|
|
@ -530,6 +530,17 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
*/
|
||||
iwl_mvm_power_update_mode(mvm, vif);
|
||||
|
||||
/* beacon filtering */
|
||||
if (!mvm->bf_allowed_vif &&
|
||||
vif->type == NL80211_IFTYPE_STATION && !vif->p2p){
|
||||
mvm->bf_allowed_vif = mvmvif;
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_disable_beacon_filter(mvm, vif);
|
||||
if (ret)
|
||||
goto out_release;
|
||||
|
||||
/*
|
||||
* P2P_DEVICE interface does not have a channel context assigned to it,
|
||||
* so a dedicated PHY context is allocated to it and the corresponding
|
||||
|
|
@ -646,6 +657,11 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
if (mvm->bf_allowed_vif == mvmvif) {
|
||||
mvm->bf_allowed_vif = NULL;
|
||||
vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
|
||||
}
|
||||
|
||||
iwl_mvm_vif_dbgfs_clean(mvm, vif);
|
||||
|
||||
/*
|
||||
|
|
@ -984,9 +1000,13 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
mvmvif->phy_ctxt->channel->band);
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
/* enable beacon filtering */
|
||||
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif));
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
/* disable beacon filtering */
|
||||
WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif));
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTH) {
|
||||
|
|
|
|||
|
|
@ -266,6 +266,12 @@ struct iwl_mvm {
|
|||
|
||||
unsigned long status;
|
||||
|
||||
/*
|
||||
* for beacon filtering -
|
||||
* currently only one interface can be supported
|
||||
*/
|
||||
struct iwl_mvm_vif *bf_allowed_vif;
|
||||
|
||||
enum iwl_ucode_type cur_ucode;
|
||||
bool ucode_loaded;
|
||||
bool init_ucode_run;
|
||||
|
|
@ -533,4 +539,10 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
enum ieee80211_rssi_event rssi_event);
|
||||
void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
||||
/* beacon filtering */
|
||||
int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
#endif /* __IWL_MVM_H__ */
|
||||
|
|
|
|||
|
|
@ -292,6 +292,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
|
|||
CMD(BT_COEX_PROT_ENV),
|
||||
CMD(BT_PROFILE_NOTIFICATION),
|
||||
CMD(BT_CONFIG),
|
||||
CMD(REPLY_BEACON_FILTERING_CMD),
|
||||
};
|
||||
#undef CMD
|
||||
|
||||
|
|
|
|||
|
|
@ -178,3 +178,70 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
|
||||
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 = {
|
||||
.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,
|
||||
};
|
||||
|
||||
if (mvmvif != mvm->bf_allowed_vif ||
|
||||
vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
||||
return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
|
||||
return 0;
|
||||
|
||||
return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user