aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-ucode.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c95
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[] = {
IWL_TX_FIFO_UNUSED,
};
+static const s8 iwlagn_ipan_queue_to_tx_fifo[] = {
+ IWL_TX_FIFO_VO,
+ IWL_TX_FIFO_VI,
+ IWL_TX_FIFO_BE,
+ IWL_TX_FIFO_BK,
+ IWL_TX_FIFO_BK_IPAN,
+ IWL_TX_FIFO_BE_IPAN,
+ IWL_TX_FIFO_VI_IPAN,
+ IWL_TX_FIFO_VO_IPAN,
+ IWL_TX_FIFO_BE_IPAN,
+ IWLAGN_CMD_FIFO_NUM,
+};
+
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
0, COEX_UNASSOC_IDLE_FLAGS},
@@ -329,8 +342,54 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
sizeof(coex_cmd), &coex_cmd);
}
+static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
+ ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ ((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
+ (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static void iwlagn_send_prio_tbl(struct iwl_priv *priv)
+{
+ struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd;
+
+ memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl,
+ sizeof(iwlagn_bt_prio_tbl));
+ if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PRIO_TABLE,
+ sizeof(prio_tbl_cmd), &prio_tbl_cmd))
+ IWL_ERR(priv, "failed to send BT prio tbl command\n");
+}
+
+static void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
+{
+ struct iwl_bt_coex_prot_env_cmd env_cmd;
+
+ env_cmd.action = action;
+ env_cmd.type = type;
+ if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
+ sizeof(env_cmd), &env_cmd))
+ IWL_ERR(priv, "failed to send BT env command\n");
+}
+
+
int iwlagn_alive_notify(struct iwl_priv *priv)
{
+ const s8 *queues;
u32 a;
unsigned long flags;
int i, chan;
@@ -365,7 +424,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL,
- IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
+ IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv));
iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
/* initiate the queues */
@@ -391,7 +450,13 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
/* Activate all Tx DMA/FIFO channels */
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
- iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+ /* map queues to FIFOs */
+ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
+ queues = iwlagn_ipan_queue_to_tx_fifo;
+ else
+ queues = iwlagn_default_queue_to_tx_fifo;
+
+ iwlagn_set_wr_ptrs(priv, priv->cmd_queue, 0);
/* make sure all queue are not stopped */
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
@@ -400,11 +465,12 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
/* reset to 0 to enable all the queue first */
priv->txq_ctx_active_msk = 0;
- /* map qos queues to fifos one-to-one */
+
BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10);
+ BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10);
- for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) {
- int ac = iwlagn_default_queue_to_tx_fifo[i];
+ for (i = 0; i < 10; i++) {
+ int ac = queues[i];
iwl_txq_ctx_activate(priv, i);
@@ -416,6 +482,25 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
+ if (priv->cfg->advanced_bt_coexist) {
+ /* Configure Bluetooth device coexistence support */
+ /* need to perform this before any calibration */
+ priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
+ priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
+ priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
+ priv->cfg->ops->hcmd->send_bt_config(priv);
+ priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
+
+ if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC) {
+ iwlagn_send_prio_tbl(priv);
+ iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
+ BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+ iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
+ BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
+ }
+
+ }
+
iwlagn_send_wimax_coex(priv);
iwlagn_set_Xtal_calib(priv);