mac80211/ath9k: some more performance improvements
[openwrt/staging/dedeckeh.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,