iiwlagn: remove unused parameter
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-agn-lib.c
index 554afb7..d4ba335 100644 (file)
@@ -405,6 +405,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
                return;
        }
 
+       txq->time_stamp = jiffies;
        info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
        memset(&info->status, 0, sizeof(info->status));
 
@@ -445,22 +446,17 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
 
                        if (priv->mac80211_registered &&
                            (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
-                           (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
-                               if (agg->state == IWL_AGG_OFF)
-                                       iwl_wake_queue(priv, txq_id);
-                               else
-                                       iwl_wake_queue(priv, txq->swq_id);
-                       }
+                           (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
+                               iwl_wake_queue(priv, txq);
                }
        } else {
-               BUG_ON(txq_id != txq->swq_id);
                iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false);
                freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
                iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
 
                if (priv->mac80211_registered &&
                    (iwl_queue_space(&txq->q) > txq->q.low_mark))
-                       iwl_wake_queue(priv, txq_id);
+                       iwl_wake_queue(priv, txq);
        }
 
        iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
@@ -477,6 +473,11 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv)
        priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
                                        iwlagn_rx_calib_complete;
        priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
+
+       /* set up notification wait support */
+       spin_lock_init(&priv->_agn.notif_wait_lock);
+       INIT_LIST_HEAD(&priv->_agn.notif_waits);
+       init_waitqueue_head(&priv->_agn.notif_waitq);
 }
 
 void iwlagn_setup_deferred_work(struct iwl_priv *priv)
@@ -496,6 +497,10 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
        struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
        u8 tx_ant_cfg_cmd;
 
+       if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+                     "TX Power requested while scanning!\n"))
+               return -EAGAIN;
+
        /* half dBm need to multiply */
        tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
 
@@ -522,9 +527,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
        else
                tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
 
-       return  iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd,
-                                      sizeof(tx_power_cmd), &tx_power_cmd,
-                                      NULL);
+       return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd),
+                               &tx_power_cmd);
 }
 
 void iwlagn_temperature(struct iwl_priv *priv)
@@ -756,6 +760,12 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
        } else
                iwlagn_txq_ctx_reset(priv);
 
+       if (priv->cfg->base_params->shadow_reg_enable) {
+               /* enable shadow regs in HW */
+               iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL,
+                       0x800FFFFF);
+       }
+
        set_bit(STATUS_INIT, &priv->status);
 
        return 0;
@@ -1152,10 +1162,11 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv,
 
        /* rx_status carries information about the packet to mac80211 */
        rx_status.mactime = le64_to_cpu(phy_res->timestamp);
-       rx_status.freq =
-               ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel));
        rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
                                IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+       rx_status.freq =
+               ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
+                                              rx_status.band);
        rx_status.rate_idx =
                iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
        rx_status.flag = 0;
@@ -1487,15 +1498,11 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        if (priv->cfg->scan_rx_antennas[band])
                rx_ant = priv->cfg->scan_rx_antennas[band];
 
-       if (priv->cfg->scan_tx_antennas[band])
-               scan_tx_antennas = priv->cfg->scan_tx_antennas[band];
-
-       if (priv->cfg->bt_params &&
-           priv->cfg->bt_params->advanced_bt_coexist &&
-           priv->bt_full_concurrent) {
-               /* operated as 1x1 in full concurrency mode */
-               scan_tx_antennas = first_antenna(
-                       priv->cfg->scan_tx_antennas[band]);
+       if (band == IEEE80211_BAND_2GHZ &&
+           priv->cfg->bt_params &&
+           priv->cfg->bt_params->advanced_bt_coexist) {
+               /* transmit 2.4 GHz probes only on first antenna */
+               scan_tx_antennas = first_antenna(scan_tx_antennas);
        }
 
        priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band],
@@ -1590,22 +1597,6 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        return ret;
 }
 
-void iwlagn_post_scan(struct iwl_priv *priv)
-{
-       struct iwl_rxon_context *ctx;
-
-       /*
-        * Since setting the RXON may have been deferred while
-        * performing the scan, fire one off if needed
-        */
-       for_each_context(priv, ctx)
-               if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
-                       iwlagn_commit_rxon(priv, ctx);
-
-       if (priv->cfg->ops->hcmd->set_pan_params)
-               priv->cfg->ops->hcmd->set_pan_params(priv);
-}
-
 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
                               struct ieee80211_vif *vif, bool add)
 {
@@ -1796,7 +1787,7 @@ static const __le32 iwlagn_def_3w_lookup[12] = {
        cpu_to_le32(0xc0004000),
        cpu_to_le32(0x00004000),
        cpu_to_le32(0xf0005000),
-       cpu_to_le32(0xf0004000),
+       cpu_to_le32(0xf0005000),
 };
 
 static const __le32 iwlagn_concurrent_lookup[12] = {
@@ -1832,6 +1823,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
                bt_cmd.prio_boost = 0;
        bt_cmd.kill_ack_mask = priv->kill_ack_mask;
        bt_cmd.kill_cts_mask = priv->kill_cts_mask;
+
        bt_cmd.valid = priv->bt_valid;
        bt_cmd.tx_prio_boost = 0;
        bt_cmd.rx_prio_boost = 0;
@@ -1847,10 +1839,15 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
        } else {
                bt_cmd.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
                                        IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
+               if (priv->cfg->bt_params &&
+                   priv->cfg->bt_params->bt_sco_disable)
+                       bt_cmd.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
+
                if (priv->bt_ch_announce)
                        bt_cmd.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
                IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags);
        }
