wl1251: fix TX queue stopping/waking (again)
authorGrazvydas Ignotas <notasas@gmail.com>
Mon, 25 Oct 2010 20:09:04 +0000 (23:09 +0300)
committerGrazvydas Ignotas <notasas@gmail.com>
Mon, 17 Jan 2011 17:19:43 +0000 (19:19 +0200)
9df86e2e702c6d5547aced7f241addd2d698bb11 ported TX queue stopping/waking
improvement from wl1271, but it has some issues:
- it forgot to initialize wl_lock.
- it placed ieee80211_wake_queues in an awkward place between result
  handling loops, it's better to do it after all processing is done.
- it left queue wake call in wl1251_tx_packet_cb, which made the patch
  ineffective because by the time we reached low watermark check, queues
  would already be woken.
- the wl1271 watermark values are too large for wl1251, as it has
  shorter hardware tx queue.

Correct those issues.

Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
drivers/net/wireless/wl12xx/wl1251.h
drivers/net/wireless/wl12xx/wl1251_main.c
drivers/net/wireless/wl12xx/wl1251_tx.c

index a851e7d..e1dbc7e 100644 (file)
@@ -402,8 +402,8 @@ void wl1251_disable_interrupts(struct wl1251 *wl);
 
 #define WL1251_DEFAULT_POWER_LEVEL 20
 
-#define WL1251_TX_QUEUE_LOW_WATERMARK  10
-#define WL1251_TX_QUEUE_HIGH_WATERMARK 25
+#define WL1251_TX_QUEUE_LOW_WATERMARK 8
+#define WL1251_TX_QUEUE_HIGH_WATERMARK 20
 
 #define WL1251_DEFAULT_BEACON_INT 100
 #define WL1251_DEFAULT_DTIM_PERIOD 1
index 2f7c65c..d212b8c 100644 (file)
@@ -1373,6 +1373,8 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
        INIT_WORK(&wl->irq_work, wl1251_irq_work);
        INIT_WORK(&wl->tx_work, wl1251_tx_work);
 
+       spin_lock_init(&wl->wl_lock);
+
        /*
         * In case our MAC address is not correctly set,
         * we use a random but Nokia MAC.
index 74708d5..30b9a6f 100644 (file)
@@ -432,10 +432,6 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
                                return;
                        }
                }
-
-               wl1251_debug(DEBUG_TX, "cb: waking queues");
-               ieee80211_wake_queues(wl->hw);
-               wl->tx_queue_stopped = false;
        }
 }
 
@@ -445,6 +441,7 @@ void wl1251_tx_complete(struct wl1251 *wl)
        int i, result_index, num_complete = 0;
        struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
        unsigned long flags;
+       int queue_len;
 
        if (unlikely(wl->state != WL1251_STATE_ON))
                return;
@@ -473,20 +470,6 @@ void wl1251_tx_complete(struct wl1251 *wl)
                }
        }
 
-       if (wl->tx_queue_stopped
-           &&
-           skb_queue_len(&wl->tx_queue) <= WL1251_TX_QUEUE_LOW_WATERMARK){
-
-               /* firmware buffer has space, restart queues */
-               wl1251_debug(DEBUG_TX, "tx_complete: waking queues");
-               spin_lock_irqsave(&wl->wl_lock, flags);
-               ieee80211_wake_queues(wl->hw);
-               wl->tx_queue_stopped = false;
-               spin_unlock_irqrestore(&wl->wl_lock, flags);
-               ieee80211_queue_work(wl->hw, &wl->tx_work);
-
-       }
-
        /* Every completed frame needs to be acknowledged */
        if (num_complete) {
                /*
@@ -535,6 +518,20 @@ void wl1251_tx_complete(struct wl1251 *wl)
        }
 
        wl->next_tx_complete = result_index;
+
+       queue_len = skb_queue_len(&wl->tx_queue);
+       if (wl->tx_queue_stopped &&
+           queue_len <= WL1251_TX_QUEUE_LOW_WATERMARK) {
+               /* firmware buffer has space, restart queues */
+               wl1251_debug(DEBUG_TX, "tx_complete: waking queues");
+               spin_lock_irqsave(&wl->wl_lock, flags);
+               ieee80211_wake_queues(wl->hw);
+               wl->tx_queue_stopped = false;
+               spin_unlock_irqrestore(&wl->wl_lock, flags);
+       }
+
+       if (queue_len > 0)
+               ieee80211_queue_work(wl->hw, &wl->tx_work);
 }
 
 /* caller must hold wl->mutex */