aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-08-02 15:37:34 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-08-02 15:37:34 -0400
commit204162296edf0d0ac3e4dfd5bd0cac4af731b583 (patch)
treefdf941fd23fae6097500db4998d4ca96467fc352 /drivers/net/wireless/iwlwifi/mvm/bt-coex.c
parente3d5291436ff9efeeb968459724af5332305dded (diff)
parent147fc9be81d10e6e863323c0b54e140b42fd1ed6 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/bt-coex.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/bt-coex.c162
1 files changed, 98 insertions, 64 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
index dbd622a3929c..0fad98b85f60 100644
--- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -220,66 +220,87 @@ static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = {
220 220
221int iwl_send_bt_init_conf(struct iwl_mvm *mvm) 221int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
222{ 222{
223 struct iwl_bt_coex_cmd cmd = { 223 struct iwl_bt_coex_cmd *bt_cmd;
224 .max_kill = 5, 224 struct iwl_host_cmd cmd = {
225 .bt3_time_t7_value = 1, 225 .id = BT_CONFIG,
226 .bt3_prio_sample_time = 2, 226 .len = { sizeof(*bt_cmd), },
227 .bt3_timer_t2_value = 0xc, 227 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
228 .flags = CMD_SYNC,
228 }; 229 };
229 int ret; 230 int ret;
230 231
231 cmd.flags = iwlwifi_mod_params.bt_coex_active ? 232 /* go to CALIB state in internal BT-Coex state machine */
233 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
234 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
235 if (ret)
236 return ret;
237
238 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
239 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
240 if (ret)
241 return ret;
242
243 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
244 if (!bt_cmd)
245 return -ENOMEM;
246 cmd.data[0] = bt_cmd;
247
248 bt_cmd->max_kill = 5;
249 bt_cmd->bt3_time_t7_value = 1;
250 bt_cmd->bt3_prio_sample_time = 2;
251 bt_cmd->bt3_timer_t2_value = 0xc;
252
253 bt_cmd->flags = iwlwifi_mod_params.bt_coex_active ?
232 BT_COEX_NW : BT_COEX_DISABLE; 254 BT_COEX_NW : BT_COEX_DISABLE;
233 cmd.flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE; 255 bt_cmd->flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE;
234 256
235 cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | 257 bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
236 BT_VALID_BT_PRIO_BOOST | 258 BT_VALID_BT_PRIO_BOOST |
237 BT_VALID_MAX_KILL | 259 BT_VALID_MAX_KILL |
238 BT_VALID_3W_TMRS | 260 BT_VALID_3W_TMRS |
239 BT_VALID_KILL_ACK | 261 BT_VALID_KILL_ACK |
240 BT_VALID_KILL_CTS | 262 BT_VALID_KILL_CTS |
241 BT_VALID_REDUCED_TX_POWER | 263 BT_VALID_REDUCED_TX_POWER |
242 BT_VALID_LUT); 264 BT_VALID_LUT);
243 265
244 if (mvm->cfg->bt_shared_single_ant) 266 if (mvm->cfg->bt_shared_single_ant)
245 memcpy(&cmd.decision_lut, iwl_single_shared_ant_lookup, 267 memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant_lookup,
246 sizeof(iwl_single_shared_ant_lookup)); 268 sizeof(iwl_single_shared_ant_lookup));
247 else if (is_loose_coex()) 269 else if (is_loose_coex())
248 memcpy(&cmd.decision_lut, iwl_loose_lookup, 270 memcpy(&bt_cmd->decision_lut, iwl_loose_lookup,
249 sizeof(iwl_tight_lookup)); 271 sizeof(iwl_tight_lookup));
250 else 272 else
251 memcpy(&cmd.decision_lut, iwl_tight_lookup, 273 memcpy(&bt_cmd->decision_lut, iwl_tight_lookup,
252 sizeof(iwl_tight_lookup)); 274 sizeof(iwl_tight_lookup));
253 275
254 cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); 276 bt_cmd->bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST);
255 cmd.kill_ack_msk = 277 bt_cmd->kill_ack_msk =
256 cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); 278 cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
257 cmd.kill_cts_msk = 279 bt_cmd->kill_cts_msk =
258 cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); 280 cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
259 281
260 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); 282 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
261 283
262 /* go to CALIB state in internal BT-Coex state machine */ 284 ret = iwl_mvm_send_cmd(mvm, &cmd);
263 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
264 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
265 if (ret)
266 return ret;
267
268 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
269 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
270 if (ret)
271 return ret;
272 285
273 return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, 286 kfree(bt_cmd);
274 sizeof(cmd), &cmd); 287 return ret;
275} 288}
276 289
277static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, 290static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
278 bool reduced_tx_power) 291 bool reduced_tx_power)
279{ 292{
280 enum iwl_bt_kill_msk bt_kill_msk; 293 enum iwl_bt_kill_msk bt_kill_msk;
281 struct iwl_bt_coex_cmd cmd = {}; 294 struct iwl_bt_coex_cmd *bt_cmd;
282 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; 295 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
296 struct iwl_host_cmd cmd = {
297 .id = BT_CONFIG,
298 .data[0] = &bt_cmd,
299 .len = { sizeof(*bt_cmd), },
300 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
301 .flags = CMD_SYNC,
302 };
303 int ret = 0;
283 304
284 lockdep_assert_held(&mvm->mutex); 305 lockdep_assert_held(&mvm->mutex);
285 306
@@ -308,24 +329,40 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
308 return 0; 329 return 0;
309 330
310 mvm->bt_kill_msk = bt_kill_msk; 331 mvm->bt_kill_msk = bt_kill_msk;
311 cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); 332
312 cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); 333 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
313 cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); 334 if (!bt_cmd)
335 return -ENOMEM;
336 cmd.data[0] = bt_cmd;
337
338 bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
339 bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
340 bt_cmd->valid_bit_msk =
341 cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
314 342
315 IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk); 343 IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk);
316 return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, 344
317 sizeof(cmd), &cmd); 345 ret = iwl_mvm_send_cmd(mvm, &cmd);
346
347 kfree(bt_cmd);
348 return ret;
318} 349}
319 350
320static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, 351static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
321 bool enable) 352 bool enable)
322{ 353{
323 struct iwl_bt_coex_cmd cmd = { 354 struct iwl_bt_coex_cmd *bt_cmd;
324 .valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER), 355 /* Send ASYNC since this can be sent from an atomic context */
325 .bt_reduced_tx_power = sta_id, 356 struct iwl_host_cmd cmd = {
357 .id = BT_CONFIG,
358 .len = { sizeof(*bt_cmd), },
359 .dataflags = { IWL_HCMD_DFL_DUP, },
360 .flags = CMD_ASYNC,
326 }; 361 };
362
327 struct ieee80211_sta *sta; 363 struct ieee80211_sta *sta;
328 struct iwl_mvm_sta *mvmsta; 364 struct iwl_mvm_sta *mvmsta;
365 int ret;
329 366
330 /* This can happen if the station has been removed right now */ 367 /* This can happen if the station has been removed right now */
331 if (sta_id == IWL_MVM_STATION_COUNT) 368 if (sta_id == IWL_MVM_STATION_COUNT)
@@ -339,17 +376,26 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
339 if (mvmsta->bt_reduced_txpower == enable) 376 if (mvmsta->bt_reduced_txpower == enable)
340 return 0; 377 return 0;
341 378
379 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
380 if (!bt_cmd)
381 return -ENOMEM;
382 cmd.data[0] = bt_cmd;
383
384 bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER),
385 bt_cmd->bt_reduced_tx_power = sta_id;
386
342 if (enable) 387 if (enable)
343 cmd.bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT; 388 bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
344 389
345 IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n", 390 IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
346 enable ? "en" : "dis", sta_id); 391 enable ? "en" : "dis", sta_id);
347 392
348 mvmsta->bt_reduced_txpower = enable; 393 mvmsta->bt_reduced_txpower = enable;
349 394
350 /* Send ASYNC since this can be sent from an atomic context */ 395 ret = iwl_mvm_send_cmd(mvm, &cmd);
351 return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_ASYNC, 396
352 sizeof(cmd), &cmd); 397 kfree(bt_cmd);
398 return ret;
353} 399}
354 400
355struct iwl_bt_iterator_data { 401struct iwl_bt_iterator_data {
@@ -384,6 +430,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
384 430
385 smps_mode = IEEE80211_SMPS_AUTOMATIC; 431 smps_mode = IEEE80211_SMPS_AUTOMATIC;
386 432
433 /* non associated BSSes aren't to be considered */
434 if (!vif->bss_conf.assoc)
435 return;
436
387 if (band != IEEE80211_BAND_2GHZ) { 437 if (band != IEEE80211_BAND_2GHZ) {
388 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, 438 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
389 smps_mode); 439 smps_mode);
@@ -523,6 +573,8 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
523 lockdep_is_held(&mvm->mutex)); 573 lockdep_is_held(&mvm->mutex));
524 mvmsta = (void *)sta->drv_priv; 574 mvmsta = (void *)sta->drv_priv;
525 575
576 data->num_bss_ifaces++;
577
526 /* 578 /*
527 * This interface doesn't support reduced Tx power (because of low 579 * This interface doesn't support reduced Tx power (because of low
528 * RSSI probably), then set bt_kill_msk to default values. 580 * RSSI probably), then set bt_kill_msk to default values.
@@ -588,23 +640,5 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
588 640
589void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 641void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
590{ 642{
591 struct ieee80211_chanctx_conf *chanctx_conf;
592 enum ieee80211_band band;
593
594 rcu_read_lock();
595 chanctx_conf = rcu_dereference(vif->chanctx_conf);
596 if (chanctx_conf && chanctx_conf->def.chan)
597 band = chanctx_conf->def.chan->band;
598 else
599 band = -1;
600 rcu_read_unlock();
601
602 /* if we are in 2GHz we will get a notification from the fw */
603 if (band == IEEE80211_BAND_2GHZ)
604 return;
605
606 /* else, we can remove all the constraints */
607 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
608
609 iwl_mvm_bt_coex_notif_handle(mvm); 643 iwl_mvm_bt_coex_notif_handle(mvm);
610} 644}