ath9k: add fixes for AP side powersave frame buffering
[openwrt/svn-archive/archive.git] / package / mac80211 / patches / 531-ath9k_fix_ap_ps_buffering.patch
1 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
2 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
3 @@ -205,6 +205,7 @@ struct ath_atx_ac {
4 int sched;
5 struct list_head list;
6 struct list_head tid_q;
7 + bool clear_ps_filter;
8 };
9
10 struct ath_frame_info {
11 @@ -262,6 +263,8 @@ struct ath_node {
12 struct ath_atx_ac ac[WME_NUM_AC];
13 u16 maxampdu;
14 u8 mpdudensity;
15 +
16 + bool sleeping;
17 };
18
19 #define AGGR_CLEANUP BIT(1)
20 @@ -343,6 +346,9 @@ int ath_tx_aggr_start(struct ath_softc *
21 void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
22 void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
23
24 +void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
25 +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an);
26 +
27 /********/
28 /* VIFs */
29 /********/
30 --- a/drivers/net/wireless/ath/ath9k/main.c
31 +++ b/drivers/net/wireless/ath/ath9k/main.c
32 @@ -1791,6 +1791,27 @@ static int ath9k_sta_remove(struct ieee8
33 return 0;
34 }
35
36 +static void ath9k_sta_notify(struct ieee80211_hw *hw,
37 + struct ieee80211_vif *vif,
38 + enum sta_notify_cmd cmd,
39 + struct ieee80211_sta *sta)
40 +{
41 + struct ath_softc *sc = hw->priv;
42 + struct ath_node *an = (struct ath_node *) sta->drv_priv;
43 +
44 + switch (cmd) {
45 + case STA_NOTIFY_SLEEP:
46 + an->sleeping = true;
47 + if (ath_tx_aggr_sleep(sc, an))
48 + ieee80211_sta_set_tim(sta);
49 + break;
50 + case STA_NOTIFY_AWAKE:
51 + an->sleeping = false;
52 + ath_tx_aggr_wakeup(sc, an);
53 + break;
54 + }
55 +}
56 +
57 static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
58 const struct ieee80211_tx_queue_params *params)
59 {
60 @@ -2130,6 +2151,7 @@ struct ieee80211_ops ath9k_ops = {
61 .configure_filter = ath9k_configure_filter,
62 .sta_add = ath9k_sta_add,
63 .sta_remove = ath9k_sta_remove,
64 + .sta_notify = ath9k_sta_notify,
65 .conf_tx = ath9k_conf_tx,
66 .bss_info_changed = ath9k_bss_info_changed,
67 .set_key = ath9k_set_key,
68 --- a/drivers/net/wireless/ath/ath9k/xmit.c
69 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
70 @@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct
71 struct ath_frame_info *fi;
72 int nframes;
73 u8 tidno;
74 + bool clear_filter;
75
76 skb = bf->bf_mpdu;
77 hdr = (struct ieee80211_hdr *)skb->data;
78 @@ -442,7 +443,11 @@ static void ath_tx_complete_aggr(struct
79 acked_cnt++;
80 } else {
81 if (!(tid->state & AGGR_CLEANUP) && retry) {
82 - if (fi->retries < ATH_MAX_SW_RETRIES) {
83 + if (ts->ts_status & ATH9K_TXERR_FILT) {
84 + if (!an->sleeping)
85 + clear_filter = true;
86 + txpending = 1;
87 + } else if (fi->retries < ATH_MAX_SW_RETRIES) {
88 ath_tx_set_retry(sc, txq, bf->bf_mpdu);
89 txpending = 1;
90 } else {
91 @@ -496,6 +501,7 @@ static void ath_tx_complete_aggr(struct
92 !txfail, sendbar);
93 } else {
94 /* retry the un-acked ones */
95 + ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
96 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
97 if (bf->bf_next == NULL && bf_last->bf_stale) {
98 struct ath_buf *tbf;
99 @@ -547,6 +553,8 @@ static void ath_tx_complete_aggr(struct
100 /* prepend un-acked frames to the beginning of the pending frame queue */
101 if (!list_empty(&bf_pending)) {
102 spin_lock_bh(&txq->axq_lock);
103 + if (clear_filter)
104 + tid->ac->clear_ps_filter = true;
105 list_splice(&bf_pending, &tid->buf_q);
106 ath_tx_queue_tid(txq, tid);
107 spin_unlock_bh(&txq->axq_lock);
108 @@ -816,6 +824,11 @@ static void ath_tx_sched_aggr(struct ath
109 bf = list_first_entry(&bf_q, struct ath_buf, list);
110 bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
111
112 + if (tid->ac->clear_ps_filter) {
113 + tid->ac->clear_ps_filter = false;
114 + ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
115 + }
116 +
117 /* if only one frame, send as non-aggregate */
118 if (bf == bf->bf_lastbf) {
119 fi = get_frame_info(bf->bf_mpdu);
120 @@ -896,6 +909,67 @@ void ath_tx_aggr_stop(struct ath_softc *
121 ath_tx_flush_tid(sc, txtid);
122 }
123
124 +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
125 +{
126 + struct ath_atx_tid *tid;
127 + struct ath_atx_ac *ac;
128 + struct ath_txq *txq;
129 + bool buffered = false;
130 + int tidno;
131 +
132 + for (tidno = 0, tid = &an->tid[tidno];
133 + tidno < WME_NUM_TID; tidno++, tid++) {
134 +
135 + if (!tid->sched)
136 + continue;
137 +
138 + ac = tid->ac;
139 + txq = ac->txq;
140 +
141 + spin_lock_bh(&txq->axq_lock);
142 +
143 + if (!list_empty(&tid->buf_q))
144 + buffered = true;
145 +
146 + tid->sched = false;
147 + list_del(&tid->list);
148 +
149 + if (ac->sched) {
150 + ac->sched = false;
151 + list_del(&ac->list);
152 + }
153 +
154 + spin_unlock_bh(&txq->axq_lock);
155 + }
156 +
157 + return buffered;
158 +}
159 +
160 +void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
161 +{
162 + struct ath_atx_tid *tid;
163 + struct ath_atx_ac *ac;
164 + struct ath_txq *txq;
165 + int tidno;
166 +
167 + for (tidno = 0, tid = &an->tid[tidno];
168 + tidno < WME_NUM_TID; tidno++, tid++) {
169 +
170 + ac = tid->ac;
171 + txq = ac->txq;
172 +
173 + spin_lock_bh(&txq->axq_lock);
174 + ac->clear_ps_filter = true;
175 +
176 + if (!list_empty(&tid->buf_q) && !tid->paused) {
177 + ath_tx_queue_tid(txq, tid);
178 + ath_txq_schedule(sc, txq);
179 + }
180 +
181 + spin_unlock_bh(&txq->axq_lock);
182 + }
183 +}
184 +
185 void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
186 {
187 struct ath_atx_tid *txtid;
188 @@ -1492,7 +1566,6 @@ static int setup_tx_flags(struct sk_buff
189 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
190 int flags = 0;
191
192 - flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
193 flags |= ATH9K_TXDESC_INTREQ;
194
195 if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
196 @@ -1755,6 +1828,9 @@ static void ath_tx_start_dma(struct ath_
197 if (txctl->paprd)
198 bf->bf_state.bfs_paprd_timestamp = jiffies;
199
200 + if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
201 + ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
202 +
203 ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
204 }
205
206 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h
207 +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
208 @@ -128,6 +128,11 @@ static inline void ath9k_hw_set11n_virtu
209 ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf);
210 }
211
212 +static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
213 +{
214 + ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
215 +}
216 +
217 /* Private hardware call ops */
218
219 /* PHY ops */
220 --- a/drivers/net/wireless/ath/ath9k/hw.h
221 +++ b/drivers/net/wireless/ath/ath9k/hw.h
222 @@ -642,6 +642,7 @@ struct ath_hw_ops {
223 u32 burstDuration);
224 void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds,
225 u32 vmf);
226 + void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
227 };
228
229 struct ath_nf_limits {
230 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
231 +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
232 @@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(stru
233 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
234 | SM(txPower, AR_XmitPower)
235 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
236 - | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
237 | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
238 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
239
240 @@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(stru
241 }
242 }
243
244 +static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
245 +{
246 + struct ar5416_desc *ads = AR5416DESC(ds);
247 +
248 + if (val)
249 + ads->ds_ctl0 |= AR_ClrDestMask;
250 + else
251 + ads->ds_ctl0 &= ~AR_ClrDestMask;
252 +}
253 +
254 static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
255 void *lastds,
256 u32 durUpdateEn, u32 rtsctsRate,
257 @@ -460,4 +469,5 @@ void ar9002_hw_attach_mac_ops(struct ath
258 ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
259 ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
260 ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag;
261 + ops->set_clrdmask = ar9002_hw_set_clrdmask;
262 }
263 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
264 +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
265 @@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(stru
266 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
267 | SM(txpower, AR_XmitPower)
268 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
269 - | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
270 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
271 | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
272
273 @@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(stru
274 ads->ctl22 = 0;
275 }
276
277 +static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
278 +{
279 + struct ar9003_txc *ads = (struct ar9003_txc *) ds;
280 +
281 + if (val)
282 + ads->ctl11 |= AR_ClrDestMask;
283 + else
284 + ads->ctl11 &= ~AR_ClrDestMask;
285 +}
286 +
287 static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
288 void *lastds,
289 u32 durUpdateEn, u32 rtsctsRate,
290 @@ -522,6 +531,7 @@ void ar9003_hw_attach_mac_ops(struct ath
291 ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
292 ops->set11n_burstduration = ar9003_hw_set11n_burstduration;
293 ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag;
294 + ops->set_clrdmask = ar9003_hw_set_clrdmask;
295 }
296
297 void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
298 --- a/drivers/net/wireless/ath/ath9k/mac.h
299 +++ b/drivers/net/wireless/ath/ath9k/mac.h
300 @@ -239,7 +239,6 @@ struct ath_desc {
301 void *ds_vdata;
302 } __packed __aligned(4);
303
304 -#define ATH9K_TXDESC_CLRDMASK 0x0001
305 #define ATH9K_TXDESC_NOACK 0x0002
306 #define ATH9K_TXDESC_RTSENA 0x0004
307 #define ATH9K_TXDESC_CTSENA 0x0008