+       priv->bt_enable_flag = bt_cmd.flags;
        if (priv->bt_full_concurrent)
                memcpy(bt_cmd.bt3_lookup_table, iwlagn_concurrent_lookup,
                        sizeof(iwlagn_concurrent_lookup));
@@ -1866,21 +1863,6 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
        if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd))
                IWL_ERR(priv, "failed to send BT Coex Config\n");
 
-       /*
-        * When we are doing a restart, need to also reconfigure BT
-        * SCO to the device. If not doing a restart, bt_sco_active
-        * will always be false, so there's no need to have an extra
-        * variable to check for it.
-        */
-       if (priv->bt_sco_active) {
-               struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 };
-
-               if (priv->bt_sco_active)
-                       sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE;
-               if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO,
-                                    sizeof(sco_cmd), &sco_cmd))
-                       IWL_ERR(priv, "failed to send BT SCO command\n");
-       }
 }
 
 static void iwlagn_bt_traffic_change_work(struct work_struct *work)
@@ -1890,12 +1872,20 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
        struct iwl_rxon_context *ctx;
        int smps_request = -1;
 
+       /*
+        * Note: bt_traffic_load can be overridden by scan complete and
+        * coex profile notifications. Ignore that since only bad consequence
+        * can be not matching debug print with actual state.
+        */
        IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
                       priv->bt_traffic_load);
 
        switch (priv->bt_traffic_load) {
        case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
-               smps_request = IEEE80211_SMPS_AUTOMATIC;
+               if (priv->bt_status)
+                       smps_request = IEEE80211_SMPS_DYNAMIC;
+               else
+                       smps_request = IEEE80211_SMPS_AUTOMATIC;
                break;
        case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
                smps_request = IEEE80211_SMPS_DYNAMIC;
@@ -1912,6 +1902,16 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
 
        mutex_lock(&priv->mutex);
 
+       /*
+        * We can not send command to firmware while scanning. When the scan
+        * complete we will schedule this work again. We do check with mutex
+        * locked to prevent new scan request to arrive. We do not check
+        * STATUS_SCANNING to avoid race when queue_work two times from
+        * different notifications, but quit and not perform any work at all.
+        */
+       if (test_bit(STATUS_SCAN_HW, &priv->status))
+               goto out;
+
        if (priv->cfg->ops->lib->update_chain_flags)
                priv->cfg->ops->lib->update_chain_flags(priv);
 
@@ -1921,7 +1921,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
                                ieee80211_request_smps(ctx->vif, smps_request);
                }
        }
-
+out:
        mutex_unlock(&priv->mutex);
 }
 
@@ -1992,24 +1992,29 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
                        BT_UART_MSG_FRAME7CONNECTABLE_POS);
 }
 
-static void iwlagn_set_kill_ack_msk(struct iwl_priv *priv,
-                                    struct iwl_bt_uart_msg *uart_msg)
+static void iwlagn_set_kill_msk(struct iwl_priv *priv,
+                               struct iwl_bt_uart_msg *uart_msg)
 {
-       u8 kill_ack_msk;
-       __le32 bt_kill_ack_msg[2] = {
-                       cpu_to_le32(0xFFFFFFF), cpu_to_le32(0xFFFFFC00) };
-
-       kill_ack_msk = (((BT_UART_MSG_FRAME3A2DP_MSK |
-                       BT_UART_MSG_FRAME3SNIFF_MSK |
-                       BT_UART_MSG_FRAME3SCOESCO_MSK) &
-                       uart_msg->frame3) == 0) ? 1 : 0;
-       if (priv->kill_ack_mask != bt_kill_ack_msg[kill_ack_msk]) {
+       u8 kill_msk;
+       static const __le32 bt_kill_ack_msg[2] = {
+               IWLAGN_BT_KILL_ACK_MASK_DEFAULT,
+               IWLAGN_BT_KILL_ACK_CTS_MASK_SCO };
+       static const __le32 bt_kill_cts_msg[2] = {
+               IWLAGN_BT_KILL_CTS_MASK_DEFAULT,
+               IWLAGN_BT_KILL_ACK_CTS_MASK_SCO };
+
+       kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3)
+               ? 1 : 0;
+       if (priv->kill_ack_mask != bt_kill_ack_msg[kill_msk] ||
+           priv->kill_cts_mask != bt_kill_cts_msg[kill_msk]) {
                priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK;
-               priv->kill_ack_mask = bt_kill_ack_msg[kill_ack_msk];
+               priv->kill_ack_mask = bt_kill_ack_msg[kill_msk];
+               priv->bt_valid |= IWLAGN_BT_VALID_KILL_CTS_MASK;
+               priv->kill_cts_mask = bt_kill_cts_msg[kill_msk];
+
                /* schedule to send runtime bt_config */
                queue_work(priv->workqueue, &priv->bt_runtime_config);
        }
-
 }
 
 void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
