]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 3 Jun 2014 20:35:42 +0000 (13:35 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 3 Jun 2014 20:35:42 +0000 (13:35 -0700)
added patches:
mac80211-fix-on-channel-remain-on-channel.patch

queue-3.10/mac80211-fix-on-channel-remain-on-channel.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/mac80211-fix-on-channel-remain-on-channel.patch b/queue-3.10/mac80211-fix-on-channel-remain-on-channel.patch
new file mode 100644 (file)
index 0000000..a5c0b7f
--- /dev/null
@@ -0,0 +1,99 @@
+From b4b177a5556a686909e643f1e9b6434c10de079f Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Wed, 14 May 2014 15:34:41 +0200
+Subject: mac80211: fix on-channel remain-on-channel
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit b4b177a5556a686909e643f1e9b6434c10de079f upstream.
+
+Jouni reported that if a remain-on-channel was active on the
+same channel as the current operating channel, then the ROC
+would start, but any frames transmitted using mgmt-tx on the
+same channel would get delayed until after the ROC.
+
+The reason for this is that the ROC starts, but doesn't have
+any handling for "remain on the same channel", so it stops
+the interface queues. The later mgmt-tx then puts the frame
+on the interface queues (since it's on the current operating
+channel) and thus they get delayed until after the ROC.
+
+To fix this, add some logic to handle remaining on the same
+channel specially and not stop the queues etc. in this case.
+This not only fixes the bug but also improves behaviour in
+this case as data frames etc. can continue to flow.
+
+Reported-by: Jouni Malinen <j@w1.fi>
+Tested-by: Jouni Malinen <j@w1.fi>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ net/mac80211/ieee80211_i.h |    1 +
+ net/mac80211/offchannel.c  |   25 ++++++++++++++++++-------
+ 2 files changed, 19 insertions(+), 7 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -311,6 +311,7 @@ struct ieee80211_roc_work {
+       bool started, abort, hw_begun, notified;
+       bool to_be_freed;
++      bool on_channel;
+       unsigned long hw_start_time;
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -333,7 +333,7 @@ void ieee80211_sw_roc_work(struct work_s
+               container_of(work, struct ieee80211_roc_work, work.work);
+       struct ieee80211_sub_if_data *sdata = roc->sdata;
+       struct ieee80211_local *local = sdata->local;
+-      bool started;
++      bool started, on_channel;
+       mutex_lock(&local->mtx);
+@@ -354,14 +354,24 @@ void ieee80211_sw_roc_work(struct work_s
+       if (!roc->started) {
+               struct ieee80211_roc_work *dep;
+-              /* start this ROC */
+-              ieee80211_offchannel_stop_vifs(local);
++              WARN_ON(local->use_chanctx);
++
++              /* If actually operating on the desired channel (with at least
++               * 20 MHz channel width) don't stop all the operations but still
++               * treat it as though the ROC operation started properly, so
++               * other ROC operations won't interfere with this one.
++               */
++              roc->on_channel = roc->chan == local->_oper_chandef.chan;
+-              /* switch channel etc */
++              /* start this ROC */
+               ieee80211_recalc_idle(local);
+-              local->tmp_channel = roc->chan;
+-              ieee80211_hw_config(local, 0);
++              if (!roc->on_channel) {
++                      ieee80211_offchannel_stop_vifs(local);
++
++                      local->tmp_channel = roc->chan;
++                      ieee80211_hw_config(local, 0);
++              }
+               /* tell userspace or send frame */
+               ieee80211_handle_roc_started(roc);
+@@ -380,9 +390,10 @@ void ieee80211_sw_roc_work(struct work_s
+  finish:
+               list_del(&roc->list);
+               started = roc->started;
++              on_channel = roc->on_channel;
+               ieee80211_roc_notify_destroy(roc, !roc->abort);
+-              if (started) {
++              if (started && !on_channel) {
+                       ieee80211_flush_queues(local, NULL);
+                       local->tmp_channel = NULL;
index 64ba869e4e3ad916a7874521929c5be3eafe279d..6fbc2a2af41dd76b8304f231d4cba0cab2ea7729 100644 (file)
@@ -19,3 +19,4 @@ mac80211-fix-suspend-vs.-authentication-race.patch
 mm-thp-close-race-between-mremap-and-split_huge_page.patch
 x86-mm-hugetlb-add-missing-tlb-page-invalidation-for-hugetlb_cow.patch
 hwpoison-hugetlb-lock_page-unlock_page-does-not-match-for-handling-a-free-hugepage.patch
+mac80211-fix-on-channel-remain-on-channel.patch