Backported r12989 for 8.09
[openwrt/svn-archive/archive.git] / package / madwifi / patches-testing / 300-napi_polling.patch
1 --- a/ath/if_ath.c
2 +++ b/ath/if_ath.c
3 @@ -182,7 +182,11 @@
4 struct sk_buff *, int, int, u_int64_t);
5 static void ath_setdefantenna(struct ath_softc *, u_int);
6 static struct ath_txq *ath_txq_setup(struct ath_softc *, int, int);
7 -static void ath_rx_tasklet(TQUEUE_ARG);
8 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
9 +static int ath_rx_poll(struct napi_struct *napi, int budget);
10 +#else
11 +static int ath_rx_poll(struct net_device *dev, int *budget);
12 +#endif
13 static int ath_hardstart(struct sk_buff *, struct net_device *);
14 static int ath_mgtstart(struct ieee80211com *, struct sk_buff *);
15 #ifdef ATH_SUPERG_COMP
16 @@ -331,6 +335,9 @@
17 static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc,
18 u_int32_t new_clamped_maxtxpower);
19
20 +static void ath_poll_disable(struct net_device *dev);
21 +static void ath_poll_enable(struct net_device *dev);
22 +
23 static void ath_scanbufs(struct ath_softc *sc);
24 static int ath_debug_iwpriv(struct ieee80211com *ic,
25 unsigned int param, unsigned int value);
26 @@ -518,7 +525,6 @@
27
28 atomic_set(&sc->sc_txbuf_counter, 0);
29
30 - ATH_INIT_TQUEUE(&sc->sc_rxtq, ath_rx_tasklet, dev);
31 ATH_INIT_TQUEUE(&sc->sc_txtq, ath_tx_tasklet, dev);
32 ATH_INIT_TQUEUE(&sc->sc_bmisstq, ath_bmiss_tasklet, dev);
33 ATH_INIT_TQUEUE(&sc->sc_bstucktq, ath_bstuck_tasklet, dev);
34 @@ -833,6 +839,12 @@
35 dev->set_mac_address = ath_set_mac_address;
36 dev->change_mtu = ath_change_mtu;
37 dev->tx_queue_len = ATH_TXBUF - ATH_TXBUF_MGT_RESERVED;
38 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
39 + netif_napi_add(dev, &sc->sc_napi, ath_rx_poll, 64);
40 +#else
41 + dev->poll = ath_rx_poll;
42 + dev->weight = 64;
43 +#endif
44 #ifdef USE_HEADERLEN_RESV
45 dev->hard_header_len += sizeof(struct ieee80211_qosframe) +
46 sizeof(struct llc) +
47 @@ -1770,7 +1782,7 @@
48 }
49
50 static void
51 -ath_intr_process_rx_descriptors(struct ath_softc *sc, int *pneedmark, u_int64_t hw_tsf)
52 +ath_intr_process_rx_descriptors(struct ath_softc *sc, int *pneedmark, u_int64_t hw_tsf, int schedule)
53 {
54 struct ath_hal *ah = sc->sc_ah;
55 struct ath_desc *ds;
56 @@ -2252,8 +2264,25 @@
57 }
58
59 /* If we got something to process, schedule rx queue to handle it */
60 - if (count)
61 - ATH_SCHEDULE_TQUEUE(&sc->sc_rxtq, pneedmark);
62 + if (count) {
63 + sc->sc_isr &= ~HAL_INT_RX;
64 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
65 + if (netif_rx_schedule_prep(sc->sc_dev, &sc->sc_napi))
66 +#else
67 + if (netif_rx_schedule_prep(sc->sc_dev))
68 +#endif
69 + {
70 +#ifndef ATH_PRECISE_TSF
71 + sc->sc_imask &= ~HAL_INT_RX;
72 + ath_hal_intrset(ah, sc->sc_imask);
73 +#endif
74 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
75 + __netif_rx_schedule(sc->sc_dev, &sc->sc_napi);
76 +#else
77 + __netif_rx_schedule(sc->sc_dev);
78 +#endif
79 + }
80 + }
81 ATH_RXBUF_UNLOCK_IRQ(sc);
82 #undef PA2DESC
83 }
84 @@ -2343,6 +2372,7 @@
85 (status & HAL_INT_GLOBAL) ? " HAL_INT_GLOBAL" : ""
86 );
87
88 + sc->sc_isr = status;
89 status &= sc->sc_imask; /* discard unasked for bits */
90 /* As soon as we know we have a real interrupt we intend to service,
91 * we will check to see if we need an initial hardware TSF reading.
92 @@ -2400,7 +2430,7 @@
93 }
94 if (status & (HAL_INT_RX | HAL_INT_RXPHY)) {
95 /* NB: Will schedule rx tasklet if necessary. */
96 - ath_intr_process_rx_descriptors(sc, &needmark, hw_tsf);
97 + ath_intr_process_rx_descriptors(sc, &needmark, hw_tsf, 1);
98 }
99 if (status & HAL_INT_TX) {
100 #ifdef ATH_SUPERG_DYNTURBO
101 @@ -2426,6 +2456,11 @@
102 }
103 }
104 #endif
105 + /* disable transmit interrupt */
106 + sc->sc_isr &= ~HAL_INT_TX;
107 + ath_hal_intrset(ah, sc->sc_imask & ~HAL_INT_TX);
108 + sc->sc_imask &= ~HAL_INT_TX;
109 +
110 ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, &needmark);
111 }
112 if (status & HAL_INT_BMISS) {
113 @@ -2617,6 +2652,7 @@
114 if (sc->sc_tx99 != NULL)
115 sc->sc_tx99->start(sc->sc_tx99);
116 #endif
117 + ath_poll_enable(dev);
118
119 done:
120 ATH_UNLOCK(sc);
121 @@ -2657,6 +2693,9 @@
122 if (sc->sc_tx99 != NULL)
123 sc->sc_tx99->stop(sc->sc_tx99);
124 #endif
125 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
126 + ath_poll_disable(dev);
127 +#endif
128 netif_stop_queue(dev); /* XXX re-enabled by ath_newstate */
129 dev->flags &= ~IFF_RUNNING; /* NB: avoid recursion */
130 ieee80211_stop_running(ic); /* stop all VAPs */
131 @@ -4109,6 +4148,43 @@
132 return ath_keyset(sc, k, mac, vap->iv_bss);
133 }
134
135 +static void ath_poll_disable(struct net_device *dev)
136 +{
137 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
138 + struct ath_softc *sc = dev->priv;
139 +#endif
140 +
141 + /*
142 + * XXX Using in_softirq is not right since we might
143 + * be called from other soft irq contexts than
144 + * ath_rx_poll
145 + */
146 + if (!in_softirq()) {
147 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
148 + napi_disable(&sc->sc_napi);
149 +#else
150 + netif_poll_disable(dev);
151 +#endif
152 + }
153 +}
154 +
155 +static void ath_poll_enable(struct net_device *dev)
156 +{
157 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
158 + struct ath_softc *sc = dev->priv;
159 +#endif
160 +
161 + /* NB: see above */
162 + if (!in_softirq()) {
163 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
164 + napi_enable(&sc->sc_napi);
165 +#else
166 + netif_poll_enable(dev);
167 +#endif
168 + }
169 +}
170 +
171 +
172 /*
173 * Block/unblock tx+rx processing while a key change is done.
174 * We assume the caller serializes key management operations
175 @@ -4119,33 +4195,23 @@
176 ath_key_update_begin(struct ieee80211vap *vap)
177 {
178 struct net_device *dev = vap->iv_ic->ic_dev;
179 - struct ath_softc *sc = dev->priv;
180
181 - DPRINTF(sc, ATH_DEBUG_KEYCACHE, "Begin\n");
182 /*
183 * When called from the rx tasklet we cannot use
184 * tasklet_disable because it will block waiting
185 * for us to complete execution.
186 - *
187 - * XXX Using in_softirq is not right since we might
188 - * be called from other soft irq contexts than
189 - * ath_rx_tasklet.
190 */
191 - if (!in_softirq())
192 - tasklet_disable(&sc->sc_rxtq);
193 - netif_stop_queue(dev);
194 + if ((dev->flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))
195 + netif_stop_queue(dev);
196 }
197
198 static void
199 ath_key_update_end(struct ieee80211vap *vap)
200 {
201 struct net_device *dev = vap->iv_ic->ic_dev;
202 - struct ath_softc *sc = dev->priv;
203
204 - DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n");
205 - netif_wake_queue(dev);
206 - if (!in_softirq()) /* NB: see above */
207 - tasklet_enable(&sc->sc_rxtq);
208 + if ((dev->flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))
209 + netif_wake_queue(dev);
210 }
211
212 /*
213 @@ -6405,15 +6471,25 @@
214 sc->sc_numrxotherant = 0;
215 }
216
217 -static void
218 -ath_rx_tasklet(TQUEUE_ARG data)
219 +static int
220 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
221 +ath_rx_poll(struct napi_struct *napi, int budget)
222 +#else
223 +ath_rx_poll(struct net_device *dev, int *budget)
224 +#endif
225 {
226 #define PA2DESC(_sc, _pa) \
227 ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
228 ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
229 - struct net_device *dev = (struct net_device *)data;
230 - struct ath_buf *bf;
231 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
232 + struct ath_softc *sc = container_of(napi, struct ath_softc, sc_napi);
233 + struct net_device *dev = sc->sc_dev;
234 + u_int rx_limit = budget;
235 +#else
236 struct ath_softc *sc = dev->priv;
237 + u_int rx_limit = min(dev->quota, *budget);
238 +#endif
239 + struct ath_buf *bf;
240 struct ieee80211com *ic = &sc->sc_ic;
241 struct ath_hal *ah = sc ? sc->sc_ah : NULL;
242 struct ath_desc *ds;
243 @@ -6421,6 +6497,7 @@
244 struct ieee80211_node *ni;
245 struct sk_buff *skb = NULL;
246 unsigned int len, phyerr, mic_fail = 0;
247 + unsigned int early_stop = 0;
248 int type = -1; /* undefined */
249 int init_ret = 0;
250 int bf_processed = 0;
251 @@ -6428,6 +6505,7 @@
252 int errors = 0;
253
254 DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s started...\n", __func__);
255 +process_rx_again:
256 do {
257 /* Get next RX buffer pending processing by RX tasklet...
258 *
259 @@ -6457,6 +6535,10 @@
260 break;
261
262 bf_processed++;
263 + if (rx_limit-- < 0) {
264 + early_stop = 1;
265 + break;
266 + }
267 ds = bf->bf_desc;
268
269 #ifdef AR_DEBUG
270 @@ -6491,6 +6573,7 @@
271 sc->sc_stats.ast_rx_phyerr++;
272 phyerr = rs->rs_phyerr & 0x1f;
273 sc->sc_stats.ast_rx_phy[phyerr]++;
274 + goto rx_next;
275 }
276 if (rs->rs_status & HAL_RXERR_DECRYPT) {
277 /* Decrypt error. If the error occurred
278 @@ -6689,6 +6772,33 @@
279 STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
280 ATH_RXBUF_UNLOCK_IRQ(sc);
281 } while (1);
282 + if (!early_stop) {
283 + unsigned long flags;
284 + /* Check if more data is received while we were
285 + * processing the descriptor chain.
286 + */
287 +#ifndef ATH_PRECISE_TSF
288 + local_irq_save(flags);
289 + if (sc->sc_isr & HAL_INT_RX) {
290 + u_int64_t hw_tsf = ath_hal_gettsf64(ah);
291 + sc->sc_isr &= ~HAL_INT_RX;
292 + local_irq_restore(flags);
293 + ath_intr_process_rx_descriptors(sc, NULL, hw_tsf, 0);
294 + goto process_rx_again;
295 + }
296 + sc->sc_imask |= HAL_INT_RX;
297 + ath_hal_intrset(ah, sc->sc_imask);
298 + local_irq_restore(flags);
299 +#endif
300 + }
301 +
302 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
303 + netif_rx_complete(dev, napi);
304 +#else
305 + netif_rx_complete(dev);
306 + *budget -= bf_processed;
307 + dev->quota -= bf_processed;
308 +#endif
309
310 if (sc->sc_useintmit)
311 ath_hal_rxmonitor(ah, &sc->sc_halstats, &sc->sc_curchan);
312 @@ -6701,6 +6811,12 @@
313 " %d rx buf processed. %d were errors. %d skb accepted.\n",
314 __func__, bf_processed, errors, skb_accepted);
315 #undef PA2DESC
316 +
317 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
318 + return bf_processed;
319 +#else
320 + return early_stop;
321 +#endif
322 }
323
324 #ifdef ATH_SUPERG_XR
325 @@ -8306,12 +8422,24 @@
326 {
327 struct net_device *dev = (struct net_device *)data;
328 struct ath_softc *sc = dev->priv;
329 + unsigned long flags;
330
331 +process_tx_again:
332 if (txqactive(sc->sc_ah, 0))
333 ath_tx_processq(sc, &sc->sc_txq[0]);
334 if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
335 ath_tx_processq(sc, sc->sc_cabq);
336
337 + local_irq_save(flags);
338 + if (sc->sc_isr & HAL_INT_TX) {
339 + sc->sc_isr &= ~HAL_INT_TX;
340 + local_irq_restore(flags);
341 + goto process_tx_again;
342 + }
343 + sc->sc_imask |= HAL_INT_TX;
344 + ath_hal_intrset(sc->sc_ah, sc->sc_imask);
345 + local_irq_restore(flags);
346 +
347 netif_wake_queue(dev);
348
349 if (sc->sc_softled)
350 @@ -8327,7 +8455,9 @@
351 {
352 struct net_device *dev = (struct net_device *)data;
353 struct ath_softc *sc = dev->priv;
354 + unsigned long flags;
355
356 +process_tx_again:
357 /*
358 * Process each active queue.
359 */
360 @@ -8357,6 +8487,16 @@
361 if (sc->sc_uapsdq && txqactive(sc->sc_ah, sc->sc_uapsdq->axq_qnum))
362 ath_tx_processq(sc, sc->sc_uapsdq);
363
364 + local_irq_save(flags);
365 + if (sc->sc_isr & HAL_INT_TX) {
366 + sc->sc_isr &= ~HAL_INT_TX;
367 + local_irq_restore(flags);
368 + goto process_tx_again;
369 + }
370 + sc->sc_imask |= HAL_INT_TX;
371 + ath_hal_intrset(sc->sc_ah, sc->sc_imask);
372 + local_irq_restore(flags);
373 +
374 netif_wake_queue(dev);
375
376 if (sc->sc_softled)
377 @@ -10322,9 +10462,9 @@
378 dev->mtu = mtu;
379 if ((dev->flags & IFF_RUNNING) && !sc->sc_invalid) {
380 /* NB: the rx buffers may need to be reallocated */
381 - tasklet_disable(&sc->sc_rxtq);
382 + ath_poll_disable(dev);
383 error = ath_reset(dev);
384 - tasklet_enable(&sc->sc_rxtq);
385 + ath_poll_enable(dev);
386 }
387 ATH_UNLOCK(sc);
388
389 --- a/ath/if_athvar.h
390 +++ b/ath/if_athvar.h
391 @@ -56,6 +56,10 @@
392 # include <asm/bitops.h>
393 #endif
394
395 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
396 +#define irqs_disabled() 0
397 +#endif
398 +
399 /*
400 * Deduce if tasklets are available. If not then
401 * fall back to using the immediate work queue.
402 @@ -644,6 +648,9 @@
403 struct ath_softc {
404 struct ieee80211com sc_ic; /* NB: must be first */
405 struct net_device *sc_dev;
406 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
407 + struct napi_struct sc_napi;
408 +#endif
409 void __iomem *sc_iobase; /* address of the device */
410 struct semaphore sc_lock; /* dev-level lock */
411 struct net_device_stats sc_devstats; /* device statistics */
412 @@ -756,7 +763,6 @@
413 struct ath_buf *sc_rxbufcur; /* current rx buffer */
414 u_int32_t *sc_rxlink; /* link ptr in last RX desc */
415 spinlock_t sc_rxbuflock;
416 - struct ATH_TQ_STRUCT sc_rxtq; /* rx intr tasklet */
417 struct ATH_TQ_STRUCT sc_rxorntq; /* rxorn intr tasklet */
418 u_int16_t sc_cachelsz; /* cache line size */
419
420 @@ -769,6 +775,7 @@
421 u_int sc_txintrperiod; /* tx interrupt batching */
422 struct ath_txq sc_txq[HAL_NUM_TX_QUEUES];
423 struct ath_txq *sc_ac2q[WME_NUM_AC]; /* WME AC -> h/w qnum */
424 + HAL_INT sc_isr; /* unmasked ISR state */
425 struct ATH_TQ_STRUCT sc_txtq; /* tx intr tasklet */
426 u_int8_t sc_grppoll_str[GRPPOLL_RATE_STR_LEN];
427 struct ath_descdma sc_bdma; /* beacon descriptors */
428 @@ -888,6 +895,8 @@
429 #define ATH_TXBUF_LOCK_CHECK(_sc)
430 #endif
431
432 +#define ATH_DISABLE_INTR local_irq_disable
433 +#define ATH_ENABLE_INTR local_irq_enable
434
435 #define ATH_RXBUF_LOCK_INIT(_sc) spin_lock_init(&(_sc)->sc_rxbuflock)
436 #define ATH_RXBUF_LOCK_DESTROY(_sc)
437 --- a/net80211/ieee80211_skb.c
438 +++ b/net80211/ieee80211_skb.c
439 @@ -73,7 +73,7 @@
440 #undef dev_queue_xmit
441 #undef kfree_skb
442 #undef kfree_skb_fast
443 -#undef netif_rx
444 +#undef netif_receive_skb
445 #undef pskb_copy
446 #undef skb_clone
447 #undef skb_copy
448 @@ -581,8 +581,8 @@
449 grp, vlan_tag);
450 }
451
452 -int netif_rx_debug(struct sk_buff *skb, const char *func, int line) {
453 - return netif_rx(untrack_skb(skb, 0, __func__, __LINE__));
454 +int netif_receive_skb_debug(struct sk_buff *skb, const char *func, int line) {
455 + return netif_receive_skb(untrack_skb(skb, 0, __func__, __LINE__));
456 }
457
458 struct sk_buff *alloc_skb_debug(unsigned int length, gfp_t gfp_mask,
459 @@ -707,7 +707,7 @@
460 }
461
462 EXPORT_SYMBOL(vlan_hwaccel_rx_debug);
463 -EXPORT_SYMBOL(netif_rx_debug);
464 +EXPORT_SYMBOL(netif_receive_skb_debug);
465 EXPORT_SYMBOL(alloc_skb_debug);
466 EXPORT_SYMBOL(dev_alloc_skb_debug);
467 EXPORT_SYMBOL(skb_clone_debug);
468 --- a/net80211/ieee80211_skb.h
469 +++ b/net80211/ieee80211_skb.h
470 @@ -115,7 +115,7 @@
471
472 int vlan_hwaccel_rx_debug(struct sk_buff *skb, struct vlan_group *grp,
473 unsigned short vlan_tag, const char *func, int line);
474 -int netif_rx_debug(struct sk_buff *skb, const char *func, int line);
475 +int netif_receive_skb_debug(struct sk_buff *skb, const char *func, int line);
476 struct sk_buff *alloc_skb_debug(unsigned int length, gfp_t gfp_mask,
477 const char *func, int line);
478 struct sk_buff *dev_alloc_skb_debug(unsigned int length,
479 @@ -150,7 +150,7 @@
480 #undef dev_queue_xmit
481 #undef kfree_skb
482 #undef kfree_skb_fast
483 -#undef netif_rx
484 +#undef netif_receive_skb
485 #undef pskb_copy
486 #undef skb_clone
487 #undef skb_copy
488 @@ -167,8 +167,8 @@
489 skb_copy_expand_debug(_skb, _newheadroom, _newtailroom, _gfp_mask, __func__, __LINE__)
490 #define vlan_hwaccel_rx(_skb, _grp, _tag) \
491 vlan_hwaccel_rx_debug(_skb, _grp, _tag, __func__, __LINE__)
492 -#define netif_rx(_skb) \
493 - netif_rx_debug(_skb, __func__, __LINE__)
494 +#define netif_receive_skb(_skb) \
495 + netif_receive_skb_debug(_skb, __func__, __LINE__)
496 #define alloc_skb(_length, _gfp_mask) \
497 alloc_skb_debug(_length, _gfp_mask, __func__, __LINE__)
498 #define dev_alloc_skb(_length) \
499 --- a/net80211/ieee80211_input.c
500 +++ b/net80211/ieee80211_input.c
501 @@ -1185,7 +1185,7 @@
502 ret = vlan_hwaccel_rx(skb,
503 vap->iv_vlgrp, ni->ni_vlan);
504 else
505 - ret = netif_rx(skb);
506 + ret = netif_receive_skb(skb);
507 if (ret == NET_RX_DROP)
508 vap->iv_devstats.rx_dropped++;
509 if (tni != NULL)
510 @@ -2285,7 +2285,7 @@
511
512 if (SKB_NI(skb1) != NULL)
513 ieee80211_unref_node(&SKB_NI(skb1));
514 - if (netif_rx(skb1) == NET_RX_DROP)
515 + if (netif_receive_skb(skb1) == NET_RX_DROP)
516 vap->iv_devstats.rx_dropped++;
517 }
518 }
519 --- a/net80211/ieee80211_monitor.c
520 +++ b/net80211/ieee80211_monitor.c
521 @@ -580,7 +580,7 @@
522
523 if (SKB_NI(skb1) != NULL)
524 ieee80211_unref_node(&SKB_NI(skb1));
525 - if (netif_rx(skb1) == NET_RX_DROP)
526 + if (netif_receive_skb(skb1) == NET_RX_DROP)
527 vap->iv_devstats.rx_dropped++;
528 skb1 = NULL;
529 }