}
 }
 
-static void ath5k_tasklet_beacon(unsigned long data)
-{
-       struct ath5k_softc *sc = (struct ath5k_softc *) data;
-
-       /*
-        * Software beacon alert--time to send a beacon.
-        *
-        * In IBSS mode we use this interrupt just to
-        * keep track of the next TBTT (target beacon
-        * transmission time) in order to detect wether
-        * automatic TSF updates happened.
-        */
-       if (sc->opmode == NL80211_IFTYPE_ADHOC) {
-               /* XXX: only if VEOL suppported */
-               u64 tsf = ath5k_hw_get_tsf64(sc->ah);
-               sc->nexttbtt += sc->bintval;
-               ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
-                               "SWBA nexttbtt: %x hw_tu: %x "
-                               "TSF: %llx\n",
-                               sc->nexttbtt,
-                               TSF_TO_TU(tsf),
-                               (unsigned long long) tsf);
-       } else {
-               spin_lock(&sc->block);
-               ath5k_beacon_send(sc);
-               spin_unlock(&sc->block);
-       }
-}
-
 static void
 ath5k_tasklet_rx(unsigned long data)
 {
                sc->bmisscount++;
                ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
                        "missed %u consecutive beacons\n", sc->bmisscount);
-               if (sc->bmisscount > 3) {               /* NB: 3 is a guess */
+               if (sc->bmisscount > 10) {      /* NB: 10 is a guess */
                        ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
                                "stuck beacon time (%u missed)\n",
                                sc->bmisscount);
         * are still pending on the queue.
         */
        if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) {
-               ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq);
+               ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq);
                /* NB: hw still stops DMA, so proceed */
        }
 
+       /* Note: Beacon buffer is updated on beacon_update when mac80211
+        * calls config_interface */
        ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
        ath5k_hw_start_tx_dma(ah, sc->bhalq);
        ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
        ath5k_hw_set_imr(ah, sc->imask);
 }
 
+static void ath5k_tasklet_beacon(unsigned long data)
+{
+       struct ath5k_softc *sc = (struct ath5k_softc *) data;
+
+       /*
+        * Software beacon alert--time to send a beacon.
+        *
+        * In IBSS mode we use this interrupt just to
+        * keep track of the next TBTT (target beacon
+        * transmission time) in order to detect wether
+        * automatic TSF updates happened.
+        */
+       if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+               /* XXX: only if VEOL suppported */
+               u64 tsf = ath5k_hw_get_tsf64(sc->ah);
+               sc->nexttbtt += sc->bintval;
+               ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+                               "SWBA nexttbtt: %x hw_tu: %x "
+                               "TSF: %llx\n",
+                               sc->nexttbtt,
+                               TSF_TO_TU(tsf),
+                               (unsigned long long) tsf);
+       } else {
+               spin_lock(&sc->block);
+               ath5k_beacon_send(sc);
+               spin_unlock(&sc->block);
+       }
+}
+
 
 /********************\
 * Interrupt handling *
 
        /* When in AP mode zero timer0 to start TSF */
        if (ah->ah_op_mode == NL80211_IFTYPE_AP)
                ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
-       else
-               ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
+
+       ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
        ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
        ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
        ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
 
        if (ah->ah_version == AR5K_AR5210)
                return false;
 
-       pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT);
+       pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
+       pending &= AR5K_QCU_STS_FRMPENDCNT;
 
        /* It's possible to have no frames pending even if TXE
         * is set. To indicate that q has not stopped return
                        AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
                                (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
                                AR5K_DCU_MISC_ARBLOCK_CTL_S) |
+                               AR5K_DCU_MISC_ARBLOCK_IGNORE |
                                AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
                                AR5K_DCU_MISC_BCN_ENABLE);
                        break;
 
                case AR5K_TX_QUEUE_CAB:
                        AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-                               AR5K_QCU_MISC_FRSHED_DBA_GT |
+                               AR5K_QCU_MISC_FRSHED_BCN_SENT_GT |
                                AR5K_QCU_MISC_CBREXP_DIS |
+                               AR5K_QCU_MISC_RDY_VEOL_POLICY |
                                AR5K_QCU_MISC_CBREXP_BCN_DIS);
 
                        ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -