diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-05-19 19:51:45 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2014-05-19 19:51:45 +0000 |
commit | a97ece5cb3ae58f18f3ef326edb7c234bc95d620 (patch) | |
tree | e9d16b2a39173bf40b2500d8f861c41335600ab8 /package/kernel/mac80211/patches/300-pending_work.patch | |
parent | c3f88699cd5988a9323f22b079826b87a167aa17 (diff) | |
download | upstream-a97ece5cb3ae58f18f3ef326edb7c234bc95d620.tar.gz upstream-a97ece5cb3ae58f18f3ef326edb7c234bc95d620.tar.bz2 upstream-a97ece5cb3ae58f18f3ef326edb7c234bc95d620.zip |
ath9k: add some rx path fixes
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@40780 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/kernel/mac80211/patches/300-pending_work.patch')
-rw-r--r-- | package/kernel/mac80211/patches/300-pending_work.patch | 176 |
1 files changed, 172 insertions, 4 deletions
diff --git a/package/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch index ce19e7db5f..ef81721529 100644 --- a/package/kernel/mac80211/patches/300-pending_work.patch +++ b/package/kernel/mac80211/patches/300-pending_work.patch @@ -1,3 +1,26 @@ +commit 230ab8c1880266c9cfceac962e2d48309dea79a7 +Author: Felix Fietkau <nbd@openwrt.org> +Date: Mon May 19 21:48:56 2014 +0200 + + ath9k: re-schedule rx processing after budget exceeded + + Should improve rx stability under load + + Signed-off-by: Felix Fietkau <nbd@openwrt.org> + +commit 27647baeaee1b12bc3c57ccf1c7eba53bcd7fe53 +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> + commit 92e9dd662542683856e62a5e7e43fcf5b9da5c4a Author: Henning Rogge <hrogge@gmail.com> Date: Thu May 1 10:03:46 2014 +0200 @@ -359,7 +382,97 @@ Date: Sun Apr 6 23:35:28 2014 +0200 __skb_queue_head_init(&tid->retry_q); --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c -@@ -975,6 +975,7 @@ int ath_rx_tasklet(struct ath_softc *sc, +@@ -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; + } +@@ -106,7 +108,7 @@ static void ath_opmode_init(struct ath_s + } + + static bool ath_rx_edma_buf_link(struct ath_softc *sc, +- enum ath9k_rx_qtype qtype) ++ enum ath9k_rx_qtype qtype, bool flush) + { + struct ath_hw *ah = sc->sc_ah; + struct ath_rx_edma *rx_edma; +@@ -127,7 +129,8 @@ static bool ath_rx_edma_buf_link(struct + ah->caps.rx_status_len, DMA_TO_DEVICE); + + SKB_CB_ATHBUF(skb) = bf; +- ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype); ++ if (!flush) ++ ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype); + __skb_queue_tail(&rx_edma->rx_fifo, skb); + + return true; +@@ -145,7 +148,7 @@ static void ath_rx_addbuffer_edma(struct + } + + list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) +- if (!ath_rx_edma_buf_link(sc, qtype)) ++ if (!ath_rx_edma_buf_link(sc, qtype, false)) + break; + + } +@@ -442,7 +445,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 */ +@@ -636,7 +639,7 @@ static bool ath_edma_get_buffers(struct + if (ret == -EINVAL) { + /* corrupt descriptor, skip this one and the following one */ + list_add_tail(&bf->list, &sc->rx.rxbuf); +- ath_rx_edma_buf_link(sc, qtype); ++ ath_rx_edma_buf_link(sc, qtype, false); + + skb = skb_peek(&rx_edma->rx_fifo); + if (skb) { +@@ -645,7 +648,7 @@ static bool ath_edma_get_buffers(struct + + __skb_unlink(skb, &rx_edma->rx_fifo); + list_add_tail(&bf->list, &sc->rx.rxbuf); +- ath_rx_edma_buf_link(sc, qtype); ++ ath_rx_edma_buf_link(sc, qtype, false); + } + + bf = NULL; +@@ -975,6 +978,7 @@ int ath_rx_tasklet(struct ath_softc *sc, u64 tsf = 0; unsigned long flags; dma_addr_t new_buf_addr; @@ -367,7 +480,7 @@ Date: Sun Apr 6 23:35:28 2014 +0200 if (edma) dma_type = DMA_BIDIRECTIONAL; -@@ -1113,15 +1114,17 @@ requeue_drop_frag: +@@ -1113,15 +1117,17 @@ requeue_drop_frag: } requeue: list_add_tail(&bf->list, &sc->rx.rxbuf); @@ -375,10 +488,12 @@ Date: Sun Apr 6 23:35:28 2014 +0200 - continue; if (edma) { - ath_rx_edma_buf_link(sc, qtype); +- ath_rx_edma_buf_link(sc, qtype); ++ ath_rx_edma_buf_link(sc, qtype, flush); } else { - ath_rx_buf_relink(sc, bf); +- ath_rx_buf_relink(sc, bf); - ath9k_hw_rxena(ah); ++ ath_rx_buf_relink(sc, bf, flush); + if (!flush) + ath9k_hw_rxena(ah); } @@ -388,6 +503,13 @@ Date: Sun Apr 6 23:35:28 2014 +0200 } while (1); if (!(ah->imask & ATH9K_INT_RXEOL)) { +@@ -1129,5 +1135,5 @@ requeue: + ath9k_hw_set_interrupts(ah); + } + +- return 0; ++ return !budget; + } --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -86,7 +86,6 @@ static int ath_ahb_probe(struct platform @@ -565,3 +687,49 @@ Date: Sun Apr 6 23:35:28 2014 +0200 sta->last_rx_rate_idx = status->rate_idx; sta->last_rx_rate_flag = status->flag; sta->last_rx_rate_vht_flag = status->vht_flag; +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -442,6 +442,8 @@ void ath9k_tasklet(unsigned long data) + ath9k_ps_wakeup(sc); + spin_lock(&sc->sc_pcu_lock); + ++ sc->intrstatus = 0; ++ + if (status & ATH9K_INT_FATAL) { + type = RESET_TYPE_FATAL_INT; + ath9k_queue_reset(sc, type); +@@ -510,10 +512,12 @@ void ath9k_tasklet(unsigned long data) + if (status & rxmask) { + /* Check for high priority Rx first */ + if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && +- (status & ATH9K_INT_RXHP)) +- ath_rx_tasklet(sc, 0, true); ++ (status & ATH9K_INT_RXHP) && ++ ath_rx_tasklet(sc, 0, true)) ++ sc->intrstatus |= ATH9K_INT_RXHP; + +- ath_rx_tasklet(sc, 0, false); ++ if (ath_rx_tasklet(sc, 0, false)) ++ sc->intrstatus |= ATH9K_INT_RXLP; + } + + if (status & ATH9K_INT_TX) { +@@ -541,6 +545,9 @@ void ath9k_tasklet(unsigned long data) + + /* re-enable hardware interrupt */ + ath9k_hw_enable_interrupts(ah); ++ if (sc->intrstatus) ++ tasklet_schedule(&sc->intr_tq); ++ + out: + spin_unlock(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); +@@ -607,7 +614,7 @@ irqreturn_t ath_isr(int irq, void *dev) + return IRQ_NONE; + + /* Cache the status */ +- sc->intrstatus = status; ++ sc->intrstatus |= status; + + if (status & SCHED_INTR) + sched = true; |