wpa_supplicant: fix regressions introduced by the ibss-rsn changes
[openwrt.git] / package / mac80211 / patches / 300-pending_work.patch
index 4eb0a3f14e29b8a728787fa0e4cf837dd6d11cc2..30ce96e1703b96e278b85c3e0bc3918e16e86285 100644 (file)
  #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
                printk(KERN_DEBUG "STA %pM aid %d: PS buffer for AC %d\n",
                       sta->sta.addr, sta->sta.aid, ac);
+@@ -1060,6 +1065,7 @@ static bool ieee80211_tx_prep_agg(struct
+ {
+       bool queued = false;
+       bool reset_agg_timer = false;
++      struct sk_buff *purge_skb = NULL;
+       if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
+               info->flags |= IEEE80211_TX_CTL_AMPDU;
+@@ -1101,8 +1107,13 @@ static bool ieee80211_tx_prep_agg(struct
+                       info->control.vif = &tx->sdata->vif;
+                       info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
+                       __skb_queue_tail(&tid_tx->pending, skb);
++                      if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
++                              purge_skb = __skb_dequeue(&tid_tx->pending);
+               }
+               spin_unlock(&tx->sta->lock);
++
++              if (purge_skb)
++                      dev_kfree_skb(purge_skb);
+       }
+       /* reset session timer */
 --- a/net/mac80211/ieee80211_i.h
 +++ b/net/mac80211/ieee80211_i.h
 @@ -480,7 +480,7 @@ struct ieee80211_if_ibss {
  }
  
  /*
-@@ -1011,6 +1010,8 @@ static int ath9k_rx_skb_preprocess(struc
+@@ -988,8 +987,6 @@ static int ath9k_rx_skb_preprocess(struc
+ {
+       struct ath_hw *ah = common->ah;
+-      memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
+-
+       /*
+        * everything but the rate is checked here, the rate check is done
+        * separately to avoid doing two lookups for a rate for each frame.
+@@ -1011,6 +1008,8 @@ static int ath9k_rx_skb_preprocess(struc
        rx_status->signal = ah->noise + rx_stats->rs_rssi;
        rx_status->antenna = rx_stats->rs_antenna;
        rx_status->flag |= RX_FLAG_MACTIME_MPDU;
  
        return 0;
  }
+@@ -1845,6 +1844,8 @@ int ath_rx_tasklet(struct ath_softc *sc,
+               if (sc->sc_flags & SC_OP_RXFLUSH)
+                       goto requeue_drop_frag;
++              memset(rxs, 0, sizeof(struct ieee80211_rx_status));
++
+               rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
+               if (rs.rs_tstamp > tsf_lower &&
+                   unlikely(rs.rs_tstamp - tsf_lower > 0x10000000))
 --- a/drivers/net/wireless/ath/ath9k/beacon.c
 +++ b/drivers/net/wireless/ath/ath9k/beacon.c
 @@ -91,7 +91,7 @@ static void ath_beacon_setup(struct ath_
  
                if (on)
                        REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -430,10 +430,14 @@ void rt2x00lib_txdone(struct queue_entry
+       /*
+        * If the data queue was below the threshold before the txdone
+        * handler we must make sure the packet queue in the mac80211 stack
+-       * is reenabled when the txdone handler has finished.
++       * is reenabled when the txdone handler has finished. This has to be
++       * serialized with rt2x00mac_tx(), otherwise we can wake up queue
++       * before it was stopped.
+        */
++      spin_lock_bh(&entry->queue->tx_lock);
+       if (!rt2x00queue_threshold(entry->queue))
+               rt2x00queue_unpause_queue(entry->queue);
++      spin_unlock_bh(&entry->queue->tx_lock);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
+--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
++++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
+@@ -152,13 +152,22 @@ void rt2x00mac_tx(struct ieee80211_hw *h
+       if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false)))
+               goto exit_fail;
++      /*
++       * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
++       * we should not use spin_lock_bh variant as bottom halve was already
++       * disabled before ieee80211_xmit() call.
++       */
++      spin_lock(&queue->tx_lock);
+       if (rt2x00queue_threshold(queue))
+               rt2x00queue_pause_queue(queue);
++      spin_unlock(&queue->tx_lock);
+       return;
+  exit_fail:
++      spin_lock(&queue->tx_lock);
+       rt2x00queue_pause_queue(queue);
++      spin_unlock(&queue->tx_lock);
+  exit_free_skb:
+       ieee80211_free_txskb(hw, skb);
+ }
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -619,6 +619,9 @@ int rt2x00queue_write_tx_frame(struct da
+       else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
+               rt2x00queue_align_frame(skb);
++      /*
++       * That function must be called with bh disabled.
++       */
+       spin_lock(&queue->tx_lock);
+       if (unlikely(rt2x00queue_full(queue))) {