aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2013-02-10 10:06:17 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-06 10:47:59 -0500
commit7da052b818371b6b29909d871bf803192aa40b84 (patch)
tree6e61aeaf40c4a8455410918fb280d55423d57143
parentf421f9c3b2dc77e2be1b9400a4420b6d2cdfb847 (diff)
iwlwifi: mvm: update SMPS when BT gets active
When BT traffic load gets higher, we want to avoid using the shared antenna. In order to do so, we need to tell the AP that we don't support MIMO any more, or at least not all the time: in short, use the SMPS to achieve this. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/bt-coex.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
index 61159f8abe78..fa054b364e52 100644
--- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -242,12 +242,60 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
242 sizeof(cmd), &cmd); 242 sizeof(cmd), &cmd);
243} 243}
244 244
245struct iwl_bt_notif_iterator_data {
246 struct iwl_mvm *mvm;
247 struct iwl_bt_coex_profile_notif *notif;
248};
249
250static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
251 struct ieee80211_vif *vif)
252{
253 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
254 struct iwl_bt_notif_iterator_data *data = _data;
255 struct ieee80211_chanctx_conf *chanctx_conf;
256 enum ieee80211_smps_mode smps_mode;
257 enum ieee80211_band band;
258
259 if (vif->type != NL80211_IFTYPE_STATION)
260 return;
261
262 rcu_read_lock();
263 chanctx_conf = rcu_dereference(vif->chanctx_conf);
264 if (chanctx_conf && chanctx_conf->def.chan)
265 band = chanctx_conf->def.chan->band;
266 else
267 band = -1;
268 rcu_read_unlock();
269
270 if (band != IEEE80211_BAND_2GHZ)
271 return;
272
273 smps_mode = IEEE80211_SMPS_AUTOMATIC;
274
275 if (data->notif->bt_status)
276 smps_mode = IEEE80211_SMPS_DYNAMIC;
277
278 if (data->notif->bt_traffic_load)
279 smps_mode = IEEE80211_SMPS_STATIC;
280
281 IWL_DEBUG_COEX(data->mvm,
282 "mac %d: bt_status %d traffic_load %d smps_req %d\n",
283 mvmvif->id, data->notif->bt_status,
284 data->notif->bt_traffic_load, smps_mode);
285
286 ieee80211_request_smps(vif, smps_mode);
287}
288
245int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, 289int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
246 struct iwl_rx_cmd_buffer *rxb, 290 struct iwl_rx_cmd_buffer *rxb,
247 struct iwl_device_cmd *dev_cmd) 291 struct iwl_device_cmd *dev_cmd)
248{ 292{
249 struct iwl_rx_packet *pkt = rxb_addr(rxb); 293 struct iwl_rx_packet *pkt = rxb_addr(rxb);
250 struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data; 294 struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
295 struct iwl_bt_notif_iterator_data data = {
296 .mvm = mvm,
297 .notif = notif,
298 };
251 struct iwl_bt_coex_cmd cmd = {}; 299 struct iwl_bt_coex_cmd cmd = {};
252 enum iwl_bt_kill_msk bt_kill_msk; 300 enum iwl_bt_kill_msk bt_kill_msk;
253 301
@@ -259,6 +307,10 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
259 notif->bt_agg_traffic_load); 307 notif->bt_agg_traffic_load);
260 IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); 308 IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
261 309
310 ieee80211_iterate_active_interfaces_atomic(
311 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
312 iwl_mvm_bt_notif_iterator, &data);
313
262 /* Low latency BT profile is active: give higher prio to BT */ 314 /* Low latency BT profile is active: give higher prio to BT */
263 if (BT_MBOX_MSG(notif, 3, SCO_STATE) || 315 if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
264 BT_MBOX_MSG(notif, 3, A2DP_STATE) || 316 BT_MBOX_MSG(notif, 3, A2DP_STATE) ||