9a5b580019df3dd2edab0ad59a0e9fc3377477b1
[openwrt.git] / package / mac80211 / patches / 560-ath9k_reset_after_full_sleep.patch
1 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
2 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
3 @@ -619,6 +619,7 @@ struct ath_softc {
4         u16 curtxpow;
5         bool ps_enabled;
6         bool ps_idle;
7 +       bool ps_fullsleep;
8         short nbcnvifs;
9         short nvifs;
10         unsigned long ps_usecount;
11 --- a/drivers/net/wireless/ath/ath9k/main.c
12 +++ b/drivers/net/wireless/ath/ath9k/main.c
13 @@ -118,9 +118,10 @@ void ath9k_ps_restore(struct ath_softc *
14         if (--sc->ps_usecount != 0)
15                 goto unlock;
16  
17 -       if (sc->ps_idle)
18 +       if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) {
19                 mode = ATH9K_PM_FULL_SLEEP;
20 -       else if (sc->ps_enabled &&
21 +               sc->ps_fullsleep = true;
22 +       } else if (sc->ps_enabled &&
23                  !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
24                               PS_WAIT_FOR_CAB |
25                               PS_WAIT_FOR_PSPOLL_DATA |
26 @@ -275,6 +276,7 @@ static bool ath_complete_reset(struct at
27                                sc->config.txpowlimit, &sc->curtxpow);
28         ath9k_hw_set_interrupts(ah);
29         ath9k_hw_enable_interrupts(ah);
30 +       sc->ps_fullsleep = false;
31  
32         if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
33                 if (sc->sc_flags & SC_OP_BEACONS)
34 @@ -332,7 +334,8 @@ static int ath_reset_internal(struct ath
35                 hchan = ah->curchan;
36         }
37  
38 -       if (fastcc && !ath9k_hw_check_alive(ah))
39 +       if (fastcc && (sc->ps_fullsleep ||
40 +           !ath9k_hw_check_alive(ah)))
41                 fastcc = false;
42  
43         if (!ath_prepare_reset(sc, retry_tx, flush))
44 @@ -1173,6 +1176,13 @@ static void ath9k_tx(struct ieee80211_hw
45                 }
46         }
47  
48 +       /*
49 +        * Cannot tx while the hardware is in full sleep, it first needs a full
50 +        * chip reset to recover from that
51 +        */
52 +       if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP))
53 +               goto exit;
54 +
55         if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) {
56                 /*
57                  * We are using PS-Poll and mac80211 can request TX while in
58 --- a/drivers/net/wireless/ath/ath9k/xmit.c
59 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
60 @@ -1983,7 +1983,7 @@ static void ath_tx_complete(struct ath_s
61                 skb_pull(skb, padsize);
62         }
63  
64 -       if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
65 +       if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) {
66                 sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
67                 ath_dbg(common, ATH_DBG_PS,
68                         "Going back to sleep after having received TX status (0x%lx)\n",