diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-ucode.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 6f77441cb65a..a7961bf395fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -52,6 +52,19 @@ static const s8 iwlagn_default_queue_to_tx_fifo[] = { | |||
52 | IWL_TX_FIFO_UNUSED, | 52 | IWL_TX_FIFO_UNUSED, |
53 | }; | 53 | }; |
54 | 54 | ||
55 | static const s8 iwlagn_ipan_queue_to_tx_fifo[] = { | ||
56 | IWL_TX_FIFO_VO, | ||
57 | IWL_TX_FIFO_VI, | ||
58 | IWL_TX_FIFO_BE, | ||
59 | IWL_TX_FIFO_BK, | ||
60 | IWL_TX_FIFO_BK_IPAN, | ||
61 | IWL_TX_FIFO_BE_IPAN, | ||
62 | IWL_TX_FIFO_VI_IPAN, | ||
63 | IWL_TX_FIFO_VO_IPAN, | ||
64 | IWL_TX_FIFO_BE_IPAN, | ||
65 | IWLAGN_CMD_FIFO_NUM, | ||
66 | }; | ||
67 | |||
55 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | 68 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { |
56 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, | 69 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, |
57 | 0, COEX_UNASSOC_IDLE_FLAGS}, | 70 | 0, COEX_UNASSOC_IDLE_FLAGS}, |
@@ -329,8 +342,54 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) | |||
329 | sizeof(coex_cmd), &coex_cmd); | 342 | sizeof(coex_cmd), &coex_cmd); |
330 | } | 343 | } |
331 | 344 | ||
345 | static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | ||
346 | ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | | ||
347 | (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), | ||
348 | ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | | ||
349 | (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), | ||
350 | ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | | ||
351 | (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), | ||
352 | ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | | ||
353 | (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), | ||
354 | ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | | ||
355 | (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), | ||
356 | ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | | ||
357 | (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), | ||
358 | ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | | ||
359 | (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), | ||
360 | ((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | | ||
361 | (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), | ||
362 | ((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | | ||
363 | (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), | ||
364 | 0, 0, 0, 0, 0, 0, 0 | ||
365 | }; | ||
366 | |||
367 | static void iwlagn_send_prio_tbl(struct iwl_priv *priv) | ||
368 | { | ||
369 | struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; | ||
370 | |||
371 | memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, | ||
372 | sizeof(iwlagn_bt_prio_tbl)); | ||
373 | if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PRIO_TABLE, | ||
374 | sizeof(prio_tbl_cmd), &prio_tbl_cmd)) | ||
375 | IWL_ERR(priv, "failed to send BT prio tbl command\n"); | ||
376 | } | ||
377 | |||
378 | static void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) | ||
379 | { | ||
380 | struct iwl_bt_coex_prot_env_cmd env_cmd; | ||
381 | |||
382 | env_cmd.action = action; | ||
383 | env_cmd.type = type; | ||
384 | if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, | ||
385 | sizeof(env_cmd), &env_cmd)) | ||
386 | IWL_ERR(priv, "failed to send BT env command\n"); | ||
387 | } | ||
388 | |||
389 | |||
332 | int iwlagn_alive_notify(struct iwl_priv *priv) | 390 | int iwlagn_alive_notify(struct iwl_priv *priv) |
333 | { | 391 | { |
392 | const s8 *queues; | ||
334 | u32 a; | 393 | u32 a; |
335 | unsigned long flags; | 394 | unsigned long flags; |
336 | int i, chan; | 395 | int i, chan; |
@@ -365,7 +424,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv) | |||
365 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | 424 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); |
366 | 425 | ||
367 | iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, | 426 | iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, |
368 | IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); | 427 | IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv)); |
369 | iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0); | 428 | iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0); |
370 | 429 | ||
371 | /* initiate the queues */ | 430 | /* initiate the queues */ |
@@ -391,7 +450,13 @@ int iwlagn_alive_notify(struct iwl_priv *priv) | |||
391 | /* Activate all Tx DMA/FIFO channels */ | 450 | /* Activate all Tx DMA/FIFO channels */ |
392 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); | 451 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); |
393 | 452 | ||
394 | iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 453 | /* map queues to FIFOs */ |
454 | if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) | ||
455 | queues = iwlagn_ipan_queue_to_tx_fifo; | ||
456 | else | ||
457 | queues = iwlagn_default_queue_to_tx_fifo; | ||
458 | |||
459 | iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0); | ||
395 | 460 | ||
396 | /* make sure all queue are not stopped */ | 461 | /* make sure all queue are not stopped */ |
397 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | 462 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); |
@@ -400,11 +465,12 @@ int iwlagn_alive_notify(struct iwl_priv *priv) | |||
400 | 465 | ||
401 | /* reset to 0 to enable all the queue first */ | 466 | /* reset to 0 to enable all the queue first */ |
402 | priv->txq_ctx_active_msk = 0; | 467 | priv->txq_ctx_active_msk = 0; |
403 | /* map qos queues to fifos one-to-one */ | 468 | |
404 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); | 469 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); |
470 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10); | ||
405 | 471 | ||
406 | for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) { | 472 | for (i = 0; i < 10; i++) { |
407 | int ac = iwlagn_default_queue_to_tx_fifo[i]; | 473 | int ac = queues[i]; |
408 | 474 | ||
409 | iwl_txq_ctx_activate(priv, i); | 475 | iwl_txq_ctx_activate(priv, i); |
410 | 476 | ||
@@ -416,6 +482,25 @@ int iwlagn_alive_notify(struct iwl_priv *priv) | |||
416 | 482 | ||
417 | spin_unlock_irqrestore(&priv->lock, flags); | 483 | spin_unlock_irqrestore(&priv->lock, flags); |
418 | 484 | ||
485 | if (priv->cfg->advanced_bt_coexist) { | ||
486 | /* Configure Bluetooth device coexistence support */ | ||
487 | /* need to perform this before any calibration */ | ||
488 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; | ||
489 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; | ||
490 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; | ||
491 | priv->cfg->ops->hcmd->send_bt_config(priv); | ||
492 | priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; | ||
493 | |||
494 | if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC) { | ||
495 | iwlagn_send_prio_tbl(priv); | ||
496 | iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, | ||
497 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
498 | iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, | ||
499 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
500 | } | ||
501 | |||
502 | } | ||
503 | |||
419 | iwlagn_send_wimax_coex(priv); | 504 | iwlagn_send_wimax_coex(priv); |
420 | 505 | ||
421 | iwlagn_set_Xtal_calib(priv); | 506 | iwlagn_set_Xtal_calib(priv); |