mwifiex: add custom IE framework
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / iwl-agn-tx.c
index 697f2032bfd6eae891f1ed144b2558cc13ecb724..3366e2e2f00fc809ce084e236ab8d9fb3c93f34b 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/ieee80211.h>
 
 #include "iwl-dev.h"
-#include "iwl-core.h"
 #include "iwl-io.h"
 #include "iwl-agn-hw.h"
 #include "iwl-agn.h"
@@ -85,8 +84,8 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
        else if (ieee80211_is_back_req(fc))
                tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
        else if (info->band == IEEE80211_BAND_2GHZ &&
-                cfg(priv)->bt_params &&
-                cfg(priv)->bt_params->advanced_bt_coexist &&
+                priv->cfg->bt_params &&
+                priv->cfg->bt_params->advanced_bt_coexist &&
                 (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) ||
                 ieee80211_is_reassoc_req(fc) ||
                 skb->protocol == cpu_to_be16(ETH_P_PAE)))
@@ -203,15 +202,15 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
                rate_flags |= RATE_MCS_CCK_MSK;
 
        /* Set up antennas */
-        if (cfg(priv)->bt_params &&
-            cfg(priv)->bt_params->advanced_bt_coexist &&
+        if (priv->cfg->bt_params &&
+            priv->cfg->bt_params->advanced_bt_coexist &&
             priv->bt_full_concurrent) {
                /* operated as 1x1 in full concurrency mode */
                priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
-                               first_antenna(hw_params(priv).valid_tx_ant));
+                               first_antenna(priv->hw_params.valid_tx_ant));
        } else
                priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
-                                               hw_params(priv).valid_tx_ant);
+                                               priv->hw_params.valid_tx_ant);
        rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
 
        /* Set the rate in the TX cmd */
@@ -396,12 +395,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* TODO need this for burst mode later on */
        iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id);
-       iwl_dbg_log_tx_data_frame(priv, len, hdr);
 
        iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc);
 
-       iwl_update_stats(priv, true, fc, len);
-
        memset(&info->status, 0, sizeof(info->status));
 
        info->driver_data[0] = ctx;
@@ -467,7 +463,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        else
                txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
 
-       if (iwl_trans_tx(trans(priv), skb, dev_cmd, txq_id))
+       WARN_ON_ONCE(!is_agg && txq_id != info->hw_queue);
+       WARN_ON_ONCE(is_agg &&
+                    priv->queue_to_mac80211[txq_id] != info->hw_queue);
+
+       if (iwl_trans_tx(priv->trans, skb, dev_cmd, txq_id))
                goto drop_unlock_sta;
 
        if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc) &&
@@ -496,14 +496,14 @@ drop_unlock_priv:
        return -1;
 }
 
-static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int ac)
+static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int mq)
 {
        int q;
 
        for (q = IWLAGN_FIRST_AMPDU_QUEUE;
-            q < cfg(priv)->base_params->num_of_queues; q++) {
+            q < priv->cfg->base_params->num_of_queues; q++) {
                if (!test_and_set_bit(q, priv->agg_q_alloc)) {
-                       priv->queue_to_ac[q] = ac;
+                       priv->queue_to_mac80211[q] = mq;
                        return q;
                }
        }
@@ -514,7 +514,7 @@ static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int ac)
 static void iwlagn_dealloc_agg_txq(struct iwl_priv *priv, int q)
 {
        clear_bit(q, priv->agg_q_alloc);
-       priv->queue_to_ac[q] = IWL_INVALID_AC;
+       priv->queue_to_mac80211[q] = IWL_INVALID_MAC80211_QUEUE;
 }
 
 int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
@@ -522,6 +522,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
 {
        struct iwl_tid_data *tid_data;
        int sta_id, txq_id;
+       enum iwl_agg_state agg_state;
 
        sta_id = iwl_sta_id(sta);
 
@@ -545,6 +546,13 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
                */
                IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
                goto turn_off;
+       case IWL_AGG_STARTING:
+               /*
+                * This can happen when the session is stopped before
+                * we receive ADDBA response
+                */
+               IWL_DEBUG_HT(priv, "AGG stop before AGG became operational\n");
+               goto turn_off;
        case IWL_AGG_ON:
                break;
        default:
@@ -576,12 +584,23 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
        IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n",
                            tid_data->agg.ssn);
 turn_off:
+       agg_state = priv->tid_data[sta_id][tid].agg.state;
        priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
 
        spin_unlock_bh(&priv->sta_lock);
 
        if (test_bit(txq_id, priv->agg_q_alloc)) {
-               iwl_trans_tx_agg_disable(trans(priv), txq_id);
+               /*
+                * If the transport didn't know that we wanted to start
+                * agreggation, don't tell it that we want to stop them.
+                * This can happen when we don't get the addBA response on
+                * time, or we hadn't time to drain the AC queues.
+                */
+               if (agg_state == IWL_AGG_ON)
+                       iwl_trans_tx_agg_disable(priv->trans, txq_id);
+               else
+                       IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n",
+                                           agg_state);
                iwlagn_dealloc_agg_txq(priv, txq_id);
        }
 
