cfa1eb7c375524fe05c616c303db9a3b6136c452
[openwrt.git] / package / mac80211 / patches / 560-ath9k_optimize_beacon_tx.patch
1 --- a/drivers/net/wireless/ath/ath9k/beacon.c
2 +++ b/drivers/net/wireless/ath/ath9k/beacon.c
3 @@ -357,41 +357,12 @@ void ath_beacon_tasklet(unsigned long da
4         struct ieee80211_vif *vif;
5         bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
6         int slot;
7 -       u32 bfaddr, bc = 0;
8 -
9 -       /*
10 -        * Check if the previous beacon has gone out.  If
11 -        * not don't try to post another, skip this period
12 -        * and wait for the next.  Missed beacons indicate
13 -        * a problem and should not occur.  If we miss too
14 -        * many consecutive beacons reset the device.
15 -        */
16 -       if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
17 -               sc->beacon.bmisscnt++;
18 -
19 -               if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
20 -                       ath_dbg(common, BSTUCK,
21 -                               "missed %u consecutive beacons\n",
22 -                               sc->beacon.bmisscnt);
23 -                       ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
24 -                       if (sc->beacon.bmisscnt > 3)
25 -                               ath9k_hw_bstuck_nfcal(ah);
26 -               } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
27 -                       ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
28 -                       sc->sc_flags |= SC_OP_TSF_RESET;
29 -                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
30 -               }
31 -
32 -               return;
33 -       }
34  
35         /*
36          * Generate beacon frames. we are sending frames
37          * staggered so calculate the slot for this frame based
38          * on the tsf to safeguard against missing an swba.
39          */
40 -
41 -
42         if (ah->opmode == NL80211_IFTYPE_AP) {
43                 u16 intval;
44                 u32 tsftu;
45 @@ -412,23 +383,6 @@ void ath_beacon_tasklet(unsigned long da
46                 vif = sc->beacon.bslot[slot];
47         }
48  
49 -
50 -       bfaddr = 0;
51 -       if (vif) {
52 -               bf = ath_beacon_generate(sc->hw, vif);
53 -               if (bf != NULL) {
54 -                       bfaddr = bf->bf_daddr;
55 -                       bc = 1;
56 -               }
57 -
58 -               if (sc->beacon.bmisscnt != 0) {
59 -                       ath_dbg(common, BSTUCK,
60 -                               "resume beacon xmit after %u misses\n",
61 -                               sc->beacon.bmisscnt);
62 -                       sc->beacon.bmisscnt = 0;
63 -               }
64 -       }
65 -
66         /*
67          * Handle slot time change when a non-ERP station joins/leaves
68          * an 11g network.  The 802.11 layer notifies us via callback,
69 @@ -453,15 +407,54 @@ void ath_beacon_tasklet(unsigned long da
70                 ath9k_hw_init_global_settings(ah);
71                 sc->beacon.updateslot = OK;
72         }
73 -       if (bfaddr != 0) {
74 -               /* NB: cabq traffic should already be queued and primed */
75 -               ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
76  
77 -               if (!edma)
78 -                       ath9k_hw_txstart(ah, sc->beacon.beaconq);
79 +       if (!vif)
80 +               return;
81 +
82 +       /*
83 +        * Check if the previous beacon has gone out.  If
84 +        * not don't try to post another, skip this period
85 +        * and wait for the next.  Missed beacons indicate
86 +        * a problem and should not occur.  If we miss too
87 +        * many consecutive beacons reset the device.
88 +        */
89 +       if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
90 +               sc->beacon.bmisscnt++;
91 +
92 +               if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
93 +                       ath_dbg(common, BSTUCK,
94 +                               "missed %u consecutive beacons\n",
95 +                               sc->beacon.bmisscnt);
96 +                       ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
97 +                       if (sc->beacon.bmisscnt > 3)
98 +                               ath9k_hw_bstuck_nfcal(ah);
99 +               } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
100 +                       ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
101 +                       sc->sc_flags |= SC_OP_TSF_RESET;
102 +                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
103 +               }
104 +
105 +               return;
106 +       }
107 +
108 +       bf = ath_beacon_generate(sc->hw, vif);
109 +       if (!bf)
110 +               return;
111  
112 -               sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */
113 +       if (sc->beacon.bmisscnt != 0) {
114 +               ath_dbg(common, BSTUCK,
115 +                       "resume beacon xmit after %u misses\n",
116 +                       sc->beacon.bmisscnt);
117 +               sc->beacon.bmisscnt = 0;
118         }
119 +
120 +       /* NB: cabq traffic should already be queued and primed */
121 +       ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
122 +
123 +       if (!edma)
124 +               ath9k_hw_txstart(ah, sc->beacon.beaconq);
125 +
126 +       sc->beacon.ast_be_xmit++;
127  }
128  
129  static void ath9k_beacon_init(struct ath_softc *sc,