@@ -2018,9 +2023,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
        unsigned long flags;
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
-       struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 };
        struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
-       u8 last_traffic_load;
 
        IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
        IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status);
@@ -2029,11 +2032,10 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
                        coex->bt_ci_compliance);
        iwlagn_print_uartmsg(priv, uart_msg);
 
-       last_traffic_load = priv->notif_bt_traffic_load;
-       priv->notif_bt_traffic_load = coex->bt_traffic_load;
+       priv->last_bt_traffic_load = priv->bt_traffic_load;
        if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
                if (priv->bt_status != coex->bt_status ||
-                   last_traffic_load != coex->bt_traffic_load) {
+                   priv->last_bt_traffic_load != coex->bt_traffic_load) {
                        if (coex->bt_status) {
                                /* BT on */
                                if (!priv->bt_ch_announce)
@@ -2051,18 +2053,9 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
                        queue_work(priv->workqueue,
                                   &priv->bt_traffic_change_work);
                }
-               if (priv->bt_sco_active !=
-                   (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) {
-                       priv->bt_sco_active = uart_msg->frame3 &
-                               BT_UART_MSG_FRAME3SCOESCO_MSK;
-                       if (priv->bt_sco_active)
-                               sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE;
-                       iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO,
-                                      sizeof(sco_cmd), &sco_cmd, NULL);
-               }
        }
 
-       iwlagn_set_kill_ack_msk(priv, uart_msg);
+       iwlagn_set_kill_msk(priv, uart_msg);
 
        /* FIXME: based on notification, adjust the prio_boost */
 
@@ -2282,7 +2275,7 @@ static const char *get_csr_string(int cmd)
 void iwl_dump_csr(struct iwl_priv *priv)
 {
        int i;
-       u32 csr_tbl[] = {
+       static const u32 csr_tbl[] = {
                CSR_HW_IF_CONFIG_REG,
                CSR_INT_COALESCING,
                CSR_INT,
@@ -2341,7 +2334,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
        int pos = 0;
        size_t bufsz = 0;
 #endif
-       u32 fh_tbl[] = {
+       static const u32 fh_tbl[] = {
                FH_RSCSR_CHNL0_STTS_WPTR_REG,
                FH_RSCSR_CHNL0_RBDCB_BASE_REG,
                FH_RSCSR_CHNL0_WPTR,
@@ -2377,3 +2370,44 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
        }
        return 0;
 }
+
+/* notification wait support */
+void iwlagn_init_notification_wait(struct iwl_priv *priv,
+                                  struct iwl_notification_wait *wait_entry,
+                                  void (*fn)(struct iwl_priv *priv,
+                                             struct iwl_rx_packet *pkt),
+                                  u8 cmd)
+{
+       wait_entry->fn = fn;
+       wait_entry->cmd = cmd;
+       wait_entry->triggered = false;
+
+       spin_lock_bh(&priv->_agn.notif_wait_lock);
+       list_add(&wait_entry->list, &priv->_agn.notif_waits);
+       spin_unlock_bh(&priv->_agn.notif_wait_lock);
+}
+
+signed long iwlagn_wait_notification(struct iwl_priv *priv,
+                                    struct iwl_notification_wait *wait_entry,
+                                    unsigned long timeout)
+{
+       int ret;
+
+       ret = wait_event_timeout(priv->_agn.notif_waitq,
+                                &wait_entry->triggered,
+                                timeout);
+
+       spin_lock_bh(&priv->_agn.notif_wait_lock);
+       list_del(&wait_entry->list);
+       spin_unlock_bh(&priv->_agn.notif_wait_lock);
+
+       return ret;
+}
+
+void iwlagn_remove_notification(struct iwl_priv *priv,
+                               struct iwl_notification_wait *wait_entry)
+{
+       spin_lock_bh(&priv->_agn.notif_wait_lock);
+       list_del(&wait_entry->list);
+       spin_unlock_bh(&priv->_agn.notif_wait_lock);
+}