Merge branch 'for-linus' of git://github.com/gregungerer/m68knommu
[cascardo/linux.git] / drivers / net / wireless / iwlwifi / iwl-agn-tx.c
index f8a4bcf..35a6b71 100644 (file)
@@ -35,9 +35,7 @@
 
 #include "iwl-dev.h"
 #include "iwl-core.h"
-#include "iwl-sta.h"
 #include "iwl-io.h"
-#include "iwl-helpers.h"
 #include "iwl-agn-hw.h"
 #include "iwl-agn.h"
 #include "iwl-trans.h"
@@ -113,8 +111,6 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
        tx_cmd->next_frame_len = 0;
 }
 
-#define RTS_DFAULT_RETRY_LIMIT         60
-
 static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
                                     struct iwl_tx_cmd *tx_cmd,
                                     struct ieee80211_tx_info *info,
@@ -126,17 +122,25 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
        u8 data_retry_limit;
        u8 rate_plcp;
 
-       /* Set retry limit on DATA packets and Probe Responses*/
-       if (ieee80211_is_probe_resp(fc))
-               data_retry_limit = 3;
-       else
-               data_retry_limit = IWLAGN_DEFAULT_TX_RETRY;
-       tx_cmd->data_retry_limit = data_retry_limit;
+       if (priv->shrd->wowlan) {
+               rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
+               data_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
+       } else {
+               /* Set retry limit on RTS packets */
+               rts_retry_limit = IWLAGN_RTS_DFAULT_RETRY_LIMIT;
+
+               /* Set retry limit on DATA packets and Probe Responses*/
+               if (ieee80211_is_probe_resp(fc)) {
+                       data_retry_limit = IWLAGN_MGMT_DFAULT_RETRY_LIMIT;
+                       rts_retry_limit =
+                               min(data_retry_limit, rts_retry_limit);
+               } else if (ieee80211_is_back_req(fc))
+                       data_retry_limit = IWLAGN_BAR_DFAULT_RETRY_LIMIT;
+               else
+                       data_retry_limit = IWLAGN_DEFAULT_TX_RETRY;
+       }
 
-       /* Set retry limit on RTS packets */
-       rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
-       if (data_retry_limit < rts_retry_limit)
-               rts_retry_limit = data_retry_limit;
+       tx_cmd->data_retry_limit = data_retry_limit;
        tx_cmd->rts_retry_limit = rts_retry_limit;
 
        /* DATA packets will use the uCode station table for rate/antenna
@@ -300,7 +304,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                sta_priv = (void *)info->control.sta->drv_priv;
 
        if (sta_priv && sta_priv->asleep &&
-           (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
+           (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) {
                /*
                 * This sends an asynchronous command to the device,
                 * but we can rely on it being processed before the
@@ -313,6 +317,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
        }
 
+       if (info->flags & IEEE80211_TX_CTL_AMPDU)
+               is_agg = true;
+
        /* irqs already disabled/saved above when locking priv->shrd->lock */
        spin_lock(&priv->shrd->sta_lock);
 
@@ -322,10 +329,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                goto drop_unlock_sta;
 
        memset(dev_cmd, 0, sizeof(*dev_cmd));
-       tx_cmd = &dev_cmd->cmd.tx;
-
-       /* Copy MAC header from skb into command buffer */
-       memcpy(tx_cmd->hdr, hdr, hdr_len);
+       tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
 
        /* Total # bytes to be transmitted */
        len = (u16)skb->len;
@@ -342,6 +346,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        iwl_update_stats(priv, true, fc, len);
 
+       memset(&info->status, 0, sizeof(info->status));
+
        info->driver_data[0] = ctx;
        info->driver_data[1] = dev_cmd;
 
@@ -580,6 +586,9 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
                IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n");
        }
 
+       if (tx_resp->frame_count == 1)
+               return;
+
        /* Construct bit-map of pending frames within Tx window */
        for (i = 0; i < tx_resp->frame_count; i++) {
                u16 fstatus = le16_to_cpu(frame_status[i].status);
@@ -736,12 +745,13 @@ static void iwl_check_abort_status(struct iwl_priv *priv,
        }
 }
 
-void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+                              struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        u16 sequence = le16_to_cpu(pkt->hdr.sequence);
        int txq_id = SEQ_TO_QUEUE(sequence);
-       int cmd_index = SEQ_TO_INDEX(sequence);
+       int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence);
        struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
        struct ieee80211_hdr *hdr;
        u32 status = le16_to_cpu(tx_resp->status.status);
@@ -824,6 +834,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 
        iwl_check_abort_status(priv, tx_resp->frame_count, status);
        spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+       return 0;
 }
 
 /**
@@ -832,8 +843,9 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
  * Handles block-acknowledge notification from device, which reports success
  * of frames sent via aggregation.
  */
-void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
-                                          struct iwl_rx_mem_buffer *rxb)
+int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
+                                  struct iwl_rx_mem_buffer *rxb,
+                                  struct iwl_device_cmd *cmd)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
@@ -857,7 +869,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        if (scd_flow >= hw_params(priv).max_txq_num) {
                IWL_ERR(priv,
                        "BUG_ON scd_flow is bigger than number of queues\n");
-               return;
+               return 0;
        }
 
        sta_id = ba_resp->sta_id;
@@ -877,14 +889,14 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                        "BA scd_flow %d does not match txq_id %d\n",
                        scd_flow, agg->txq_id);
                spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-               return;
+               return 0;
        }
 
        if (unlikely(!agg->wait_for_ba)) {
                if (unlikely(ba_resp->bitmap))
                        IWL_ERR(priv, "Received BA when not expected\n");
                spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
-               return;
+               return 0;
        }
 
        IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
@@ -901,7 +913,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                           ba_resp->scd_ssn);
 
        /* Mark that the expected block-ack response arrived */
-       agg->wait_for_ba = 0;
+       agg->wait_for_ba = false;
 
        /* Sanity check values reported by uCode */
        if (ba_resp->txed_2_done > ba_resp->txed) {
@@ -935,7 +947,10 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                else
                        WARN_ON_ONCE(1);
 
-               if (freed == 0) {
+               info = IEEE80211_SKB_CB(skb);
+               kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
+
+               if (freed == 1) {
                        /* this is the first skb we deliver in this batch */
                        /* put the rate scaling data there */
                        info = IEEE80211_SKB_CB(skb);
@@ -948,11 +963,9 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
                                                    info);
                }
 
-               info = IEEE80211_SKB_CB(skb);
-               kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
-
                ieee80211_tx_status_irqsafe(priv->hw, skb);
        }
 
        spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
+       return 0;
 }