ath9k: merge a fix for queue start/stop handling (fixes #18164, #18130)
[oweals/openwrt.git] / package / kernel / mac80211 / patches / 313-ath9k-Check-for-pending-frames-properly.patch
1 From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
2 Date: Fri, 17 Oct 2014 07:40:18 +0530
3 Subject: [PATCH] ath9k: Check for pending frames properly
4
5 Pending frames in the driver can be present
6 either in the HW queues or SW. ath9k_has_pending_frames()
7 currently checks for the HW queues first and then
8 checks if any ACs are queued in the driver.
9
10 In MCC mode, we need to check the HW queues alone, since
11 the SW queues are just marked as 'stopped' - they will
12 be processed in the next context switch. But since we
13 don't differentiate this now, mention whether we want
14 to check if there are frames in the SW queues.
15
16 * The flush() callback checks both HW and SW queues.
17 * The tx_frames_pending() callback does the same.
18 * The call to __ath9k_flush() in MCC mode checks HW queues alone.
19
20 Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
21 ---
22
23 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
24 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
25 @@ -715,7 +715,8 @@ int ath_update_survey_stats(struct ath_s
26  void ath_update_survey_nf(struct ath_softc *sc, int channel);
27  void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
28  void ath_ps_full_sleep(unsigned long data);
29 -void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
30 +void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
31 +                  bool sw_pending);
32  
33  /**********/
34  /* BTCOEX */
35 --- a/drivers/net/wireless/ath/ath9k/channel.c
36 +++ b/drivers/net/wireless/ath/ath9k/channel.c
37 @@ -1137,10 +1137,11 @@ void ath_chanctx_set_next(struct ath_sof
38                 ath9k_chanctx_stop_queues(sc, sc->cur_chan);
39                 queues_stopped = true;
40  
41 -               __ath9k_flush(sc->hw, ~0, true);
42 +               __ath9k_flush(sc->hw, ~0, true, false);
43  
44                 if (ath_chanctx_send_ps_frame(sc, true))
45 -                       __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false);
46 +                       __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO),
47 +                                     false, false);
48  
49                 send_ps = true;
50                 spin_lock_bh(&sc->chan_lock);
51 --- a/drivers/net/wireless/ath/ath9k/main.c
52 +++ b/drivers/net/wireless/ath/ath9k/main.c
53 @@ -54,7 +54,8 @@ u8 ath9k_parse_mpdudensity(u8 mpdudensit
54         }
55  }
56  
57 -static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
58 +static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq,
59 +                                    bool sw_pending)
60  {
61         bool pending = false;
62  
63 @@ -65,6 +66,9 @@ static bool ath9k_has_pending_frames(str
64                 goto out;
65         }
66  
67 +       if (!sw_pending)
68 +               goto out;
69 +
70         if (txq->mac80211_qnum >= 0) {
71                 struct list_head *list;
72  
73 @@ -2003,7 +2007,8 @@ static void ath9k_set_coverage_class(str
74         mutex_unlock(&sc->mutex);
75  }
76  
77 -static bool ath9k_has_tx_pending(struct ath_softc *sc)
78 +static bool ath9k_has_tx_pending(struct ath_softc *sc,
79 +                                bool sw_pending)
80  {
81         int i, npend = 0;
82  
83 @@ -2011,7 +2016,8 @@ static bool ath9k_has_tx_pending(struct 
84                 if (!ATH_TXQ_SETUP(sc, i))
85                         continue;
86  
87 -               npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
88 +               npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i],
89 +                                                sw_pending);
90                 if (npend)
91                         break;
92         }
93 @@ -2025,11 +2031,12 @@ static void ath9k_flush(struct ieee80211
94         struct ath_softc *sc = hw->priv;
95  
96         mutex_lock(&sc->mutex);
97 -       __ath9k_flush(hw, queues, drop);
98 +       __ath9k_flush(hw, queues, drop, true);
99         mutex_unlock(&sc->mutex);
100  }
101  
102 -void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
103 +void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
104 +                  bool sw_pending)
105  {
106         struct ath_softc *sc = hw->priv;
107         struct ath_hw *ah = sc->sc_ah;
108 @@ -2056,7 +2063,7 @@ void __ath9k_flush(struct ieee80211_hw *
109         ath_dbg(common, CHAN_CTX,
110                 "Flush timeout: %d\n", jiffies_to_msecs(timeout));
111  
112 -       if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc),
113 +       if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc, sw_pending),
114                                timeout) > 0)
115                 drop = false;
116  
117 @@ -2079,7 +2086,7 @@ static bool ath9k_tx_frames_pending(stru
118  {
119         struct ath_softc *sc = hw->priv;
120  
121 -       return ath9k_has_tx_pending(sc);
122 +       return ath9k_has_tx_pending(sc, true);
123  }
124  
125  static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)