40e095b970ac7da38362b4450dd1b82d5b55a696
[openwrt.git] / package / kernel / mac80211 / patches / 324-ath9k-Improve-flush-in-mcc-mode.patch
1 From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
2 Date: Fri, 17 Oct 2014 07:40:29 +0530
3 Subject: [PATCH] ath9k: Improve flush() in mcc mode
4
5 The flush timeout in MCC mode is very small, since
6 we are constrained by the time slice for each
7 channel context, but since only the HW queues are
8 flushed when switching contexts, it is acceptable.
9
10 Since the SW queues are also emptied in the mac80211 flush()
11 callback, a larger duration is needed. Add an override
12 argument to __ath9k_flush() and set it when flush()
13 is called in MCC mode. This allows the driver to
14 drain both the SW and HW queues.
15
16 Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
17 ---
18
19 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
20 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
21 @@ -719,7 +719,7 @@ void ath_update_survey_nf(struct ath_sof
22  void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
23  void ath_ps_full_sleep(unsigned long data);
24  void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
25 -                  bool sw_pending);
26 +                  bool sw_pending, bool timeout_override);
27  
28  /**********/
29  /* BTCOEX */
30 --- a/drivers/net/wireless/ath/ath9k/channel.c
31 +++ b/drivers/net/wireless/ath/ath9k/channel.c
32 @@ -1232,11 +1232,11 @@ void ath_chanctx_set_next(struct ath_sof
33                 ath9k_chanctx_stop_queues(sc, sc->cur_chan);
34                 queues_stopped = true;
35  
36 -               __ath9k_flush(sc->hw, ~0, true, false);
37 +               __ath9k_flush(sc->hw, ~0, true, false, false);
38  
39                 if (ath_chanctx_send_ps_frame(sc, true))
40                         __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO),
41 -                                     false, false);
42 +                                     false, false, false);
43  
44                 send_ps = true;
45                 spin_lock_bh(&sc->chan_lock);
46 --- a/drivers/net/wireless/ath/ath9k/main.c
47 +++ b/drivers/net/wireless/ath/ath9k/main.c
48 @@ -2031,14 +2031,33 @@ static void ath9k_flush(struct ieee80211
49                         u32 queues, bool drop)
50  {
51         struct ath_softc *sc = hw->priv;
52 +       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
53 +
54 +       if (ath9k_is_chanctx_enabled()) {
55 +               if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
56 +                       goto flush;
57  
58 +               /*
59 +                * If MCC is active, extend the flush timeout
60 +                * and wait for the HW/SW queues to become
61 +                * empty. This needs to be done outside the
62 +                * sc->mutex lock to allow the channel scheduler
63 +                * to switch channel contexts.
64 +                *
65 +                * The vif queues have been stopped in mac80211,
66 +                * so there won't be any incoming frames.
67 +                */
68 +               __ath9k_flush(hw, queues, drop, true, true);
69 +               return;
70 +       }
71 +flush:
72         mutex_lock(&sc->mutex);
73 -       __ath9k_flush(hw, queues, drop, true);
74 +       __ath9k_flush(hw, queues, drop, true, false);
75         mutex_unlock(&sc->mutex);
76  }
77  
78  void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
79 -                  bool sw_pending)
80 +                  bool sw_pending, bool timeout_override)
81  {
82         struct ath_softc *sc = hw->priv;
83         struct ath_hw *ah = sc->sc_ah;
84 @@ -2059,7 +2078,10 @@ void __ath9k_flush(struct ieee80211_hw *
85         }
86  
87         spin_lock_bh(&sc->chan_lock);
88 -       timeout = sc->cur_chan->flush_timeout;
89 +       if (timeout_override)
90 +               timeout = HZ / 5;
91 +       else
92 +               timeout = sc->cur_chan->flush_timeout;
93         spin_unlock_bh(&sc->chan_lock);
94  
95         ath_dbg(common, CHAN_CTX,