aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h76
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c20
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h12
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c1
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c67
6 files changed, 178 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index 81fe45f46be7..90fdfcda15b6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -117,4 +117,80 @@ struct iwl_powertable_cmd {
117 __le32 lprx_rssi_threshold; 117 __le32 lprx_rssi_threshold;
118} __packed; 118} __packed;
119 119
120/**
121 * struct iwl_beacon_filter_cmd
122 * REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
123 * @id_and_color: MAC contex identifier
124 * @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon
125 * to driver if delta in Energy values calculated for this and last
126 * passed beacon is greater than this threshold. Zero value means that
127 * the Energy change is ignored for beacon filtering, and beacon will
128 * not be forced to be sent to driver regardless of this delta. Typical
129 * energy delta 5dB.
130 * @bf_roaming_energy_delta: Used for RSSI filtering, if in 'roaming' state.
131 * Send beacon to driver if delta in Energy values calculated for this
132 * and last passed beacon is greater than this threshold. Zero value
133 * means that the Energy change is ignored for beacon filtering while in
134 * Roaming state, typical energy delta 1dB.
135 * @bf_roaming_state: Used for RSSI filtering. If absolute Energy values
136 * calculated for current beacon is less than the threshold, use
137 * Roaming Energy Delta Threshold, otherwise use normal Energy Delta
138 * Threshold. Typical energy threshold is -72dBm.
139 * @bf_temperature_delta: Send Beacon to driver if delta in temperature values
140 * calculated for this and the last passed beacon is greater than this
141 * threshold. Zero value means that the temperature changeis ignored for
142 * beacon filtering; beacons will not be forced to be sent to driver
143 * regardless of whether its temerature has been changed.
144 * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
145 * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed
146 * for a specific period of time. Units: Beacons.
147 * @ba_escape_timer: Fully receive and parse beacon if no beacons were passed
148 * for a longer period of time then this escape-timeout. Units: Beacons.
149 * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
150 */
151struct iwl_beacon_filter_cmd {
152 u8 bf_energy_delta;
153 u8 bf_roaming_energy_delta;
154 u8 bf_roaming_state;
155 u8 bf_temperature_delta;
156 u8 bf_enable_beacon_filter;
157 u8 bf_debug_flag;
158 __le16 reserved1;
159 __le32 bf_escape_timer;
160 __le32 ba_escape_timer;
161 u8 ba_enable_beacon_abort;
162 u8 reserved2[3];
163} __packed;
164
165/* Beacon filtering and beacon abort */
166#define IWL_BF_ENERGY_DELTA_DEFAULT 5
167#define IWL_BF_ENERGY_DELTA_MAX 255
168#define IWL_BF_ENERGY_DELTA_MIN 0
169
170#define IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT 1
171#define IWL_BF_ROAMING_ENERGY_DELTA_MAX 255
172#define IWL_BF_ROAMING_ENERGY_DELTA_MIN 0
173
174#define IWL_BF_ROAMING_STATE_DEFAULT 72
175#define IWL_BF_ROAMING_STATE_MAX 255
176#define IWL_BF_ROAMING_STATE_MIN 0
177
178#define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5
179#define IWL_BF_TEMPERATURE_DELTA_MAX 255
180#define IWL_BF_TEMPERATURE_DELTA_MIN 0
181
182#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1
183
184#define IWL_BF_DEBUG_FLAG_DEFAULT 0
185
186#define IWL_BF_ESCAPE_TIMER_DEFAULT 50
187#define IWL_BF_ESCAPE_TIMER_MAX 1024
188#define IWL_BF_ESCAPE_TIMER_MIN 0
189
190#define IWL_BA_ESCAPE_TIMER_DEFAULT 3
191#define IWL_BA_ESCAPE_TIMER_MAX 1024
192#define IWL_BA_ESCAPE_TIMER_MIN 0
193
194#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
195
120#endif 196#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 191dcae8ba47..6031dbf83a96 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -170,6 +170,8 @@ enum {
170 BT_COEX_PROT_ENV = 0xcd, 170 BT_COEX_PROT_ENV = 0xcd,
171 BT_PROFILE_NOTIFICATION = 0xce, 171 BT_PROFILE_NOTIFICATION = 0xce,
172 172
173 REPLY_BEACON_FILTERING_CMD = 0xd2,
174
173 REPLY_DEBUG_CMD = 0xf0, 175 REPLY_DEBUG_CMD = 0xf0,
174 DEBUG_LOG_MSG = 0xf7, 176 DEBUG_LOG_MSG = 0xf7,
175 177
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index dd158ec571fb..e2cf6d92217b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -530,6 +530,17 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
530 */ 530 */
531 iwl_mvm_power_update_mode(mvm, vif); 531 iwl_mvm_power_update_mode(mvm, vif);
532 532
533 /* beacon filtering */
534 if (!mvm->bf_allowed_vif &&
535 vif->type == NL80211_IFTYPE_STATION && !vif->p2p){
536 mvm->bf_allowed_vif = mvmvif;
537 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
538 }
539
540 ret = iwl_mvm_disable_beacon_filter(mvm, vif);
541 if (ret)
542 goto out_release;
543
533 /* 544 /*
534 * P2P_DEVICE interface does not have a channel context assigned to it, 545 * P2P_DEVICE interface does not have a channel context assigned to it,
535 * so a dedicated PHY context is allocated to it and the corresponding 546 * 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,
646 657
647 mutex_lock(&mvm->mutex); 658 mutex_lock(&mvm->mutex);
648 659
660 if (mvm->bf_allowed_vif == mvmvif) {
661 mvm->bf_allowed_vif = NULL;
662 vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;
663 }
664
649 iwl_mvm_vif_dbgfs_clean(mvm, vif); 665 iwl_mvm_vif_dbgfs_clean(mvm, vif);
650 666
651 /* 667 /*
@@ -984,9 +1000,13 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
984 mvmvif->phy_ctxt->channel->band); 1000 mvmvif->phy_ctxt->channel->band);
985 } else if (old_state == IEEE80211_STA_ASSOC && 1001 } else if (old_state == IEEE80211_STA_ASSOC &&
986 new_state == IEEE80211_STA_AUTHORIZED) { 1002 new_state == IEEE80211_STA_AUTHORIZED) {
1003 /* enable beacon filtering */
1004 WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif));
987 ret = 0; 1005 ret = 0;
988 } else if (old_state == IEEE80211_STA_AUTHORIZED && 1006 } else if (old_state == IEEE80211_STA_AUTHORIZED &&
989 new_state == IEEE80211_STA_ASSOC) { 1007 new_state == IEEE80211_STA_ASSOC) {
1008 /* disable beacon filtering */
1009 WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif));
990 ret = 0; 1010 ret = 0;
991 } else if (old_state == IEEE80211_STA_ASSOC && 1011 } else if (old_state == IEEE80211_STA_ASSOC &&
992 new_state == IEEE80211_STA_AUTH) { 1012 new_state == IEEE80211_STA_AUTH) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 8269bc562951..4fc64d50dc50 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -266,6 +266,12 @@ struct iwl_mvm {
266 266
267 unsigned long status; 267 unsigned long status;
268 268
269 /*
270 * for beacon filtering -
271 * currently only one interface can be supported
272 */
273 struct iwl_mvm_vif *bf_allowed_vif;
274
269 enum iwl_ucode_type cur_ucode; 275 enum iwl_ucode_type cur_ucode;
270 bool ucode_loaded; 276 bool ucode_loaded;
271 bool init_ucode_run; 277 bool init_ucode_run;
@@ -533,4 +539,10 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
533 enum ieee80211_rssi_event rssi_event); 539 enum ieee80211_rssi_event rssi_event);
534void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 540void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
535 541
542/* beacon filtering */
543int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
544 struct ieee80211_vif *vif);
545int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
546 struct ieee80211_vif *vif);
547
536#endif /* __IWL_MVM_H__ */ 548#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index fe031d304d1e..5bf1eaf9046a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -292,6 +292,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
292 CMD(BT_COEX_PROT_ENV), 292 CMD(BT_COEX_PROT_ENV),
293 CMD(BT_PROFILE_NOTIFICATION), 293 CMD(BT_PROFILE_NOTIFICATION),
294 CMD(BT_CONFIG), 294 CMD(BT_CONFIG),
295 CMD(REPLY_BEACON_FILTERING_CMD),
295}; 296};
296#undef CMD 297#undef CMD
297 298
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index ed77e437aac4..30a5c27bd623 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -178,3 +178,70 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
178 return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, 178 return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
179 sizeof(cmd), &cmd); 179 sizeof(cmd), &cmd);
180} 180}
181
182static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
183 struct iwl_beacon_filter_cmd *cmd)
184{
185 int ret;
186
187 ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, CMD_SYNC,
188 sizeof(struct iwl_beacon_filter_cmd), cmd);
189
190 if (!ret) {
191 IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
192 cmd->ba_enable_beacon_abort);
193 IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
194 cmd->ba_escape_timer);
195 IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
196 cmd->bf_debug_flag);
197 IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
198 cmd->bf_enable_beacon_filter);
199 IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
200 cmd->bf_energy_delta);
201 IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
202 cmd->bf_escape_timer);
203 IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
204 cmd->bf_roaming_energy_delta);
205 IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
206 cmd->bf_roaming_state);
207 IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n",
208 cmd->bf_temperature_delta);
209 }
210 return ret;
211}
212
213int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
214 struct ieee80211_vif *vif)
215{
216 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
217 struct iwl_beacon_filter_cmd cmd = {
218 .bf_enable_beacon_filter = 1,
219 .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT,
220 .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT,
221 .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT,
222 .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT,
223 .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT,
224 .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),
225 .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT),
226 .ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT,
227 };
228
229 if (mvmvif != mvm->bf_allowed_vif ||
230 vif->type != NL80211_IFTYPE_STATION || vif->p2p)
231 return 0;
232
233 return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
234}
235
236int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
237 struct ieee80211_vif *vif)
238{
239 struct iwl_beacon_filter_cmd cmd = {
240 .bf_enable_beacon_filter = 0,
241 };
242
243 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
244 return 0;
245
246 return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
247}