return 0;
 }
 
+
+static void
+ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
+{
+       u32 hw_tu;
+       struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+
+       if ((mgmt->frame_control & IEEE80211_FCTL_FTYPE) ==
+               IEEE80211_FTYPE_MGMT &&
+           (mgmt->frame_control & IEEE80211_FCTL_STYPE) ==
+               IEEE80211_STYPE_BEACON &&
+           mgmt->u.beacon.capab_info & WLAN_CAPABILITY_IBSS &&
+           memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
+               /*
+                * Received an IBSS beacon with the same BSSID. Hardware might
+                * have updated the TSF, check if we need to update timers.
+                */
+               hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
+               if (hw_tu >= sc->nexttbtt) {
+                       ath5k_beacon_update_timers(sc,
+                               mgmt->u.beacon.timestamp);
+                       ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+                               "detected HW merge from received beacon\n");
+               }
+       }
+}
+
+
 static void
 ath5k_tasklet_rx(unsigned long data)
 {
 
                ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
 
+               /* check beacons in IBSS mode */
+               if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
+                       ath5k_check_ibss_hw_merge(sc, skb);
+
                __ieee80211_rx(sc->hw, skb, &rxs);
                sc->led_rxrate = ds->ds_rxstat.rs_rate;
                ath5k_led_event(sc, ATH_LED_RX);
        }
 #undef FUDGE
 
+       sc->nexttbtt = nexttbtt;
+
        intval |= AR5K_BEACON_ENA;
        ath5k_hw_init_beacon(ah, nexttbtt, intval);
 
 }
 
 
-/*
- * Configure the beacon timers and interrupts based on the operating mode
+/**
+ * ath5k_beacon_config - Configure the beacon queues and interrupts
+ *
+ * @sc: struct ath5k_softc pointer we are operating on
  *
  * When operating in station mode we want to receive a BMISS interrupt when we
  * stop seeing beacons from the AP we've associated with so we can look for
  * another AP to associate with.
  *
- * In IBSS mode we need to configure the beacon timers and use a self-linked tx
- * descriptor if possible. If the hardware cannot deal with that we enable SWBA
- * interrupts to send the beacons from the interrupt handler.
+ * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
+ * interrupts to detect HW merges only.
+ *
+ * AP mode is missing.
  */
 static void
 ath5k_beacon_config(struct ath5k_softc *sc)
                sc->imask |= AR5K_INT_BMISS;
        } else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
                /*
-                * In IBSS mode enable the beacon timers but only enable SWBA
-                * interrupts if we need to manually prepare beacon frames.
-                * Otherwise we use a self-linked tx descriptor and let the
-                * hardware deal with things. In that case we have to load it
+                * In IBSS mode we use a self-linked tx descriptor and let the
+                * hardware send the beacons automatically. We have to load it
                 * only once here.
+                * We use the SWBA interrupt only to keep track of the beacon
+                * timers in order to detect HW merges (automatic TSF updates).
                 */
                ath5k_beaconq_config(sc);
 
-               if (!ath5k_hw_hasveol(ah))
-                       sc->imask |= AR5K_INT_SWBA;
-               else
+               sc->imask |= AR5K_INT_SWBA;
+
+               if (ath5k_hw_hasveol(ah))
                        ath5k_beacon_send(sc);
        }
        /* TODO else AP */
                                * Handle beacon transmission directly; deferring
                                * this is too slow to meet timing constraints
                                * under load.
+                               *
+                               * In IBSS mode we use this interrupt just to
+                               * keep track of the next TBTT (target beacon
+                               * transmission time) in order to detect hardware
+                               * merges (TSF updates).
                                */
-                               ath5k_beacon_send(sc);
+                               if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+                                        /* XXX: only if VEOL suppported */
+                                       u64 tsf = ath5k_hw_get_tsf64(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), tsf);
+                               } else {
+                                       ath5k_beacon_send(sc);
+                               }
                        }
                        if (status & AR5K_INT_RXEOL) {
                                /*