-commit 98a713933d8495f4078f561c1e651b738dd5b531
+commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sun Apr 27 14:49:03 2014 +0200
+Date: Fri May 23 19:58:14 2014 +0200
- ath9k_hw: do not lower ANI setting below default on AR913x
+ mac80211: reduce packet loss notifications under load
- When the amount of noise fluctuates strongly, low immunity settings
- can sometimes disrupt signal detection on AR913x chips. When that
- happens, no OFDM/CCK errors are reported anymore, and ANI tunes the
- radio to the lowest immunity settings.
- Usually rx/tx fails as well in that case.
+ During strong signal fluctuations under high throughput, few consecutive
+ failed A-MPDU transmissions can easily trigger packet loss notification,
+ and thus (in AP mode) client disconnection.
- To fix this, keep noise immunity settings at or above ANI default level,
- which will keep radio parameters at or above INI values.
+ Reduce the number of false positives by checking the A-MPDU status flag
+ and treating a failed A-MPDU as a single packet.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-commit 7cbb4c021bfd1e656f5b9953a947ab3c64e4e3b0
+commit 7b7843a36fbcc568834404c7430ff895d8502131
Author: Felix Fietkau <nbd@openwrt.org>
-Date: Thu Apr 10 10:49:01 2014 +0200
+Date: Fri May 23 19:26:32 2014 +0200
- mac80211: exclude AP_VLAN interfaces from tx power calculation
-
- Their power value is initialized to zero. This patch fixes an issue
- where the configured power drops to the minimum value when AP_VLAN
- interfaces are created/removed.
+ mac80211: fix a memory leak on sta rate selection table
Cc: stable@vger.kernel.org
+ Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-commit 0ca13e26341733bf9577287fb04a3bef0d2f5cc9
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Wed Apr 9 00:07:01 2014 +0200
-
- mac80211: suppress BSS info change notifications for AP_VLAN
-
- Fixes warnings on tx power changes
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit ec998e5991781ecdaad0911dc64f1c8d3749c308
+commit 96892d6aa0a153423070addf3070bc79578b3897
Author: Felix Fietkau <nbd@openwrt.org>
-Date: Tue Apr 8 23:42:17 2014 +0200
+Date: Mon May 19 21:20:49 2014 +0200
- ath9k: fix a scheduling while atomic bug in CSA handling
+ ath9k: avoid passing buffers to the hardware during flush
- Commit "ath9k: prepare for multi-interface CSA support" added a call to
- ieee80211_iterate_active_interfaces in atomic context (beacon tasklet),
- which is crashing.
- Use ieee80211_iterate_active_interfaces_atomic instead.
+ The commit "ath9k: fix possible hang on flush" changed the receive code
+ to always link rx descriptors of processed frames, even when flushing.
+ In some cases, this leads to flushed rx buffers being passed to the
+ hardware while rx is already stopped.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sun Apr 6 23:35:28 2014 +0200
-
- ath9k_hw: reduce ANI firstep range for older chips
-
- Use 0-8 instead of 0-16, which is closer to the old implementation.
- Also drop the overwrite of the firstep_low parameter to improve
- stability.
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-
---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-@@ -1004,11 +1004,9 @@ static bool ar5008_hw_ani_control_new(st
- case ATH9K_ANI_FIRSTEP_LEVEL:{
- u32 level = param;
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
+ * buffer (or rx fifo). This can incorrectly acknowledge packets
+ * to a sender if last desc is self-linked.
+ */
+-static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
++static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
++ bool flush)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
+ common->rx_bufsize,
+ 0);
-- value = level * 2;
-+ value = level;
- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
- AR_PHY_FIND_SIG_FIRSTEP, value);
-- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
-- AR_PHY_FIND_SIG_FIRSTEP_LOW, value);
+- if (sc->rx.rxlink == NULL)
+- ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+- else
++ if (sc->rx.rxlink)
+ *sc->rx.rxlink = bf->bf_daddr;
++ else if (!flush)
++ ath9k_hw_putrxbuf(ah, bf->bf_daddr);
- if (level != aniState->firstepLevel) {
- ath_dbg(common, ANI,
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -312,10 +312,9 @@ static void ath9k_csa_update_vif(void *d
+ sc->rx.rxlink = &ds->ds_link;
+ }
- void ath9k_csa_update(struct ath_softc *sc)
+-static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
++static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
++ bool flush)
{
-- ieee80211_iterate_active_interfaces(sc->hw,
-- IEEE80211_IFACE_ITER_NORMAL,
-- ath9k_csa_update_vif,
-- sc);
-+ ieee80211_iterate_active_interfaces_atomic(sc->hw,
-+ IEEE80211_IFACE_ITER_NORMAL,
-+ ath9k_csa_update_vif, sc);
- }
+ if (sc->rx.buf_hold)
+- ath_rx_buf_link(sc, sc->rx.buf_hold);
++ ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
- void ath9k_beacon_tasklet(unsigned long data)
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -152,6 +152,8 @@ static u32 ieee80211_hw_conf_chan(struct
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (!rcu_access_pointer(sdata->vif.chanctx_conf))
- continue;
-+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-+ continue;
- power = min(power, sdata->vif.bss_conf.txpower);
+ sc->rx.buf_hold = bf;
+ }
+@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
+ sc->rx.buf_hold = NULL;
+ sc->rx.rxlink = NULL;
+ list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
+- ath_rx_buf_link(sc, bf);
++ ath_rx_buf_link(sc, bf, false);
}
- rcu_read_unlock();
-@@ -203,7 +205,7 @@ void ieee80211_bss_info_change_notify(st
- {
- struct ieee80211_local *local = sdata->local;
-- if (!changed)
-+ if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- return;
+ /* We could have deleted elements so the list may be empty now */
+@@ -1118,12 +1120,12 @@ requeue_drop_frag:
+ requeue:
+ list_add_tail(&bf->list, &sc->rx.rxbuf);
+
+- if (edma) {
+- ath_rx_edma_buf_link(sc, qtype);
+- } else {
+- ath_rx_buf_relink(sc, bf);
++ if (!edma) {
++ ath_rx_buf_relink(sc, bf, flush);
+ if (!flush)
+ ath9k_hw_rxena(ah);
++ } else if (!flush) {
++ ath_rx_edma_buf_link(sc, qtype);
+ }
+
+ if (!budget--)
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -227,6 +227,7 @@ struct sta_info *sta_info_get_by_idx(str
+ */
+ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
+ {
++ struct ieee80211_sta_rates *rates;
+ int i;
- drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
---- a/drivers/net/wireless/ath/ath9k/ani.c
-+++ b/drivers/net/wireless/ath/ath9k/ani.c
-@@ -155,6 +155,9 @@ static void ath9k_hw_set_ofdm_nil(struct
- ATH9K_ANI_RSSI_THR_LOW,
- ATH9K_ANI_RSSI_THR_HIGH);
+ if (sta->rate_ctrl)
+@@ -238,6 +239,10 @@ void sta_info_free(struct ieee80211_loca
+ kfree(sta->tx_lat);
+ }
-+ if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL)
-+ immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
++ rates = rcu_dereference_protected(sta->sta.rates, true);
++ if (rates)
++ kfree(rates);
+
- if (!scan)
- aniState->ofdmNoiseImmunityLevel = immunityLevel;
+ sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
-@@ -235,6 +238,9 @@ static void ath9k_hw_set_cck_nil(struct
- BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
- ATH9K_ANI_RSSI_THR_HIGH);
+ kfree(sta);
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
+ */
+ #define STA_LOST_PKT_THRESHOLD 50
-+ if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL)
-+ immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
++static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
++{
++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++
++ /* This packet was aggregated but doesn't carry status info */
++ if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
++ !(info->flags & IEEE80211_TX_STAT_AMPDU))
++ return;
++
++ if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
++ return;
+
- if (ah->opmode == NL80211_IFTYPE_STATION &&
- BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
- immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
++ cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
++ sta->lost_packets, GFP_ATOMIC);
++ sta->lost_packets = 0;
++}
++
+ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+ {
+ struct sk_buff *skb2;
+@@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021
+ if (info->flags & IEEE80211_TX_STAT_ACK) {
+ if (sta->lost_packets)
+ sta->lost_packets = 0;
+- } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
+- cfg80211_cqm_pktloss_notify(sta->sdata->dev,
+- sta->sta.addr,
+- sta->lost_packets,
+- GFP_ATOMIC);
+- sta->lost_packets = 0;
++ } else {
++ ieee80211_lost_packet(sta, skb);
+ }
+ }
+