mwl8k: Reserve buffers for tx management frames
authorNishant Sarmukadam <nishants@marvell.com>
Thu, 21 Apr 2011 11:04:58 +0000 (16:34 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 25 Apr 2011 18:50:16 +0000 (14:50 -0400)
Since queues are not stopped anymore, management frames would be
dropped if the corresponding tx queue is full.
This can cause issues say when we want to setup an ampdu stream and
action frames i.e addba requests keep getting dropped frequently.
Fix this by reserving some buffers to allow management frames to
go through in queue full conditions.

Signed-off-by: Nishant Sarmukadam <nishants@marvell.com>
Signed-off-by: Pradeep Nemavat <pnemavat@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/mwl8k.c

index 93fe1bd91c369c2ede97c5f2d3922e487ad2641e..63ee8cfe322b0d3e832a7e6473fec94e3a7b51b7 100644 (file)
@@ -1818,6 +1818,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
        u8 tid = 0;
        struct mwl8k_ampdu_stream *stream = NULL;
        bool start_ba_session = false;
+       bool mgmtframe = false;
        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
 
        wh = (struct ieee80211_hdr *)skb->data;
@@ -1826,6 +1827,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
        else
                qos = 0;
 
+       if (ieee80211_is_mgmt(wh->frame_control))
+               mgmtframe = true;
+
        if (priv->ap_fw)
                mwl8k_encapsulate_tx_frame(skb);
        else
@@ -1955,15 +1959,26 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 
        txq = priv->txq + index;
 
-       if (txq->len >= MWL8K_TX_DESCS) {
-               if (start_ba_session) {
-                       spin_lock(&priv->stream_lock);
-                       mwl8k_remove_stream(hw, stream);
-                       spin_unlock(&priv->stream_lock);
+       /* Mgmt frames that go out frequently are probe
+        * responses. Other mgmt frames got out relatively
+        * infrequently. Hence reserve 2 buffers so that
+        * other mgmt frames do not get dropped due to an
+        * already queued probe response in one of the
+        * reserved buffers.
+        */
+
+       if (txq->len >= MWL8K_TX_DESCS - 2) {
+               if (mgmtframe == false ||
+                       txq->len == MWL8K_TX_DESCS) {
+                       if (start_ba_session) {
+                               spin_lock(&priv->stream_lock);
+                               mwl8k_remove_stream(hw, stream);
+                               spin_unlock(&priv->stream_lock);
+                       }
+                       spin_unlock_bh(&priv->tx_lock);
+                       dev_kfree_skb(skb);
+                       return;
                }
-               spin_unlock_bh(&priv->tx_lock);
-               dev_kfree_skb(skb);
-               return;
        }
 
        BUG_ON(txq->skb[txq->tail] != NULL);