[kernel] Add patches to improve mac80211 latency and throughput (rhbz 830151)

Josh Boyer jwboyer at fedoraproject.org
Fri Feb 1 15:25:50 UTC 2013


commit f63d946a67648dabfad5373921ac0b33b901490d
Author: Josh Boyer <jwboyer at redhat.com>
Date:   Fri Feb 1 09:34:24 2013 -0500

    Add patches to improve mac80211 latency and throughput (rhbz 830151)

 iwlegacy-add-flush-callback.patch                  |  103 ++++++++++++++
 kernel.spec                                        |    9 ++
 ...ove-latency-and-throughput-while-software.patch |  142 ++++++++++++++++++++
 3 files changed, 254 insertions(+), 0 deletions(-)
---
diff --git a/iwlegacy-add-flush-callback.patch b/iwlegacy-add-flush-callback.patch
new file mode 100644
index 0000000..b8b6567
--- /dev/null
+++ b/iwlegacy-add-flush-callback.patch
@@ -0,0 +1,103 @@
+From 70277f47b58b174a6b0b891dcd06ae5125afb73b Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka at redhat.com>
+Date: Thu, 20 Dec 2012 14:31:51 +0100
+Subject: [PATCH] iwlegacy: add flush callback
+
+Dump implementation of flush, which just wait until all TX queues
+become empty.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka at redhat.com>
+Signed-off-by: John W. Linville <linville at tuxdriver.com>
+---
+ drivers/net/wireless/iwlegacy/3945-mac.c |    1 +
+ drivers/net/wireless/iwlegacy/4965-mac.c |    1 +
+ drivers/net/wireless/iwlegacy/common.c   |   36 ++++++++++++++++++++++++++++++
+ drivers/net/wireless/iwlegacy/common.h   |    1 +
+ 4 files changed, 39 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
+index d604b40..962400a 100644
+--- a/drivers/net/wireless/iwlegacy/3945-mac.c
++++ b/drivers/net/wireless/iwlegacy/3945-mac.c
+@@ -3474,6 +3474,7 @@ struct ieee80211_ops il3945_mac_ops = {
+ 	.sta_add = il3945_mac_sta_add,
+ 	.sta_remove = il_mac_sta_remove,
+ 	.tx_last_beacon = il_mac_tx_last_beacon,
++	.flush = il_mac_flush,
+ };
+ 
+ static int
+diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
+index 6a86ed4..c40020c 100644
+--- a/drivers/net/wireless/iwlegacy/4965-mac.c
++++ b/drivers/net/wireless/iwlegacy/4965-mac.c
+@@ -6308,6 +6308,7 @@ const struct ieee80211_ops il4965_mac_ops = {
+ 	.sta_remove = il_mac_sta_remove,
+ 	.channel_switch = il4965_mac_channel_switch,
+ 	.tx_last_beacon = il_mac_tx_last_beacon,
++	.flush = il_mac_flush,
+ };
+ 
+ static int
+diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
+index 7e16d10..56b8021 100644
+--- a/drivers/net/wireless/iwlegacy/common.c
++++ b/drivers/net/wireless/iwlegacy/common.c
+@@ -4707,6 +4707,42 @@ out:
+ }
+ EXPORT_SYMBOL(il_mac_change_interface);
+ 
++void
++il_mac_flush(struct ieee80211_hw *hw, bool drop)
++{
++	struct il_priv *il = hw->priv;
++	unsigned long timeout = jiffies + msecs_to_jiffies(500);
++	int i;
++
++	mutex_lock(&il->mutex);
++	D_MAC80211("enter\n");
++
++	if (il->txq == NULL)
++		goto out;
++
++	for (i = 0; i < il->hw_params.max_txq_num; i++) {
++		struct il_queue *q;
++
++		if (i == il->cmd_queue)
++			continue;
++
++		q = &il->txq[i].q;
++		if (q->read_ptr == q->write_ptr)
++			continue;
++
++		if (time_after(jiffies, timeout)) {
++			IL_ERR("Failed to flush queue %d\n", q->id);
++			break;
++		}
++
++		msleep(20);
++	}
++out:
++	D_MAC80211("leave\n");
++	mutex_unlock(&il->mutex);
++}
++EXPORT_SYMBOL(il_mac_flush);
++
+ /*
+  * On every watchdog tick we check (latest) time stamp. If it does not
+  * change during timeout period and queue is not empty we reset firmware.
+diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
+index a9a569f..37fe553 100644
+--- a/drivers/net/wireless/iwlegacy/common.h
++++ b/drivers/net/wireless/iwlegacy/common.h
+@@ -1723,6 +1723,7 @@ void il_mac_remove_interface(struct ieee80211_hw *hw,
+ 			     struct ieee80211_vif *vif);
+ int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ 			    enum nl80211_iftype newtype, bool newp2p);
++void il_mac_flush(struct ieee80211_hw *hw, bool drop);
+ int il_alloc_txq_mem(struct il_priv *il);
+ void il_free_txq_mem(struct il_priv *il);
+ 
+-- 
+1.7.7.6
+
diff --git a/kernel.spec b/kernel.spec
index a019e50..baabf1a 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -748,6 +748,10 @@ Patch21241: Input-add-support-for-Cypress-PS2-Trackpads.patch
 # https://fedoraproject.org/wiki/Features/Checkpoint_Restore
 Patch21242: criu-no-expert.patch
 
+#rhbz 830151
+Patch21243: mac80211-improve-latency-and-throughput-while-software.patch
+Patch21244: iwlegacy-add-flush-callback.patch
+
 # END OF PATCH DEFINITIONS
 
 %endif
@@ -1446,6 +1450,10 @@ ApplyPatch Input-add-support-for-Cypress-PS2-Trackpads.patch
 # https://fedoraproject.org/wiki/Features/Checkpoint_Restore
 ApplyPatch criu-no-expert.patch
 
+#rhbz 830151
+ApplyPatch mac80211-improve-latency-and-throughput-while-software.patch
+ApplyPatch iwlegacy-add-flush-callback.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2304,6 +2312,7 @@ fi
 * Fri Feb 01 2013 Josh Boyer <jwboyer at redhat.com>
 - Linux v3.8-rc6
 - Enable CONFIG_DMA_API_DEBUG
+- Add patches to improve mac80211 latency and throughput (rhbz 830151)
 
 * Thu Jan 31 2013 Josh Boyer <jwboyer at redhat.com> - 3.8.0-0.rc5.git3.1
 - Linux v3.8-rc5-245-g04c2eee
diff --git a/mac80211-improve-latency-and-throughput-while-software.patch b/mac80211-improve-latency-and-throughput-while-software.patch
new file mode 100644
index 0000000..16f8394
--- /dev/null
+++ b/mac80211-improve-latency-and-throughput-while-software.patch
@@ -0,0 +1,142 @@
+From c790794fcb461842e6ae1d764b7f68e9a789d149 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka at redhat.com>
+Date: Wed, 23 Jan 2013 12:32:45 +0100
+Subject: [PATCH] mac80211: improve latency and throughput while software
+ scanning
+
+Patch vastly improve latency while scanning. Slight throughput
+improvements were observed as well. Is intended for improve performance
+of voice and video applications, when scan is periodically requested by
+user space (i.e. default NetworkManager behaviour).
+
+Patch remove latency requirement based on PM_QOS_NETWORK_LATENCY,
+this value is 2000 seconds by default (i.e. approximately 0.5 hour !?!).
+
+Also remove listen interval requirement, which based on beaconing and
+depending on BSS parameters. It can make we stay off-channel for a
+second or more.
+
+Instead try to offer the best latency that we could, i.e. be off-channel
+no longer than PASSIVE channel scan time: 125 ms. That mean we will
+scan two ACTIVE channels and go back to on-channel, and one PASSIVE
+channel, and go back to on-channel.
+
+Patch also decrease PASSIVE channel scan time to about 110 ms.
+
+As drawback patch increase overall scan time. On my tests, when scanning
+both 2GHz and 5GHz bands, scanning time increase from 5 seconds up to 10
+seconds. Since that increase happen only when we are associated, I think
+it can be acceptable. If eventually better scan time is needed for
+situations when we lose signal and quickly need to decide to which AP
+roam, additional scan flag or parameter can be introduced.
+
+I tested patch by doing:
+
+while true; do iw dev wlan0 scan; sleep 3; done > /dev/null
+
+and
+
+ping -i0.2 -c 1000 HOST
+
+on remote and local machine, results are as below:
+
+* Ping from local periodically scanning machine to AP:
+Unpatched: rtt min/avg/max/mdev = 0.928/24.946/182.135/36.873 ms
+Patched:   rtt min/avg/max/mdev = 0.928/19.678/150.845/33.130 ms
+
+* Ping from remote machine to periodically scanning machine:
+Unpatched: rtt min/avg/max/mdev = 1.637/120.683/709.139/164.337 ms
+Patched:   rtt min/avg/max/mdev = 1.807/26.893/201.435/40.284 ms
+
+Throughput measured by scp show following results.
+
+* Upload to periodically scanning machine:
+Unpatched: 3.9MB/s   03:15
+Patched:   4.3MB/s   02:58
+
+* Download from periodically scanning machine:
+Unpatched: 5.5MB/s   02:17
+Patched:   6.2MB/s   02:02
+
+Signed-off-by: Stanislaw Gruszka <sgruszka at redhat.com>
+Signed-off-by: Johannes Berg <johannes.berg at intel.com>
+---
+ net/mac80211/scan.c | 32 +++++---------------------------
+ 1 file changed, 5 insertions(+), 27 deletions(-)
+
+diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
+index bf82e69..e6b2ebc 100644
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -27,7 +27,7 @@
+ 
+ #define IEEE80211_PROBE_DELAY (HZ / 33)
+ #define IEEE80211_CHANNEL_TIME (HZ / 33)
+-#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8)
++#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 9)
+ 
+ static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
+ {
+@@ -547,8 +547,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
+ 	bool associated = false;
+ 	bool tx_empty = true;
+ 	bool bad_latency;
+-	bool listen_int_exceeded;
+-	unsigned long min_beacon_int = 0;
+ 	struct ieee80211_sub_if_data *sdata;
+ 	struct ieee80211_channel *next_chan;
+ 	enum mac80211_scan_state next_scan_state;
+@@ -567,11 +565,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
+ 			if (sdata->u.mgd.associated) {
+ 				associated = true;
+ 
+-				if (sdata->vif.bss_conf.beacon_int <
+-				    min_beacon_int || min_beacon_int == 0)
+-					min_beacon_int =
+-						sdata->vif.bss_conf.beacon_int;
+-
+ 				if (!qdisc_all_tx_empty(sdata->dev)) {
+ 					tx_empty = false;
+ 					break;
+@@ -588,34 +581,19 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
+ 	 * see if we can scan another channel without interfering
+ 	 * with the current traffic situation.
+ 	 *
+-	 * Since we don't know if the AP has pending frames for us
+-	 * we can only check for our tx queues and use the current
+-	 * pm_qos requirements for rx. Hence, if no tx traffic occurs
+-	 * at all we will scan as many channels in a row as the pm_qos
+-	 * latency allows us to. Additionally we also check for the
+-	 * currently negotiated listen interval to prevent losing
+-	 * frames unnecessarily.
+-	 *
+-	 * Otherwise switch back to the operating channel.
++	 * Keep good latency, do not stay off-channel more than 125 ms.
+ 	 */
+ 
+ 	bad_latency = time_after(jiffies +
+-			ieee80211_scan_get_channel_time(next_chan),
+-			local->leave_oper_channel_time +
+-			usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
+-
+-	listen_int_exceeded = time_after(jiffies +
+-			ieee80211_scan_get_channel_time(next_chan),
+-			local->leave_oper_channel_time +
+-			usecs_to_jiffies(min_beacon_int * 1024) *
+-			local->hw.conf.listen_interval);
++				 ieee80211_scan_get_channel_time(next_chan),
++				 local->leave_oper_channel_time + HZ / 8);
+ 
+ 	if (associated && !tx_empty) {
+ 		if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+ 			next_scan_state = SCAN_ABORT;
+ 		else
+ 			next_scan_state = SCAN_SUSPEND;
+-	} else if (associated && (bad_latency || listen_int_exceeded)) {
++	} else if (associated && bad_latency) {
+ 		next_scan_state = SCAN_SUSPEND;
+ 	} else {
+ 		next_scan_state = SCAN_SET_CHANNEL;
+-- 
+1.8.1
+


More information about the scm-commits mailing list