ath5k: treat RXORN as non-fatal
authorBruno Randolf <br1@einfach.org>
Mon, 12 Apr 2010 07:38:52 +0000 (16:38 +0900)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 14 Apr 2010 18:52:42 +0000 (14:52 -0400)
We get RXORN interrupts when all receive buffers are full. This is not
necessarily a fatal situation. It can also happen when the bus is busy or the
CPU is not fast enough to process all frames.

Older chipsets apparently need a reset to come out of this situration, but on
newer chips we can treat RXORN like RX, as going thru a full reset does more
harm than good, there.

The exact chip revisions which need a reset are unknown - this guess
AR5K_SREV_AR5212 ("venice") is copied from the HAL.

Inspired by openwrt 413-rxorn.patch:
"treat rxorn like rx, reset after rxorn seems to do more harm than good"

Signed-off-by: Bruno Randolf <br1@einfach.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/base.h

index 3f59bc2d7912e586a0597348f8f977181b00b06f..92327423325fa06c51ed48b4a5363213f730807a 100644 (file)
@@ -2705,7 +2705,20 @@ ath5k_intr(int irq, void *dev_id)
                         */
                        tasklet_schedule(&sc->restq);
                } else if (unlikely(status & AR5K_INT_RXORN)) {
-                       tasklet_schedule(&sc->restq);
+                       /*
+                        * Receive buffers are full. Either the bus is busy or
+                        * the CPU is not fast enough to process all received
+                        * frames.
+                        * Older chipsets need a reset to come out of this
+                        * condition, but we treat it as RX for newer chips.
+                        * We don't know exactly which versions need a reset -
+                        * this guess is copied from the HAL.
+                        */
+                       sc->stats.rxorn_intr++;
+                       if (ah->ah_mac_srev < AR5K_SREV_AR5212)
+                               tasklet_schedule(&sc->restq);
+                       else
+                               tasklet_schedule(&sc->rxtq);
                } else {
                        if (status & AR5K_INT_SWBA) {
                                tasklet_hi_schedule(&sc->beacontq);
index 53a5651c57a2548c15858f4236716e8053f8a7b0..56221bc7c8cd095208af6f8a591678df5f327e84 100644 (file)
@@ -135,6 +135,7 @@ struct ath5k_statistics {
        unsigned int beacons;
 
        unsigned int mib_intr;
+       unsigned int rxorn_intr;
 };
 
 #if CHAN_DEBUG