[OpenWrt-Devel] [PATCH] Fix 'Dropping frame due to full tx queue' for Ralink wifi get stuck.
N.Leiten
nickleiten at gmail.com
Fri Sep 11 07:33:43 EDT 2015
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 <nickleiten at gmail.com>
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
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list