@@ -593,6 +612,7 @@ turn_off:
 int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
                        struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
+       struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
        struct iwl_tid_data *tid_data;
        int sta_id, txq_id, ret;
 
@@ -612,7 +632,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
                return -ENXIO;
        }
 
-       txq_id = iwlagn_alloc_agg_txq(priv, tid_to_ac[tid]);
+       txq_id = iwlagn_alloc_agg_txq(priv, ctx->ac_to_queue[tid_to_ac[tid]]);
        if (txq_id < 0) {
                IWL_DEBUG_TX_QUEUES(priv,
                        "No free aggregation queue for %pM/%d\n",
@@ -634,7 +654,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
        if (*ssn == tid_data->next_reclaimed) {
                IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n",
                                    tid_data->agg.ssn);
-               tid_data->agg.state = IWL_AGG_ON;
+               tid_data->agg.state = IWL_AGG_STARTING;
                ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
        } else {
                IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
@@ -661,11 +681,12 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
        spin_lock_bh(&priv->sta_lock);
        ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn;
        q = priv->tid_data[sta_priv->sta_id][tid].agg.txq_id;
+       priv->tid_data[sta_priv->sta_id][tid].agg.state = IWL_AGG_ON;
        spin_unlock_bh(&priv->sta_lock);
 
        fifo = ctx->ac_to_fifo[tid_to_ac[tid]];
 
-       iwl_trans_tx_agg_setup(trans(priv), q, fifo,
+       iwl_trans_tx_agg_setup(priv->trans, q, fifo,
                               sta_priv->sta_id, tid,
                               buf_size, ssn);
 
@@ -689,7 +710,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
        sta_priv->max_agg_bufsize =
                min(sta_priv->max_agg_bufsize, buf_size);
 
-       if (hw_params(priv).use_rts_for_aggregation) {
+       if (priv->hw_params.use_rts_for_aggregation) {
                /*
                 * switch to RTS/CTS if it is the prefer protection
                 * method for HT traffic
@@ -732,7 +753,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
                        IWL_DEBUG_TX_QUEUES(priv,
                                "Can continue DELBA flow ssn = next_recl ="
                                " %d", tid_data->next_reclaimed);
-                       iwl_trans_tx_agg_disable(trans(priv),
+                       iwl_trans_tx_agg_disable(priv->trans,
                                                 tid_data->agg.txq_id);
                        iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id);
                        tid_data->agg.state = IWL_AGG_OFF;
@@ -745,7 +766,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
                        IWL_DEBUG_TX_QUEUES(priv,
                                "Can continue ADDBA flow ssn = next_recl ="
                                " %d", tid_data->next_reclaimed);
-                       tid_data->agg.state = IWL_AGG_ON;
+                       tid_data->agg.state = IWL_AGG_STARTING;
                        ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
                }
                break;
@@ -909,8 +930,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
         * notification again.
         */
        if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
-           cfg(priv)->bt_params &&
-           cfg(priv)->bt_params->advanced_bt_coexist) {
+           priv->cfg->bt_params &&
+           priv->cfg->bt_params->advanced_bt_coexist) {
                IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n");
        }
 
@@ -1092,7 +1113,7 @@ static int iwl_reclaim(struct iwl_priv *priv, int sta_id, int tid,
                return 1;
        }
 
-       iwl_trans_reclaim(trans(priv), txq_id, ssn, skbs);
+       iwl_trans_reclaim(priv->trans, txq_id, ssn, skbs);
        return 0;
 }
 
@@ -1249,7 +1270,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
         * (in Tx queue's circular buffer) of first TFD/frame in window */
        u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
 
-       if (scd_flow >= cfg(priv)->base_params->num_of_queues) {
+       if (scd_flow >= priv->cfg->base_params->num_of_queues) {
                IWL_ERR(priv,
                        "BUG_ON scd_flow is bigger than number of queues\n");
                return 0;
@@ -1285,10 +1306,11 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                           (u8 *) &ba_resp->sta_addr_lo32,
                           ba_resp->sta_id);
        IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, "
-                          "scd_flow = %d, scd_ssn = %d\n",
+                          "scd_flow = %d, scd_ssn = %d sent:%d, acked:%d\n",
                           ba_resp->tid, le16_to_cpu(ba_resp->seq_ctl),
                           (unsigned long long)le64_to_cpu(ba_resp->bitmap),
-                          scd_flow, ba_resp_scd_ssn);
+                          scd_flow, ba_resp_scd_ssn, ba_resp->txed,
+                          ba_resp->txed_2_done);
 
        /* Mark that the expected block-ack response arrived */
        agg->wait_for_ba = false;
@@ -1304,8 +1326,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                 */
                ba_resp->txed = ba_resp->txed_2_done;
        }
-       IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
-                       ba_resp->txed, ba_resp->txed_2_done);
 
        priv->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn;
 
This page took 0.030859 seconds and 5 git commands to generate.