You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openwrt/package/kernel/mac80211/patches/300-pending_work.patch

164 lines
4.9 KiB
Diff

commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
Author: Felix Fietkau <nbd@openwrt.org>
Date: Fri May 23 19:58:14 2014 +0200
mac80211: reduce packet loss notifications under load
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.
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 7b7843a36fbcc568834404c7430ff895d8502131
Author: Felix Fietkau <nbd@openwrt.org>
Date: Fri May 23 19:26:32 2014 +0200
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 96892d6aa0a153423070addf3070bc79578b3897
Author: Felix Fietkau <nbd@openwrt.org>
Date: Mon May 19 21:20:49 2014 +0200
ath9k: avoid passing buffers to the hardware during flush
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>
--- 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);
- 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);
sc->rx.rxlink = &ds->ds_link;
}
-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)
{
if (sc->rx.buf_hold)
- ath_rx_buf_link(sc, sc->rx.buf_hold);
+ ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
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);
}
/* 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;
if (sta->rate_ctrl)
@@ -238,6 +239,10 @@ void sta_info_free(struct ieee80211_loca
kfree(sta->tx_lat);
}
+ rates = rcu_dereference_protected(sta->sta.rates, true);
+ if (rates)
+ kfree(rates);
+
sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
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
+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;
+
+ 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);
}
}