ath9k: add a tx locking fix
[openwrt.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
index a790183..be82f37 100644 (file)
@@ -1,3 +1,43 @@
+commit a63caf0a357ad5c1f08d6b7827dc76c451445017
+Author: Stanislaw Gruszka <sgruszka@redhat.com>
+Date:   Wed Feb 19 13:15:17 2014 +0100
+
+    ath9k: protect tid->sched check
+    
+    We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That
+    is race condition which can result of doing list_del(&tid->list) twice
+    (second time with poisoned list node) and cause crash like shown below:
+    
+    [424271.637220] BUG: unable to handle kernel paging request at 00100104
+    [424271.637328] IP: [<f90fc072>] ath_tx_aggr_sleep+0x62/0xe0 [ath9k]
+    ...
+    [424271.639953] Call Trace:
+    [424271.639998]  [<f90f6900>] ? ath9k_get_survey+0x110/0x110 [ath9k]
+    [424271.640083]  [<f90f6942>] ath9k_sta_notify+0x42/0x50 [ath9k]
+    [424271.640177]  [<f809cfef>] sta_ps_start+0x8f/0x1c0 [mac80211]
+    [424271.640258]  [<c10f730e>] ? free_compound_page+0x2e/0x40
+    [424271.640346]  [<f809e915>] ieee80211_rx_handlers+0x9d5/0x2340 [mac80211]
+    [424271.640437]  [<c112f048>] ? kmem_cache_free+0x1d8/0x1f0
+    [424271.640510]  [<c1345a84>] ? kfree_skbmem+0x34/0x90
+    [424271.640578]  [<c10fc23c>] ? put_page+0x2c/0x40
+    [424271.640640]  [<c1345a84>] ? kfree_skbmem+0x34/0x90
+    [424271.640706]  [<c1345a84>] ? kfree_skbmem+0x34/0x90
+    [424271.640787]  [<f809dde3>] ? ieee80211_rx_handlers_result+0x73/0x1d0 [mac80211]
+    [424271.640897]  [<f80a07a0>] ieee80211_prepare_and_rx_handle+0x520/0xad0 [mac80211]
+    [424271.641009]  [<f809e22d>] ? ieee80211_rx_handlers+0x2ed/0x2340 [mac80211]
+    [424271.641104]  [<c13846ce>] ? ip_output+0x7e/0xd0
+    [424271.641182]  [<f80a1057>] ieee80211_rx+0x307/0x7c0 [mac80211]
+    [424271.641266]  [<f90fa6ee>] ath_rx_tasklet+0x88e/0xf70 [ath9k]
+    [424271.641358]  [<f80a0f2c>] ? ieee80211_rx+0x1dc/0x7c0 [mac80211]
+    [424271.641445]  [<f90f82db>] ath9k_tasklet+0xcb/0x130 [ath9k]
+    
+    Bug report:
+    https://bugzilla.kernel.org/show_bug.cgi?id=70551
+    
+    Reported-and-tested-by: Max Sydorenko <maxim.stargazer@gmail.com>
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+
 commit 82ed9e3ccc02797df2ffe4b78127c4cd5f799a41
 Author: Felix Fietkau <nbd@openwrt.org>
 Date:   Tue Feb 11 15:54:13 2014 +0100
@@ -2732,3 +2772,25 @@ Date:   Thu Jan 23 20:06:34 2014 +0100
        /* use the data classifier to determine what 802.1d tag the
         * data frame has */
        rcu_read_lock();
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_
+       for (tidno = 0, tid = &an->tid[tidno];
+            tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
+-              if (!tid->sched)
+-                      continue;
+-
+               ac = tid->ac;
+               txq = ac->txq;
+               ath_txq_lock(sc, txq);
++              if (!tid->sched) {
++                      ath_txq_unlock(sc, txq);
++                      continue;
++              }
++
+               buffered = ath_tid_has_buffered(tid);
+               tid->sched = false;