Merge branch 'topic/pcm-estrpipe-in-pm' into for-linus
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-tx.c
index 85ae7a6..2e89040 100644 (file)
@@ -720,8 +720,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                goto drop_unlock;
        }
 
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        hdr_len = ieee80211_hdrlen(fc);
 
        /* Find (or create) index into station table for destination station */
@@ -729,7 +727,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        if (sta_id == IWL_INVALID_STATION) {
                IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
                               hdr->addr1);
-               goto drop;
+               goto drop_unlock;
        }
 
        IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
@@ -750,14 +748,17 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                        txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
                        swq_id = iwl_virtual_agg_queue_num(swq_id, txq_id);
                }
-               priv->stations[sta_id].tid[tid].tfds_in_queue++;
        }
 
        txq = &priv->txq[txq_id];
        q = &txq->q;
        txq->swq_id = swq_id;
 
-       spin_lock_irqsave(&priv->lock, flags);
+       if (unlikely(iwl_queue_space(q) < q->high_mark))
+               goto drop_unlock;
+
+       if (ieee80211_is_data_qos(fc))
+               priv->stations[sta_id].tid[tid].tfds_in_queue++;
 
        /* Set up driver data for this TFD */
        memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
@@ -872,7 +873,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
 
        /* Set up entry for this TFD in Tx byte-count array */
-       priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
+       if (info->flags & IEEE80211_TX_CTL_AMPDU)
+               priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
                                                     le16_to_cpu(tx_cmd->len));
 
        pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
@@ -901,7 +903,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
 drop_unlock:
        spin_unlock_irqrestore(&priv->lock, flags);
-drop:
        return -1;
 }
 EXPORT_SYMBOL(iwl_tx_skb);
@@ -1170,6 +1171,8 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
                IWL_ERR(priv, "Start AGG on invalid station\n");
                return -ENXIO;
        }
+       if (unlikely(tid >= MAX_TID_COUNT))
+               return -EINVAL;
 
        if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
                IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");