From f63d946a67648dabfad5373921ac0b33b901490d Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 1 Feb 2013 09:34:24 -0500 Subject: [PATCH] Add patches to improve mac80211 latency and throughput (rhbz 830151) --- iwlegacy-add-flush-callback.patch | 103 +++++++++++++ kernel.spec | 9 ++ ...atency-and-throughput-while-software.patch | 142 ++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 iwlegacy-add-flush-callback.patch create mode 100644 mac80211-improve-latency-and-throughput-while-software.patch diff --git a/iwlegacy-add-flush-callback.patch b/iwlegacy-add-flush-callback.patch new file mode 100644 index 000000000..b8b656795 --- /dev/null +++ b/iwlegacy-add-flush-callback.patch @@ -0,0 +1,103 @@ +From 70277f47b58b174a6b0b891dcd06ae5125afb73b Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +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 +Signed-off-by: John W. Linville +--- + 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 a019e5053..baabf1aac 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 - 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 - 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 000000000..16f839418 --- /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 +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 +Signed-off-by: Johannes Berg +--- + 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 +