[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 08:08:07 EDT 2015


Hi,

Ok, I'll do it.

In email dated Пятница - 11 сентября 2015 13:39:54 user John Crispin wrote:
> Hi,
> 
> before looking at this in detail, could please send a properly formatted
> patch. the patch you sent is not using the unified option when
> generating it. upstream linux-wireless wont accept it otherwise and we
> wont either.
> 
> also please prefix the email with "mac80211: " so that we know which
> subsystem it applies to.
> 
> that being said, the bug has been annoying me for eons and i never had
> time to fix it so thanks for the time debugging this :)
> 
> 	John
> 
> 
> On 11/09/2015 13:33, N.Leiten wrote:
> > 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
> > 
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel at lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
_______________________________________________
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