Fix instability of Ralink WiFi general queue management on high load.
rt2x00 driver logs in dmesg "Dropping frame due to full queue ..." several 
times and at some point get stuck.

Solutions in patch:
1) Increasing number of frames in each TX queue helps with speed and decreases 
queue overflows. Actually 256 frames can be increased to 512 (this number of 
frames used in proprietary drivers for every queue).
2) Setting number of frames in TX/RX queues to equal values resolves async 
speed behaviour with better RX on AP-side (uplink from STAs), where it needs to 
be at least equal or better on TX queue on AP (download to STA).
3) In rt2x00mac.c additional check for queue full added and reassignment in 
this case, so interface will not drop frame.
4) Fixes in queue initialization. Default values for AC_BK, AC_BE, AC_VI, AC_VO 
set from WMM.

Tested on RT3883, RT5350, MT7620 SoCs and on RT3092 pcie interface for 10 days.

I'm planning to send this patch to mac80211 soon, but need to be sure that it 
works on other Ralink/Mediatek platforms and it's appropriate to do so.


Signed-off-by: Nick Leiten <[email protected]>
diff --git a/package/kernel/mac80211/patches/999-rt2x00-queue-update.patch 
b/package/kernel/mac80211/patches/999-rt2x00-queue-update.patch
new file mode 100644
index 0000000..9239bec
--- /dev/null
+++ b/package/kernel/mac80211/patches/999-rt2x00-queue-update.patch
@@ -0,0 +1,142 @@
+Only in compat-wireless-2015-03-09/drivers/net/wireless/rt2x00: limit
+diff -c -r 
compat-wireless-2015-03-09-orig/drivers/net/wireless/rt2x00/rt2800mmio.c 
compat-wireless-2015-03-09/drivers/net/wireless/rt2x00/rt2800mmio.c
+*** compat-wireless-2015-03-09-orig/drivers/net/wireless/rt2x00/rt2800mmio.c   
2015-06-16 13:02:30.000000000 +0300
+--- compat-wireless-2015-03-09/drivers/net/wireless/rt2x00/rt2800mmio.c        
2015-09-04 11:50:09.665148666 +0300
+***************
+*** 700,706 ****
+  
+       switch (queue->qid) {
+       case QID_RX:
+!              queue->limit = 128;
+               queue->data_size = AGGREGATION_SIZE;
+               queue->desc_size = RXD_DESC_SIZE;
+               queue->winfo_size = rxwi_size;
+--- 700,706 ----
+  
+       switch (queue->qid) {
+       case QID_RX:
+!              queue->limit = 256;
+               queue->data_size = AGGREGATION_SIZE;
+               queue->desc_size = RXD_DESC_SIZE;
+               queue->winfo_size = rxwi_size;
+***************
+*** 711,717 ****
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+!              queue->limit = 64;
+               queue->data_size = AGGREGATION_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->winfo_size = txwi_size;
+--- 711,717 ----
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+!              queue->limit = 256;
+               queue->data_size = AGGREGATION_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->winfo_size = txwi_size;
+diff -c -r 
compat-wireless-2015-03-09-orig/drivers/net/wireless/rt2x00/rt2x00mac.c 
compat-wireless-2015-03-09/drivers/net/wireless/rt2x00/rt2x00mac.c
+*** compat-wireless-2015-03-09-orig/drivers/net/wireless/rt2x00/rt2x00mac.c    
2015-06-16 13:02:30.000000000 +0300
+--- compat-wireless-2015-03-09/drivers/net/wireless/rt2x00/rt2x00mac.c 
2015-09-04 11:47:45.845449209 +0300
+***************
+*** 26,31 ****
+--- 26,32 ----
+  
+  #include "rt2x00.h"
+  #include "rt2x00lib.h"
++ #include "rt2x00queue.h"
+  
+  static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
+                               struct data_queue *queue,
+***************
+*** 115,120 ****
+--- 116,141 ----
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               goto exit_free_skb;
+  
++      /* Dirty hack for Queue overrun protection,
++       * if AC_VO/AC_VI/AC_BE is full, use next queue.
++       * if AC_BK is full use previous queue.
++       */
++      if (qid < 4) {
++              queue = rt2x00queue_get_tx_queue(rt2x00dev,qid);
++              if (unlikely(rt2x00queue_full(queue))){
++                      switch(qid){
++                              case 0: /* QID_AC_VO */
++                              case 1: /* QID_AC_VI */
++                              case 2: /* QID_AC_BE */
++                                      qid++;
++                                      break;
++                              case 3: /* QID_AC_BK */
++                                      qid--;
++                                      break;
++                      }
++              }
++      }
++      
+       /*
+        * Use the ATIM queue if appropriate and present.
+        */
+diff -c -r 
compat-wireless-2015-03-09-orig/drivers/net/wireless/rt2x00/rt2x00queue.c 
compat-wireless-2015-03-09/drivers/net/wireless/rt2x00/rt2x00queue.c
+*** compat-wireless-2015-03-09-orig/drivers/net/wireless/rt2x00/rt2x00queue.c  
2015-03-10 05:37:16.000000000 +0200
+--- compat-wireless-2015-03-09/drivers/net/wireless/rt2x00/rt2x00queue.c       
2015-09-04 11:49:37.911446071 +0300
+***************
+*** 1213,1228 ****
+  static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
+                            struct data_queue *queue, enum data_queue_qid qid)
+  {
+       mutex_init(&queue->status_lock);
+       spin_lock_init(&queue->tx_lock);
+       spin_lock_init(&queue->index_lock);
+  
+       queue->rt2x00dev = rt2x00dev;
+       queue->qid = qid;
+!      queue->txop = 0;
+!      queue->aifs = 2;
+!      queue->cw_min = 5;
+!      queue->cw_max = 10;
+  
+       rt2x00dev->ops->queue_init(queue);
+  
+--- 1213,1252 ----
+  static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
+                            struct data_queue *queue, enum data_queue_qid qid)
+  {
++      /* Use default values for each queue type */
++      unsigned short cwmin = 5, cwmax = 10, aifs = 2, txop = 0;
++      
++      switch (qid) {
++              case QID_AC_VO:
++                      cwmin = 2;
++                      cwmax = 3;
++                      txop = 47;
++                      break;
++              case QID_AC_VI:
++                      cwmin = 3;
++                      cwmax = 4;
++                      txop = 94;
++                      break;
++              case QID_AC_BE:
++                      cwmin = 4;
++                      aifs = 3;
++                      break;
++              case QID_AC_BK:
++                      cwmin = 4;
++                      aifs = 7;
++                      break;
++      }
++      
+       mutex_init(&queue->status_lock);
+       spin_lock_init(&queue->tx_lock);
+       spin_lock_init(&queue->index_lock);
+  
+       queue->rt2x00dev = rt2x00dev;
+       queue->qid = qid;
+!      queue->txop = txop;
+!      queue->aifs = aifs;
+!      queue->cw_min = cwmin;
+!      queue->cw_max = cwmax;
+  
+       rt2x00dev->ops->queue_init(queue);
+  
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to