diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | 76 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 20 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/ops.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/power.c | 67 |
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 | */ | ||
151 | struct 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); |
534 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 540 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
535 | 541 | ||
542 | /* beacon filtering */ | ||
543 | int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, | ||
544 | struct ieee80211_vif *vif); | ||
545 | int 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 | |||
182 | static 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 | |||
213 | int 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 | |||
236 | int 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 | } | ||