diff options
author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-10-17 04:56:05 +0000 |
---|---|---|
committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-10-17 04:56:05 +0000 |
commit | a2c8edeafcd46654b20aa3a3aa7d516246d80c36 (patch) | |
tree | 0a2c24076f1f7f5f96c5aa90fe69c48df0112e5d /package/madwifi/patches | |
parent | 586c0c90e8d1c6f4bd02f5d689346a0ed375cc4c (diff) |
madwifi: fix various noderef/memleak issues
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18052 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/madwifi/patches')
-rw-r--r-- | package/madwifi/patches/421-channel_handling.patch | 19 | ||||
-rw-r--r-- | package/madwifi/patches/430-use_netdev_priv.patch | 14 | ||||
-rw-r--r-- | package/madwifi/patches/432-netdev_ops.patch | 6 | ||||
-rw-r--r-- | package/madwifi/patches/446-single_module.patch | 2 | ||||
-rw-r--r-- | package/madwifi/patches/451-ibss_race_fix.patch | 332 |
5 files changed, 325 insertions, 48 deletions
diff --git a/package/madwifi/patches/421-channel_handling.patch b/package/madwifi/patches/421-channel_handling.patch index e5302c138..8424321d7 100644 --- a/package/madwifi/patches/421-channel_handling.patch +++ b/package/madwifi/patches/421-channel_handling.patch @@ -853,7 +853,7 @@ } /* Initialize candidate channels to all available */ memcpy(ic->ic_chan_active, ic->ic_chan_avail, -@@ -311,11 +296,58 @@ ieee80211_ifattach(struct ieee80211com * +@@ -311,11 +296,59 @@ ieee80211_ifattach(struct ieee80211com * * When 11g is supported, force the rate set to * include basic rates suitable for a mixed b/g bss. */ @@ -866,6 +866,7 @@ + if (init) + return; + ++ ifmedia_removeall(&ic->ic_media); + ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, NULL, NULL); + ieee80211com_media_status(ic->ic_dev, &imr); + ifmedia_set(&ic->ic_media, imr.ifm_active); @@ -913,7 +914,7 @@ /* Setup initial channel settings */ ic->ic_bsschan = IEEE80211_CHAN_ANYC; /* Arbitrarily pick the first channel */ -@@ -327,6 +359,7 @@ ieee80211_ifattach(struct ieee80211com * +@@ -327,6 +360,7 @@ ieee80211_ifattach(struct ieee80211com * /* Enable WME by default, if we're capable. */ if (ic->ic_caps & IEEE80211_C_WME) ic->ic_flags |= IEEE80211_F_WME; @@ -921,7 +922,7 @@ (void) ieee80211_setmode(ic, ic->ic_curmode); /* Store default beacon interval, as nec. */ -@@ -763,7 +796,8 @@ ieee80211_media_setup(struct ieee80211co +@@ -763,7 +797,8 @@ ieee80211_media_setup(struct ieee80211co struct ieee80211_rateset allrates; /* Fill in media characteristics. */ @@ -931,7 +932,7 @@ maxrate = 0; memset(&allrates, 0, sizeof(allrates)); -@@ -793,7 +827,7 @@ ieee80211_media_setup(struct ieee80211co +@@ -793,7 +828,7 @@ ieee80211_media_setup(struct ieee80211co ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_WDS); if (mode == IEEE80211_MODE_AUTO) continue; @@ -940,7 +941,7 @@ for (i = 0; i < rs->rs_nrates; i++) { rate = rs->rs_rates[i]; -@@ -1207,7 +1241,7 @@ ieee80211_announce(struct ieee80211com * +@@ -1207,7 +1242,7 @@ ieee80211_announce(struct ieee80211com * if ((ic->ic_modecaps & (1 << mode)) == 0) continue; if_printf(dev, "%s rates: ", ieee80211_phymode_name[mode]); @@ -949,7 +950,7 @@ for (i = 0; i < rs->rs_nrates; i++) { rate = rs->rs_rates[i]; mword = ieee80211_rate2media(ic, rate, mode); -@@ -1417,7 +1451,7 @@ ieee80211com_media_change(struct net_dev +@@ -1417,7 +1452,7 @@ ieee80211com_media_change(struct net_dev * now so drivers have a consistent state. */ KASSERT(vap->iv_bss != NULL, ("no bss node")); @@ -958,7 +959,7 @@ } error = -ENETRESET; } -@@ -1435,7 +1469,7 @@ findrate(struct ieee80211com *ic, enum i +@@ -1435,7 +1470,7 @@ findrate(struct ieee80211com *ic, enum i { #define IEEERATE(_ic,_m,_i) \ ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) @@ -967,7 +968,7 @@ for (i = 0; i < nrates; i++) if (IEEERATE(ic, mode, i) == rate) return i; -@@ -1877,11 +1911,6 @@ ieee80211_build_countryie(struct ieee802 +@@ -1877,11 +1912,6 @@ ieee80211_build_countryie(struct ieee802 if (ieee80211_chan2mode(c) != curmode_noturbo) continue; @@ -979,7 +980,7 @@ if (*cur_runlen == 0) { (*cur_runlen)++; *cur_pow = c->ic_maxregpower; -@@ -1915,7 +1944,7 @@ void +@@ -1915,7 +1945,7 @@ void ieee80211_build_sc_ie(struct ieee80211com *ic) { struct ieee80211_ie_sc *ie = &ic->ic_sc_ie; diff --git a/package/madwifi/patches/430-use_netdev_priv.patch b/package/madwifi/patches/430-use_netdev_priv.patch index ad2b6d494..642a9d21d 100644 --- a/package/madwifi/patches/430-use_netdev_priv.patch +++ b/package/madwifi/patches/430-use_netdev_priv.patch @@ -1002,7 +1002,7 @@ #define skb_tail_pointer(_skb) ((_skb)->tail) --- a/net80211/ieee80211.c +++ b/net80211/ieee80211.c -@@ -457,7 +457,7 @@ ieee80211_vap_setup(struct ieee80211com +@@ -458,7 +458,7 @@ ieee80211_vap_setup(struct ieee80211com #define IEEE80211_C_OPMODE \ (IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | IEEE80211_C_AHDEMO | \ IEEE80211_C_MONITOR) @@ -1011,7 +1011,7 @@ struct net_device *parent = ic->ic_dev; int err; -@@ -1354,7 +1354,7 @@ media_status(enum ieee80211_opmode opmod +@@ -1355,7 +1355,7 @@ media_status(enum ieee80211_opmode opmod static void ieee80211com_media_status(struct net_device *dev, struct ifmediareq *imr) { @@ -1020,7 +1020,7 @@ imr->ifm_status = IFM_AVALID; if (!TAILQ_EMPTY(&ic->ic_vaps)) -@@ -1406,7 +1406,7 @@ media2mode(const struct ifmedia_entry *i +@@ -1407,7 +1407,7 @@ media2mode(const struct ifmedia_entry *i static int ieee80211com_media_change(struct net_device *dev) { @@ -1029,7 +1029,7 @@ struct ieee80211vap *vap; struct ifmedia_entry *ime = ic->ic_media.ifm_cur; enum ieee80211_phymode newphymode; -@@ -1510,7 +1510,7 @@ checkrate(struct ieee80211com *ic, enum +@@ -1511,7 +1511,7 @@ checkrate(struct ieee80211com *ic, enum int ieee80211_media_change(struct net_device *dev) { @@ -1038,7 +1038,7 @@ struct ieee80211com *ic = vap->iv_ic; struct ifmedia_entry *ime = vap->iv_media.ifm_cur; enum ieee80211_phymode newmode; -@@ -1544,7 +1544,7 @@ EXPORT_SYMBOL(ieee80211_media_change); +@@ -1545,7 +1545,7 @@ EXPORT_SYMBOL(ieee80211_media_change); void ieee80211_media_status(struct net_device *dev, struct ifmediareq *imr) { @@ -1047,7 +1047,7 @@ struct ieee80211com *ic = vap->iv_ic; enum ieee80211_phymode mode; struct ieee80211_rateset *rs; -@@ -1750,7 +1750,7 @@ EXPORT_SYMBOL(ieee80211_media2rate); +@@ -1751,7 +1751,7 @@ EXPORT_SYMBOL(ieee80211_media2rate); static struct net_device_stats * ieee80211_getstats(struct net_device *dev) { @@ -1056,7 +1056,7 @@ struct net_device_stats *stats = &vap->iv_devstats; /* XXX: Total guess as to what to count where */ -@@ -1789,7 +1789,7 @@ ieee80211_change_mtu(struct net_device * +@@ -1790,7 +1790,7 @@ ieee80211_change_mtu(struct net_device * static void ieee80211_set_multicast_list(struct net_device *dev) { diff --git a/package/madwifi/patches/432-netdev_ops.patch b/package/madwifi/patches/432-netdev_ops.patch index 372000fc8..2e542bfec 100644 --- a/package/madwifi/patches/432-netdev_ops.patch +++ b/package/madwifi/patches/432-netdev_ops.patch @@ -69,7 +69,7 @@ http://madwifi-project.org/changeset/4005 case NETDEV_CHANGENAME: --- a/net80211/ieee80211.c +++ b/net80211/ieee80211.c -@@ -450,6 +450,18 @@ ieee80211_ifdetach(struct ieee80211com * +@@ -451,6 +451,18 @@ ieee80211_ifdetach(struct ieee80211com * } EXPORT_SYMBOL(ieee80211_ifdetach); @@ -88,7 +88,7 @@ http://madwifi-project.org/changeset/4005 int ieee80211_vap_setup(struct ieee80211com *ic, struct net_device *dev, const char *name, int opmode, int flags, struct ieee80211vap *master) -@@ -470,16 +482,21 @@ ieee80211_vap_setup(struct ieee80211com +@@ -471,16 +483,21 @@ ieee80211_vap_setup(struct ieee80211com } else strncpy(dev->name, name, sizeof(dev->name)); } @@ -110,7 +110,7 @@ http://madwifi-project.org/changeset/4005 dev->tx_queue_len = 0; /* NB: bypass queuing */ dev->hard_header_len = parent->hard_header_len; /* -@@ -1823,7 +1840,11 @@ ieee80211_set_multicast_list(struct net_ +@@ -1824,7 +1841,11 @@ ieee80211_set_multicast_list(struct net_ IEEE80211_UNLOCK_IRQ(ic); /* XXX: Merge multicast list into parent device */ diff --git a/package/madwifi/patches/446-single_module.patch b/package/madwifi/patches/446-single_module.patch index ed02ae8f5..e546b054a 100644 --- a/package/madwifi/patches/446-single_module.patch +++ b/package/madwifi/patches/446-single_module.patch @@ -351,7 +351,7 @@ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/netdevice.h> -@@ -2014,3 +2015,65 @@ ieee80211_build_sc_ie(struct ieee80211co +@@ -2015,3 +2016,65 @@ ieee80211_build_sc_ie(struct ieee80211co int ath_debug_global = 0; EXPORT_SYMBOL(ath_debug_global); diff --git a/package/madwifi/patches/451-ibss_race_fix.patch b/package/madwifi/patches/451-ibss_race_fix.patch index 7785dc1d7..9be3311fd 100644 --- a/package/madwifi/patches/451-ibss_race_fix.patch +++ b/package/madwifi/patches/451-ibss_race_fix.patch @@ -1,41 +1,184 @@ --- a/net80211/ieee80211_input.c +++ b/net80211/ieee80211_input.c -@@ -322,7 +322,6 @@ ieee80211_input(struct ieee80211vap * va +@@ -294,10 +294,10 @@ ieee80211_input(struct ieee80211vap * va + break; + case IEEE80211_M_IBSS: + case IEEE80211_M_AHDEMO: +- if (!IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid) || ++ if ((!IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid) || + (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr) && +- !IEEE80211_IS_MULTICAST(wh->i_addr1) && +- (subtype != IEEE80211_FC0_SUBTYPE_BEACON))) { ++ !IEEE80211_IS_MULTICAST(wh->i_addr1))) && ++ (type == IEEE80211_FC0_TYPE_DATA)) { + if (!(vap->iv_dev->flags & IFF_PROMISC)) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, + bssid, NULL, "%s", "not to bss"); +@@ -322,22 +322,15 @@ ieee80211_input(struct ieee80211vap * va } /* Do not try to find a node reference if the packet really did come from the BSS */ if (type == IEEE80211_FC0_TYPE_DATA && ni == vap->iv_bss && - !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2) && IEEE80211_ADDR_EQ(vap->iv_bssid, wh->i_addr3)) { /* Try to find sender in local node table. */ - ni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2); -@@ -3572,10 +3571,12 @@ ieee80211_recv_mgmt(struct ieee80211vap +- ni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2); ++ if (!ni_or_null) { ++ ieee80211_unref_node(&ni); ++ ni = ieee80211_find_txnode(vap, wh->i_addr2); ++ } + if (ni == NULL) { +- /* +- * Fake up a node for this newly discovered +- * member of the IBSS. This should probably +- * done after an ACL check. +- */ +- ni = ieee80211_fakeup_adhoc_node(vap, +- wh->i_addr2); +- if (ni == NULL) { +- /* NB: stat kept for alloc failure */ +- goto err; +- } ++ /* NB: stat kept for alloc failure */ ++ goto discard; + } + } + iwspy_event(vap, ni, rssi); +@@ -3553,8 +3546,8 @@ ieee80211_recv_mgmt(struct ieee80211vap + (((vap->iv_opmode == IEEE80211_M_HOSTAP) || + (vap->iv_opmode == IEEE80211_M_WDS)) && + (scan.capinfo & IEEE80211_CAPINFO_ESS))) { ++ struct ieee80211_node *tni = NULL; + struct ieee80211vap *avp = NULL; +- int do_unref = 0; + int found = 0; + + IEEE80211_LOCK_IRQ(vap->iv_ic); +@@ -3568,14 +3561,12 @@ ieee80211_recv_mgmt(struct ieee80211vap + } + } + if (found) +- ni = ni_or_null = avp->iv_wdsnode; ++ tni = ieee80211_ref_node(avp->iv_wdsnode); } else if (vap->iv_opmode == IEEE80211_M_WDS) { found = 1; - ni = ni_or_null = vap->iv_wdsnode; +- ni = ni_or_null = vap->iv_wdsnode; - } else if (vap->iv_opmode == IEEE80211_M_IBSS) { -+ } else if ((vap->iv_opmode == IEEE80211_M_IBSS) && (vap->iv_state == IEEE80211_S_RUN)) { - ni_or_null = ieee80211_find_node(&ic->ic_sta, wh->i_addr2); +- ni_or_null = ieee80211_find_node(&ic->ic_sta, wh->i_addr2); - if (ni_or_null) -+ if (ni_or_null) { - ni = ni_or_null; -+ do_unref = 1; -+ } +- ni = ni_or_null; ++ tni = ieee80211_ref_node(vap->iv_wdsnode); ++ } else if ((vap->iv_opmode == IEEE80211_M_IBSS) && (vap->iv_state == IEEE80211_S_RUN)) { ++ tni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2); found = 1; } IEEE80211_UNLOCK_IRQ(vap->iv_ic); +@@ -3583,20 +3574,21 @@ ieee80211_recv_mgmt(struct ieee80211vap + if (!found) + break; + +- if (ni_or_null == NULL) { ++ memcpy(&SKB_CB(skb)->beacon_tsf, scan.tstamp, sizeof(u_int64_t)); ++ ++ if (tni == NULL) { + if (avp) { + IEEE80211_LOCK_IRQ(ic); +- ni = ieee80211_add_neighbor(avp, wh, &scan); ++ tni = ieee80211_add_neighbor(avp, wh, &scan); + /* force assoc */ +- ni->ni_associd |= 0xc000; +- avp->iv_wdsnode = ieee80211_ref_node(ni); ++ tni->ni_associd |= 0xc000; ++ avp->iv_wdsnode = ieee80211_ref_node(tni); + IEEE80211_UNLOCK_IRQ(ic); + } else if ((vap->iv_opmode == IEEE80211_M_IBSS) && + IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) { + /* Create a new entry in the neighbor table. */ +- ni = ieee80211_add_neighbor(vap, wh, &scan); ++ tni = ieee80211_add_neighbor(vap, wh, &scan); + } +- do_unref = 1; + } else { + /* + * Copy data from beacon to neighbor table. +@@ -3604,39 +3596,38 @@ ieee80211_recv_mgmt(struct ieee80211vap + * ieee80211_add_neighbor(), so we just copy + * everything over to be safe. + */ +- ni->ni_esslen = scan.ssid[1]; +- memcpy(ni->ni_essid, scan.ssid + 2, scan.ssid[1]); +- IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3); +- memcpy(ni->ni_tstamp.data, scan.tstamp, +- sizeof(ni->ni_tstamp)); +- ni->ni_inact = ni->ni_inact_reload; +- ni->ni_intval = ++ tni->ni_esslen = scan.ssid[1]; ++ memcpy(tni->ni_essid, scan.ssid + 2, scan.ssid[1]); ++ IEEE80211_ADDR_COPY(tni->ni_bssid, wh->i_addr3); ++ memcpy(tni->ni_tstamp.data, scan.tstamp, ++ sizeof(tni->ni_tstamp)); ++ tni->ni_inact = tni->ni_inact_reload; ++ tni->ni_intval = + IEEE80211_BINTVAL_SANITISE(scan.bintval); +- ni->ni_capinfo = scan.capinfo; +- ni->ni_chan = ic->ic_curchan; +- ni->ni_fhdwell = scan.fhdwell; +- ni->ni_fhindex = scan.fhindex; +- ni->ni_erp = scan.erp; +- ni->ni_timoff = scan.timoff; ++ tni->ni_capinfo = scan.capinfo; ++ tni->ni_chan = ic->ic_curchan; ++ tni->ni_fhdwell = scan.fhdwell; ++ tni->ni_fhindex = scan.fhindex; ++ tni->ni_erp = scan.erp; ++ tni->ni_timoff = scan.timoff; + if (scan.wme != NULL) +- ieee80211_saveie(&ni->ni_wme_ie, scan.wme); ++ ieee80211_saveie(&tni->ni_wme_ie, scan.wme); + if (scan.wpa != NULL) +- ieee80211_saveie(&ni->ni_wpa_ie, scan.wpa); ++ ieee80211_saveie(&tni->ni_wpa_ie, scan.wpa); + if (scan.rsn != NULL) +- ieee80211_saveie(&ni->ni_rsn_ie, scan.rsn); ++ ieee80211_saveie(&tni->ni_rsn_ie, scan.rsn); + if (scan.ath != NULL) +- ieee80211_saveath(ni, scan.ath); ++ ieee80211_saveath(tni, scan.ath); + + /* NB: must be after ni_chan is setup */ +- ieee80211_setup_rates(ni, scan.rates, ++ ieee80211_setup_rates(tni, scan.rates, + scan.xrates, IEEE80211_F_DOSORT); + } +- if (ni != NULL) { +- ni->ni_rssi = rssi; +- ni->ni_rtsf = rtsf; +- ni->ni_last_rx = jiffies; +- if (do_unref) +- ieee80211_unref_node(&ni); ++ if (tni != NULL) { ++ tni->ni_rssi = rssi; ++ tni->ni_rtsf = rtsf; ++ tni->ni_last_rx = jiffies; ++ ieee80211_unref_node(&tni); + } + } + break; --- a/net80211/ieee80211_node.c +++ b/net80211/ieee80211_node.c -@@ -317,16 +317,16 @@ ieee80211_create_ibss(struct ieee80211va +@@ -53,6 +53,7 @@ + + #include <net80211/ieee80211_var.h> + #include <net80211/if_athproto.h> ++#include <net80211/ieee80211_node.h> + + /* + * Association IDs are managed with a bit vector. +@@ -317,16 +318,11 @@ ieee80211_create_ibss(struct ieee80211va /* Check to see if we already have a node for this mac * NB: we gain a node reference here */ - ni = ieee80211_find_txnode(vap, vap->iv_myaddr); -+ ni = ieee80211_find_node(&ic->ic_sta, vap->iv_myaddr); -+ if (ni) { -+ ieee80211_node_leave(ni); -+ ieee80211_unref_node(&ni); -+ } -+ ++ ieee80211_node_table_reset(&ic->ic_sta, vap); + ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr); if (ni == NULL) { - ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr); @@ -51,23 +194,50 @@ } IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr); -@@ -759,6 +759,9 @@ ieee80211_sta_join(struct ieee80211vap * - ieee80211_setup_rates(ni, se->se_rates, se->se_xrates, - IEEE80211_F_DOSORT | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); +@@ -429,8 +425,8 @@ ieee80211_reset_bss(struct ieee80211vap + __func__, ni, MAC_ADDR(vap->iv_myaddr)); + KASSERT(ni != NULL, ("unable to setup inital BSS node")); -+ if (vap->iv_opmode == IEEE80211_M_IBSS) -+ ieee80211_node_table_reset(&vap->iv_ic->ic_sta, vap); -+ - return ieee80211_sta_join1(PASS_NODE(ni)); - } - EXPORT_SYMBOL(ieee80211_sta_join); +- vap->iv_bss = ieee80211_ref_node(ni); +- KASSERT((atomic_read(&vap->iv_bss->ni_refcnt) == 3), ++ vap->iv_bss = ni; ++ KASSERT((atomic_read(&vap->iv_bss->ni_refcnt) == 2), + ("wrong refcount for new node.")); + + if (obss != NULL) { +@@ -647,7 +643,7 @@ ieee80211_sta_join1(struct ieee80211_nod + (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */ + vap->iv_bss = selbs; + IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid); +- if (obss != NULL) { ++ if ((obss != NULL) && (obss != selbs)) { + if (obss->ni_table) + ieee80211_node_leave(obss); + ieee80211_unref_node(&obss); --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -6655,10 +6655,8 @@ ath_recv_mgmt(struct ieee80211vap * vap, +@@ -6625,14 +6625,6 @@ ath_recv_mgmt(struct ieee80211vap * vap, + + sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf); + +- /* Lookup the new node if any (this grabs a reference to it) */ +- ni = ieee80211_find_rxnode(vap->iv_ic, vap, +- (const struct ieee80211_frame_min *)skb->data); +- if (ni == NULL) { +- DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n"); +- return; +- } +- + switch (subtype) { + case IEEE80211_FC0_SUBTYPE_BEACON: + /* update RSSI statistics for use by the HAL */ +@@ -6654,11 +6646,9 @@ ath_recv_mgmt(struct ieee80211vap * vap, + * we do the IBSS merging in software. Also do not merge * if the difference it too small. Otherwise we are playing * tsf-pingpong with other vendors drivers */ - beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf); +- beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf); - if (beacon_tsf > rtsf + 0xffff) { ++ beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf); + if (beacon_tsf > rtsf + 0xffff) ath_hal_settsf64(sc->sc_ah, beacon_tsf - rtsf); - ieee80211_ibss_merge(ni); @@ -75,3 +245,109 @@ break; } /* NB: Fall Through */ +@@ -6680,13 +6670,21 @@ ath_recv_mgmt(struct ieee80211vap * vap, + hw_tsf = ath_hal_gettsf64(sc->sc_ah); + hw_tu = hw_tsf >> 10; + +- beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf); ++ beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf); + beacon_tu = beacon_tsf >> 10; + ++ if (!beacon_tsf) ++ break; ++ ++ if (IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) ++ break; ++ + DPRINTF(sc, ATH_DEBUG_BEACON, +- "Beacon transmitted at %10llx, " ++ "Beacon transmitted from "MAC_FMT" ("MAC_FMT") at %10llx, " + "received at %10llx(%lld), hw TSF " + "%10llx(%lld)\n", ++ MAC_ADDR(wh->i_addr3), ++ MAC_ADDR(vap->iv_bssid), + beacon_tsf, + rtsf, rtsf - beacon_tsf, + hw_tsf, hw_tsf - beacon_tsf); +@@ -6699,39 +6697,13 @@ ath_recv_mgmt(struct ieee80211vap * vap, + do_merge = 1; + } + +- /* Check sc_nexttbtt */ +- if (sc->sc_nexttbtt < hw_tu) { +- DPRINTF(sc, ATH_DEBUG_BEACON, +- "sc_nexttbtt (%8x TU) is in the past " +- "(tsf %8x TU), updating timers\n", +- sc->sc_nexttbtt, hw_tu); +- do_merge = 1; +- } +- +- intval = ni->ni_intval & HAL_BEACON_PERIOD; +-#if 0 +- /* This code is disabled since it would produce +- * unwanted merge. For instance, in a two nodes network +- * A & B, A can merge to B and at the same time, B will +- * merge to A, still having a split */ +- if (intval != 0) { +- if ((sc->sc_nexttbtt % intval) != +- (beacon_tu % intval)) { +- DPRINTF(sc, ATH_DEBUG_BEACON, +- "ibss merge: " +- "sc_nexttbtt %10x TU " +- "(%3d) beacon %10x TU " +- "(%3d)\n", +- sc->sc_nexttbtt, +- sc->sc_nexttbtt % intval, +- beacon_tu, +- beacon_tu % intval); +- do_merge = 1; +- } +- } +-#endif +- if (do_merge) ++ if (do_merge) { ++ /* Lookup the new node if any (this grabs a reference to it) */ ++ ni = ieee80211_find_txnode(vap, wh->i_addr2); ++ memcpy(ni->ni_bssid, wh->i_addr3, IEEE80211_ADDR_LEN); + ieee80211_ibss_merge(ni); ++ ieee80211_unref_node(&ni); ++ } + + if ((sc->sc_opmode == HAL_M_IBSS) && + ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval)) +@@ -6739,8 +6711,6 @@ ath_recv_mgmt(struct ieee80211vap * vap, + } + break; + } +- +- ieee80211_unref_node(&ni); + } + + static void +--- a/net80211/ieee80211_linux.h ++++ b/net80211/ieee80211_linux.h +@@ -411,7 +411,7 @@ typedef spinlock_t acl_lock_t; + * 8 bytes so we reserve/avoid it. + */ + struct ieee80211_cb { +- u_int8_t vlan[8]; /* reserve for vlan tag info */ ++ u_int64_t beacon_tsf; + struct ieee80211_node *ni; + u_int32_t flags; + #define M_LINK0 0x01 /* frame needs WEP encryption */ +--- a/net80211/ieee80211_scan_sta.c ++++ b/net80211/ieee80211_scan_sta.c +@@ -1125,11 +1125,8 @@ adhoc_default_action(struct ieee80211vap + u_int8_t zeroMacAddr[IEEE80211_ADDR_LEN]; + + memset(&zeroMacAddr, 0, IEEE80211_ADDR_LEN); +- if (IEEE80211_ADDR_EQ(se->se_bssid, &zeroMacAddr[0])) { +- ieee80211_create_ibss(vap, se->se_chan); +- return 1; +- } else +- return ieee80211_sta_join(vap, se); ++ ieee80211_create_ibss(vap, se->se_chan); ++ return 1; + } + + static const struct ieee80211_scanner adhoc_default = { |