cc956ed27939e45d54954798f509fb18ee9de4d3
[openwrt-10.03/.git] / package / mac80211 / patches / 521-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 @@ -200,6 +200,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 @@ -257,6 +258,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 @@ -338,6 +341,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 @@ -1800,6 +1800,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 @@ -2206,6 +2227,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 @@ -441,22 +442,24 @@ static void ath_tx_complete_aggr(struct 
79                         /* transmit completion */
80                         acked_cnt++;
81                 } else {
82 -                       if (!(tid->state & AGGR_CLEANUP) && retry) {
83 -                               if (fi->retries < ATH_MAX_SW_RETRIES) {
84 -                                       ath_tx_set_retry(sc, txq, bf->bf_mpdu);
85 -                                       txpending = 1;
86 -                               } else {
87 -                                       bf->bf_state.bf_type |= BUF_XRETRY;
88 -                                       txfail = 1;
89 -                                       sendbar = 1;
90 -                                       txfail_cnt++;
91 -                               }
92 -                       } else {
93 +                       if ((tid->state & AGGR_CLEANUP) || !retry) {
94                                 /*
95                                  * cleanup in progress, just fail
96                                  * the un-acked sub-frames
97                                  */
98                                 txfail = 1;
99 +                       } else if (fi->retries < ATH_MAX_SW_RETRIES) {
100 +                               if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
101 +                                   !an->sleeping)
102 +                                       ath_tx_set_retry(sc, txq, bf->bf_mpdu);
103 +
104 +                               clear_filter = true;
105 +                               txpending = 1;
106 +                       } else {
107 +                               bf->bf_state.bf_type |= BUF_XRETRY;
108 +                               txfail = 1;
109 +                               sendbar = 1;
110 +                               txfail_cnt++;
111                         }
112                 }
113  
114 @@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct 
115                                 !txfail, sendbar);
116                 } else {
117                         /* retry the un-acked ones */
118 +                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
119                         if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
120                                 if (bf->bf_next == NULL && bf_last->bf_stale) {
121                                         struct ath_buf *tbf;
122 @@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct 
123  
124         /* prepend un-acked frames to the beginning of the pending frame queue */
125         if (!list_empty(&bf_pending)) {
126 +               if (an->sleeping)
127 +                       ieee80211_sta_set_tim(sta);
128 +
129                 spin_lock_bh(&txq->axq_lock);
130 +               if (clear_filter)
131 +                       tid->ac->clear_ps_filter = true;
132                 list_splice(&bf_pending, &tid->buf_q);
133                 ath_tx_queue_tid(txq, tid);
134                 spin_unlock_bh(&txq->axq_lock);
135 @@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath
136                 bf = list_first_entry(&bf_q, struct ath_buf, list);
137                 bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
138  
139 +               if (tid->ac->clear_ps_filter) {
140 +                       tid->ac->clear_ps_filter = false;
141 +                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
142 +               }
143 +
144                 /* if only one frame, send as non-aggregate */
145                 if (bf == bf->bf_lastbf) {
146                         fi = get_frame_info(bf->bf_mpdu);
147 @@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc *
148         ath_tx_flush_tid(sc, txtid);
149  }
150  
151 +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
152 +{
153 +       struct ath_atx_tid *tid;
154 +       struct ath_atx_ac *ac;
155 +       struct ath_txq *txq;
156 +       bool buffered = false;
157 +       int tidno;
158 +
159 +       for (tidno = 0, tid = &an->tid[tidno];
160 +            tidno < WME_NUM_TID; tidno++, tid++) {
161 +
162 +               if (!tid->sched)
163 +                       continue;
164 +
165 +               ac = tid->ac;
166 +               txq = ac->txq;
167 +
168 +               spin_lock_bh(&txq->axq_lock);
169 +
170 +               if (!list_empty(&tid->buf_q))
171 +                       buffered = true;
172 +
173 +               tid->sched = false;
174 +               list_del(&tid->list);
175 +
176 +               if (ac->sched) {
177 +                       ac->sched = false;
178 +                       list_del(&ac->list);
179 +               }
180 +
181 +               spin_unlock_bh(&txq->axq_lock);
182 +       }
183 +
184 +       return buffered;
185 +}
186 +
187 +void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
188 +{
189 +       struct ath_atx_tid *tid;
190 +       struct ath_atx_ac *ac;
191 +       struct ath_txq *txq;
192 +       int tidno;
193 +
194 +       for (tidno = 0, tid = &an->tid[tidno];
195 +            tidno < WME_NUM_TID; tidno++, tid++) {
196 +
197 +               ac = tid->ac;
198 +               txq = ac->txq;
199 +
200 +               spin_lock_bh(&txq->axq_lock);
201 +               ac->clear_ps_filter = true;
202 +
203 +               if (!list_empty(&tid->buf_q) && !tid->paused) {
204 +                       ath_tx_queue_tid(txq, tid);
205 +                       ath_txq_schedule(sc, txq);
206 +               }
207 +
208 +               spin_unlock_bh(&txq->axq_lock);
209 +       }
210 +}
211 +
212  void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
213  {
214         struct ath_atx_tid *txtid;
215 @@ -1491,7 +1566,6 @@ static int setup_tx_flags(struct sk_buff
216         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
217         int flags = 0;
218  
219 -       flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
220         flags |= ATH9K_TXDESC_INTREQ;
221  
222         if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
223 @@ -1754,6 +1828,9 @@ static void ath_tx_start_dma(struct ath_
224                 if (txctl->paprd)
225                         bf->bf_state.bfs_paprd_timestamp = jiffies;
226  
227 +               if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
228 +                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
229 +
230                 ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
231         }
232  
233 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h
234 +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
235 @@ -122,6 +122,11 @@ static inline void ath9k_hw_set11n_burst
236         ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration);
237  }
238  
239 +static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
240 +{
241 +       ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
242 +}
243 +
244  /* Private hardware call ops */
245  
246  /* PHY ops */
247 --- a/drivers/net/wireless/ath/ath9k/hw.h
248 +++ b/drivers/net/wireless/ath/ath9k/hw.h
249 @@ -626,6 +626,7 @@ struct ath_hw_ops {
250         void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
251         void (*set11n_burstduration)(struct ath_hw *ah, void *ds,
252                                      u32 burstDuration);
253 +       void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
254  };
255  
256  struct ath_nf_limits {
257 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
258 +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
259 @@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(stru
260                 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
261                 | SM(txPower, AR_XmitPower)
262                 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
263 -               | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
264                 | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
265                 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
266  
267 @@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(stru
268         }
269  }
270  
271 +static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
272 +{
273 +       struct ar5416_desc *ads = AR5416DESC(ds);
274 +
275 +       if (val)
276 +               ads->ds_ctl0 |= AR_ClrDestMask;
277 +       else
278 +               ads->ds_ctl0 &= ~AR_ClrDestMask;
279 +}
280 +
281  static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
282                                           void *lastds,
283                                           u32 durUpdateEn, u32 rtsctsRate,
284 @@ -448,4 +457,5 @@ void ar9002_hw_attach_mac_ops(struct ath
285         ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
286         ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
287         ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
288 +       ops->set_clrdmask = ar9002_hw_set_clrdmask;
289  }
290 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
291 +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
292 @@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(stru
293                 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
294                 | SM(txpower, AR_XmitPower)
295                 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
296 -               | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
297                 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
298                 | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
299  
300 @@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(stru
301         ads->ctl22 = 0;
302  }
303  
304 +static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
305 +{
306 +       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
307 +
308 +       if (val)
309 +               ads->ctl11 |= AR_ClrDestMask;
310 +       else
311 +               ads->ctl11 &= ~AR_ClrDestMask;
312 +}
313 +
314  static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
315                                           void *lastds,
316                                           u32 durUpdateEn, u32 rtsctsRate,
317 @@ -510,6 +519,7 @@ void ar9003_hw_attach_mac_ops(struct ath
318         ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
319         ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
320         ops->set11n_burstduration = ar9003_hw_set11n_burstduration;
321 +       ops->set_clrdmask = ar9003_hw_set_clrdmask;
322  }
323  
324  void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
325 --- a/drivers/net/wireless/ath/ath9k/mac.h
326 +++ b/drivers/net/wireless/ath/ath9k/mac.h
327 @@ -239,7 +239,6 @@ struct ath_desc {
328         void *ds_vdata;
329  } __packed __aligned(4);
330  
331 -#define ATH9K_TXDESC_CLRDMASK          0x0001
332  #define ATH9K_TXDESC_NOACK             0x0002
333  #define ATH9K_TXDESC_RTSENA            0x0004
334  #define ATH9K_TXDESC_CTSENA            0x0008