From: Felix Fietkau Date: Sat, 17 Oct 2009 05:02:13 +0000 (+0000) Subject: madwifi: merge fixes from trunk X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=commitdiff_plain;h=9c36f4938cde5c3ee552252cfece8a1abbf6f274 madwifi: merge fixes from trunk SVN-Revision: 18054 --- diff --git a/package/madwifi/patches/421-channel_handling.patch b/package/madwifi/patches/421-channel_handling.patch index e5302c1389..8424321d76 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 ad2b6d494d..642a9d21d2 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 372000fc8e..2e542bfece 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 ed02ae8f5e..e546b054a8 100644 --- a/package/madwifi/patches/446-single_module.patch +++ b/package/madwifi/patches/446-single_module.patch @@ -351,7 +351,7 @@ #include #include #include -@@ -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/447-sta_reconnect.patch b/package/madwifi/patches/447-sta_reconnect.patch index e6f019ef75..960d1b8ed8 100644 --- a/package/madwifi/patches/447-sta_reconnect.patch +++ b/package/madwifi/patches/447-sta_reconnect.patch @@ -15,19 +15,11 @@ ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan); --- a/net80211/ieee80211_proto.c +++ b/net80211/ieee80211_proto.c -@@ -1512,14 +1512,13 @@ __ieee80211_newstate(struct ieee80211vap - if (arg != 0) - ieee80211_scan_assoc_fail(ic, - vap->iv_bss->ni_macaddr, arg); -+ ieee80211_node_leave(vap->iv_bss); - if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) - ieee80211_check_scan(vap, - IEEE80211_SCAN_ACTIVE, - IEEE80211_SCAN_FOREVER, - vap->iv_des_nssid, vap->iv_des_ssid, - NULL); -- else -- ieee80211_node_leave(vap->iv_bss); +@@ -1602,7 +1602,6 @@ __ieee80211_newstate(struct ieee80211vap + IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); break; - case IEEE80211_S_RUN: /* beacon miss */ - if (vap->iv_opmode == IEEE80211_M_STA) { + case IEEE80211_S_RUN: +- ieee80211_node_leave(ni); + if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { + /* NB: caller specifies ASSOC/REASSOC by arg */ + IEEE80211_SEND_MGMT(ni, arg ? diff --git a/package/madwifi/patches/448-beacon_handling_fixes.patch b/package/madwifi/patches/448-beacon_handling_fixes.patch index 7fe1251ea8..3fa97e2e64 100644 --- a/package/madwifi/patches/448-beacon_handling_fixes.patch +++ b/package/madwifi/patches/448-beacon_handling_fixes.patch @@ -1,26 +1,87 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -512,7 +512,7 @@ MODULE_PARM_DESC(ieee80211_debug, "Load- +@@ -160,7 +160,7 @@ static int ath_check_beacon_done(struct + static void ath_beacon_send(struct ath_softc *, int *, uint64_t hw_tsf); + static void ath_beacon_return(struct ath_softc *, struct ath_buf *); + static void ath_beacon_free(struct ath_softc *); +-static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *); ++static void ath_beacon_config(struct ath_softc *, struct ieee80211vap *, int); + static void ath_hw_beacon_stop(struct ath_softc *sc); + static int ath_desc_alloc(struct ath_softc *); + static void ath_desc_free(struct ath_softc *); +@@ -387,13 +387,11 @@ static void ath_set_timing(struct ath_so + /* calibrate every 30 secs in steady state but check every second at first. */ + static int ath_calinterval = ATH_SHORT_CALINTERVAL; + static int ath_xchanmode = AH_TRUE; /* enable extended channels */ +-static int ath_maxvaps = ATH_MAXVAPS_DEFAULT; /* set default maximum vaps */ + static int bstuck_thresh = BSTUCK_THRESH; /* Stuck beacon count required for reset */ + static char *autocreate = NULL; + static char *ratectl = DEF_RATE_CTL; + static int rfkill = 0; + static int tpc = 1; +-static int maxvaps = -1; + static int xchanmode = -1; + #include "ath_wprobe.c" + static int beacon_cal = 1; +@@ -432,7 +430,6 @@ static struct notifier_block ath_event_b + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52)) + MODULE_PARM(beacon_cal, "i"); +-MODULE_PARM(maxvaps, "i"); + MODULE_PARM(xchanmode, "i"); + MODULE_PARM(rfkill, "i"); + #ifdef ATH_CAP_TPC +@@ -444,7 +441,6 @@ MODULE_PARM(ratectl, "s"); + #else + #include + module_param(beacon_cal, int, 0600); +-module_param(maxvaps, int, 0600); + module_param(xchanmode, int, 0600); + module_param(rfkill, int, 0600); + #ifdef ATH_CAP_TPC +@@ -454,7 +450,6 @@ module_param(bstuck_thresh, int, 0600); + module_param(autocreate, charp, 0600); + module_param(ratectl, charp, 0600); + #endif +-MODULE_PARM_DESC(maxvaps, "Maximum VAPs"); + MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode"); + MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability"); + #ifdef ATH_CAP_TPC +@@ -512,7 +507,7 @@ MODULE_PARM_DESC(ieee80211_debug, "Load- * and use the higher bits as the index of the VAP. */ #define ATH_SET_VAP_BSSID_MASK(bssid_mask) \ - ((bssid_mask)[0] &= ~(((ath_maxvaps-1) << 2) | 0x02)) -+ ((bssid_mask)[0] &= ~(((ATH_MAXVAPS_MAX-1) << 2) | 0x02)) ++ ((bssid_mask)[0] &= ~(((ATH_MAXVAPS_BCN-1) << 2) | 0x02)) #define ATH_GET_VAP_ID(bssid) ((bssid)[0] >> 2) #define ATH_SET_VAP_BSSID(bssid, id) \ do { \ -@@ -604,8 +604,8 @@ ath_attach(u_int16_t devid, struct net_d +@@ -604,8 +599,8 @@ ath_attach(u_int16_t devid, struct net_d /* Allocate space for dynamically determined maximum VAP count */ sc->sc_bslot = - kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL); - memset(sc->sc_bslot, 0, ath_maxvaps * sizeof(struct ieee80211vap*)); -+ kmalloc(ATH_MAXVAPS_MAX * sizeof(struct ieee80211vap*), GFP_KERNEL); -+ memset(sc->sc_bslot, 0, ATH_MAXVAPS_MAX * sizeof(struct ieee80211vap*)); ++ kmalloc(ATH_MAXVAPS_BCN * sizeof(struct ieee80211vap*), GFP_KERNEL); ++ memset(sc->sc_bslot, 0, ATH_MAXVAPS_BCN * sizeof(struct ieee80211vap*)); /* * Cache line size is used to size and align various -@@ -1349,11 +1349,8 @@ ath_vap_create(struct ieee80211com *ic, +@@ -694,13 +689,6 @@ ath_attach(u_int16_t devid, struct net_d + for (i = 0; i < sc->sc_keymax; i++) + ath_hal_keyreset(ah, i); + +- if (maxvaps != -1) { +- ath_maxvaps = maxvaps; +- if (ath_maxvaps < ATH_MAXVAPS_MIN) +- ath_maxvaps = ATH_MAXVAPS_MIN; +- else if (ath_maxvaps > ATH_MAXVAPS_MAX) +- ath_maxvaps = ATH_MAXVAPS_MAX; +- } + if (xchanmode != -1) + ath_xchanmode = xchanmode; + error = ath_getchannels(dev); +@@ -1349,12 +1337,6 @@ ath_vap_create(struct ieee80211com *ic, return NULL; } @@ -29,123 +90,318 @@ - sc->sc_nvaps); - return NULL; - } -+ if ((sc->sc_nvaps >= ath_maxvaps) && (ath_maxvaps < ATH_MAXVAPS_MAX)) -+ ath_maxvaps++; - +- dev = alloc_etherdev(sizeof(struct ath_vap) + sc->sc_rc->arc_vap_space); if (dev == NULL) { -@@ -1451,11 +1448,11 @@ ath_vap_create(struct ieee80211com *ic, + /* XXX msg */ +@@ -1424,7 +1406,7 @@ ath_vap_create(struct ieee80211com *ic, + TAILQ_FOREACH(v, &ic->ic_vaps, iv_next) + id_mask |= (1 << ATH_GET_VAP_ID(v->iv_myaddr)); + +- for (id = 0; id < ath_maxvaps; id++) { ++ for (id = 0; id < ATH_MAXVAPS_BCN; id++) { + /* get the first available slot */ + if ((id_mask & (1 << id)) == 0) { + ATH_SET_VAP_BSSID(vap->iv_myaddr, id); +@@ -1451,11 +1433,11 @@ ath_vap_create(struct ieee80211com *ic, /* Assign the VAP to a beacon xmit slot. As * above, this cannot fail to find one. */ avp->av_bslot = 0; - for (slot = 0; slot < ath_maxvaps; slot++) -+ for (slot = 0; slot < ATH_MAXVAPS_MAX; slot++) ++ for (slot = 0; slot < ATH_MAXVAPS_BCN; slot++) if (sc->sc_bslot[slot] == NULL) { /* XXX: Hack, space out slots to better * deal with misses. */ - if (slot + 1 < ath_maxvaps && -+ if (slot + 1 < ATH_MAXVAPS_DEFAULT && ++ if (slot + 1 < ATH_MAXVAPS_BCN && sc->sc_bslot[slot+1] == NULL) { avp->av_bslot = slot + 1; break; -@@ -1463,11 +1460,16 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1463,8 +1445,11 @@ ath_vap_create(struct ieee80211com *ic, avp->av_bslot = slot; /* NB: keep looking for a double slot */ } - KASSERT(sc->sc_bslot[avp->av_bslot] == NULL, - ("beacon slot %u not empty?", avp->av_bslot)); -+ -+ /* No beacon slot found? */ + if (sc->sc_bslot[avp->av_bslot]) { + free_netdev(dev); + return NULL; + } ++ sc->sc_bslot[avp->av_bslot] = vap; sc->sc_nbcnvaps++; -+#if 0 - if ((opmode == IEEE80211_M_HOSTAP) && (sc->sc_hastsfadd)) { - /* - * Multiple VAPs are to transmit beacons and we -@@ -1485,6 +1487,9 @@ ath_vap_create(struct ieee80211com *ic, - sc->sc_stagbeacons = 1; - } +@@ -1475,15 +1460,7 @@ ath_vap_create(struct ieee80211com *ic, + * of staggered beacons. + */ + /* XXX check for beacon interval too small */ +- if (ath_maxvaps > 4) { +- DPRINTF(sc, ATH_DEBUG_BEACON, +- "Staggered beacons are not " +- "possible with maxvaps set " +- "to %d.\n", ath_maxvaps); +- sc->sc_stagbeacons = 0; +- } else { +- sc->sc_stagbeacons = 1; +- } ++ sc->sc_stagbeacons = 1; } -+#else -+ sc->sc_stagbeacons = sc->sc_hastsfadd; -+#endif DPRINTF(sc, ATH_DEBUG_BEACON, "sc->sc_stagbeacons %sabled\n", (sc->sc_stagbeacons ? "en" : "dis")); +@@ -1553,7 +1530,7 @@ ath_vap_create(struct ieee80211com *ic, + if (ath_startrecv(sc) != 0) /* restart recv */ + EPRINTF(sc, "Unable to start receive logic.\n"); + if (sc->sc_beacons) +- ath_beacon_config(sc, NULL); /* restart beacons */ ++ ath_beacon_config(sc, NULL, 0); /* restart beacons */ + ath_hal_intrset(ah, sc->sc_imask); } -@@ -4968,7 +4973,7 @@ ath_beacon_alloc_internal(struct ath_sof + +@@ -1681,7 +1658,7 @@ ath_vap_delete(struct ieee80211vap *vap) + if (ath_startrecv(sc) != 0) /* restart recv. */ + EPRINTF(sc, "Unable to start receive logic.\n"); + if (sc->sc_beacons) +- ath_beacon_config(sc, NULL); /* restart beacons */ ++ ath_beacon_config(sc, NULL, 0); /* restart beacons */ + ath_hal_intrset(ah, sc->sc_imask); + } + } +@@ -3066,7 +3043,7 @@ ath_reset(struct net_device *dev) + */ + ath_chan_change(sc, c); + if (sc->sc_beacons) +- ath_beacon_config(sc, NULL); /* restart beacons */ ++ ath_beacon_config(sc, NULL, 1); /* restart beacons */ + ath_hal_intrset(ah, sc->sc_imask); + ath_set_ack_bitrate(sc, sc->sc_ackrate); + netif_wake_queue(dev); /* restart xmit */ +@@ -4763,7 +4740,7 @@ ath_check_beacon_done(struct ath_softc * + /* + * check if the last beacon went out with the mode change flag set. + */ +- for (slot = 0; slot < ath_maxvaps; slot++) { ++ for (slot = 0; slot < ATH_MAXVAPS_BCN; slot++) { + if (sc->sc_bslot[slot]) { + vap = sc->sc_bslot[slot]; + break; +@@ -4968,7 +4945,7 @@ ath_beacon_alloc_internal(struct ath_sof * has a timestamp in one beacon interval while the * others get a timestamp aligned to the next interval. */ - tuadjust = (ni->ni_intval * (ath_maxvaps - avp->av_bslot)) / ath_maxvaps; -+ tuadjust = (ni->ni_intval * (ATH_MAXVAPS_DEFAULT - avp->av_bslot)) / ATH_MAXVAPS_DEFAULT; ++ tuadjust = (ni->ni_intval * (ATH_MAXVAPS_BCN - avp->av_bslot)) / ATH_MAXVAPS_BCN; tsfadjust = cpu_to_le64(tuadjust << 10); /* TU->TSF */ DPRINTF(sc, ATH_DEBUG_BEACON, -@@ -5358,21 +5363,40 @@ ath_beacon_send(struct ath_softc *sc, in - */ - if (sc->sc_stagbeacons) { /* staggered beacons */ - struct ieee80211com *ic = &sc->sc_ic; -+ u_int32_t *bflink = NULL; +@@ -5361,8 +5338,8 @@ ath_beacon_send(struct ath_softc *sc, in u_int32_t tsftu; tsftu = hw_tsf >> 10; /* NB: 64 -> 32: See note far above. */ - slot = ((tsftu % ic->ic_lintval) * ath_maxvaps) / ic->ic_lintval; - vap = sc->sc_bslot[(slot + 1) % ath_maxvaps]; -+ slot = ((tsftu % ic->ic_lintval) * ATH_MAXVAPS_DEFAULT) / ic->ic_lintval; ++ slot = ((tsftu % ic->ic_lintval) * ATH_MAXVAPS_BCN) / ic->ic_lintval; ++ vap = sc->sc_bslot[(slot + 1) % ATH_MAXVAPS_BCN]; DPRINTF(sc, ATH_DEBUG_BEACON_PROC, "Slot %d [tsf %llu tsftu %llu intval %u] vap %p\n", slot, (unsigned long long)hw_tsf, - (unsigned long long)tsftu, ic->ic_lintval, vap); - bfaddr = 0; -- if (vap != NULL) { -+ while (slot < ATH_MAXVAPS_MAX) { -+ vap = sc->sc_bslot[slot]; -+ if (vap == NULL) -+ goto next; -+ - bf = ath_beacon_generate(sc, vap, needmark); -- if (bf != NULL) -+ if (bf == NULL) -+ break; -+ -+ if (bflink != NULL) -+#ifdef AH_NEED_DESC_SWAP -+ *bflink = cpu_to_le32(bf->bf_daddr); -+#else -+ *bflink = bf->bf_daddr; -+#endif -+ else - bfaddr = bf->bf_daddr; -+ -+ bflink = &bf->bf_desc->ds_link; -+next: -+ slot += ATH_MAXVAPS_DEFAULT; - } -+ if (bflink != NULL) -+ *bflink = 0; /* link of last frame */ - } else { /* burst'd beacons */ +@@ -5377,7 +5354,7 @@ ath_beacon_send(struct ath_softc *sc, in u_int32_t *bflink = NULL; -@@ -5567,7 +5591,7 @@ ath_beacon_config(struct ath_softc *sc, + /* XXX: rotate/randomize order? */ +- for (slot = 0; slot < ath_maxvaps; slot++) { ++ for (slot = 0; slot < ATH_MAXVAPS_BCN; slot++) { + if ((vap = sc->sc_bslot[slot]) != NULL) { + if ((bf = ath_beacon_generate( + sc, vap, +@@ -5418,7 +5395,7 @@ ath_beacon_send(struct ath_softc *sc, in + * again. If we miss a beacon for that slot then we'll be + * slow to transition but we'll be sure at least one beacon + * interval has passed. When bursting slot is always left +- * set to ath_maxvaps so this check is a no-op. ++ * set to ATH_MAXVAPS_BCN so this check is a no-op. + */ + /* XXX locking */ + if (sc->sc_updateslot == UPDATE) { +@@ -5526,7 +5503,7 @@ ath_beacon_free(struct ath_softc *sc) + * (2^(32 + 10 - 1) - 1)us is a really long time. + */ + static void +-ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) ++ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap, int reset) + { + struct ieee80211com *ic = &sc->sc_ic; + struct ath_hal *ah = sc->sc_ah; +@@ -5553,7 +5530,7 @@ ath_beacon_config(struct ath_softc *sc, + /* We should reset hw TSF only once, so we increment + * ni_tstamp.tsf to avoid resetting the hw TSF multiple + * times */ +- if (tsf == 0) { ++ if (tsf == 0 || reset) { + reset_tsf = 1; + ni->ni_tstamp.tsf = cpu_to_le64(1); + } +@@ -5567,7 +5544,7 @@ ath_beacon_config(struct ath_softc *sc, /* NB: the beacon interval is kept internally in TUs */ intval = ic->ic_lintval & HAL_BEACON_PERIOD; if (sc->sc_stagbeacons) - intval /= ath_maxvaps; /* for staggered beacons */ -+ intval /= ATH_MAXVAPS_DEFAULT; /* for staggered beacons */ ++ intval /= ATH_MAXVAPS_BCN; /* for staggered beacons */ if ((sc->sc_nostabeacons) && (vap->iv_opmode == IEEE80211_M_HOSTAP)) reset_tsf = 1; -@@ -5889,7 +5913,7 @@ ath_desc_alloc(struct ath_softc *sc) +@@ -5583,31 +5560,24 @@ ath_beacon_config(struct ath_softc *sc, + * time */ + nexttbtt = intval; + } else if (intval) { /* NB: can be 0 for monitor mode */ +- if (tsf == 1) { +- /* We have not received any beacons or probe +- * responses. Since a beacon should be sent +- * every 'intval' ms, we compute the next +- * beacon timestamp using the hardware TSF. We +- * ensure that it is at least FUDGE TUs ahead +- * of the current TSF. Otherwise, we use the +- * next beacon timestamp again */ +- nexttbtt = roundup(hw_tsftu + FUDGE, intval); +- } +- else if (ic->ic_opmode == IEEE80211_M_IBSS) { +- if (tsf > hw_tsf) { +- /* We received a beacon, but the HW TSF has +- * not been updated (otherwise hw_tsf > tsf) +- * We cannot use the hardware TSF, so we +- * wait to synchronize beacons again. */ +- sc->sc_syncbeacon = 1; +- goto ath_beacon_config_debug; +- } else { +- /* Normal case: we received a beacon to which +- * we have synchronized. Make sure that nexttbtt +- * is at least FUDGE TU ahead of hw_tsf */ +- nexttbtt = tsftu + roundup(hw_tsftu + FUDGE - +- tsftu, intval); +- } ++ if ((tsf > hw_tsf) && (ic->ic_opmode == IEEE80211_M_IBSS)) { ++ /* We received a beacon, but the HW TSF has ++ * not been updated (otherwise hw_tsf > tsf) ++ * We cannot use the hardware TSF, so we ++ * wait to synchronize beacons again. */ ++ sc->sc_syncbeacon = 1; ++ goto ath_beacon_config_debug; ++ } else if ((tsftu + FUDGE) > hw_tsftu) { ++ if (tsftu > hw_tsftu + 2 * intval) ++ nexttbtt = roundup(hw_tsftu + FUDGE, intval); ++ else ++ nexttbtt = tsftu; ++ } else { ++ /* Normal case: we received a beacon to which ++ * we have synchronized. Make sure that nexttbtt ++ * is at least FUDGE TU ahead of hw_tsf */ ++ nexttbtt = tsftu + roundup(hw_tsftu + FUDGE - ++ tsftu, intval); + } + } + +@@ -5730,9 +5700,6 @@ ath_beacon_config(struct ath_softc *sc, + ath_beacon_dturbo_config(vap, intval & + ~(HAL_BEACON_RESET_TSF | HAL_BEACON_ENA)); + #endif +- if ((nexttbtt & HAL_BEACON_PERIOD) - (ath_hal_gettsf32(ah) >> 10) +- <= ath_hal_sw_beacon_response_time) +- nexttbtt += intval; + sc->sc_nexttbtt = nexttbtt; + + /* stop beacons before reconfiguring the timers to avoid race +@@ -5889,7 +5856,7 @@ ath_desc_alloc(struct ath_softc *sc) /* XXX allocate beacon state together with VAP */ error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf, - "beacon", ath_maxvaps, 1); -+ "beacon", ATH_MAXVAPS_MAX, 1); ++ "beacon", ATH_MAXVAPS_BCN, 1); if (error != 0) { ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf, BUS_DMA_TODEVICE); +@@ -6680,7 +6647,7 @@ ath_recv_mgmt(struct ieee80211vap * vap, + /* Resync beacon timers using the tsf of the + * beacon frame we just received. */ + vap->iv_flags_ext &= ~IEEE80211_FEXT_APPIE_UPDATE; +- ath_beacon_config(sc, vap); ++ ath_beacon_config(sc, vap, 0); + DPRINTF(sc, ATH_DEBUG_BEACON, + "Updated beacon timers\n"); + } +@@ -9359,7 +9326,7 @@ ath_chan_set(struct ath_softc *sc, struc + * HW seems to turn off beacons during turbo mode switch. + */ + if (sc->sc_beacons && !sc->sc_dfs_cac) +- ath_beacon_config(sc, NULL); ++ ath_beacon_config(sc, NULL, 0); + /* + * Re-enable interrupts. + */ +@@ -9813,7 +9780,7 @@ ath_newstate(struct ieee80211vap *vap, e + ATH_DEBUG_BEACON_PROC, + "Beacons reconfigured by %p[%s]!\n", + vap, vap->iv_nickname); +- ath_beacon_config(sc, vap); ++ ath_beacon_config(sc, vap, 1); + sc->sc_beacons = 1; + } + } else { +@@ -9948,9 +9915,6 @@ ath_dfs_cac_completed(unsigned long data + } + netif_wake_queue(dev); + ath_reset(dev); +- if (sc->sc_beacons) { +- ath_beacon_config(sc, NULL); +- } + dev->watchdog_timeo = 5 * HZ; /* restore normal timeout */ + } else { + do_gettimeofday(&tv); +@@ -11473,9 +11437,6 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl + case ATH_OUTDOOR: + val = ic->ic_country_outdoor; + break; +- case ATH_MAXVAPS: +- val = ath_maxvaps; +- break; + case ATH_REGDOMAIN: + ath_hal_getregdomain(ah, &val); + break; +@@ -11606,12 +11567,6 @@ static const ctl_table ath_sysctl_templa + .extra2 = (void *)ATH_OUTDOOR, + }, + { .ctl_name = CTL_AUTO, +- .procname = "maxvaps", +- .mode = 0444, +- .proc_handler = ath_sysctl_halparam, +- .extra2 = (void *)ATH_MAXVAPS, +- }, +- { .ctl_name = CTL_AUTO, + .procname = "regdomain", + .mode = 0644, + .proc_handler = ath_sysctl_halparam, +@@ -11928,13 +11883,6 @@ static ctl_table ath_static_sysctls[] = + }, + #endif + { .ctl_name = CTL_AUTO, +- .procname = "maxvaps", +- .mode = 0444, +- .data = &ath_maxvaps, +- .maxlen = sizeof(ath_maxvaps), +- .proc_handler = proc_dointvec +- }, +- { .ctl_name = CTL_AUTO, + .procname = "xchanmode", + .mode = 0444, + .data = &ath_xchanmode, +--- a/ath/if_athvar.h ++++ b/ath/if_athvar.h +@@ -211,9 +211,7 @@ static inline struct net_device *_alloc_ + #define ATH_RXBUF 40 /* number of RX buffers */ + #define ATH_TXBUF 200 /* number of TX buffers */ + +-#define ATH_MAXVAPS_MIN 2 /* minimum number of beacon buffers */ +-#define ATH_MAXVAPS_MAX 64 /* maximum number of beacon buffers */ +-#define ATH_MAXVAPS_DEFAULT 4 /* default number of beacon buffers */ ++#define ATH_MAXVAPS_BCN 4 /* maximum number of beacon buffers */ + + /* free buffer threshold to restart net dev */ + #define ATH_TXBUF_FREE_THRESHOLD (ATH_TXBUF / 20) diff --git a/package/madwifi/patches/449-fix_txbuf_leak.patch b/package/madwifi/patches/449-fix_txbuf_leak.patch index 9fd5ecb74c..31f2fef3a8 100644 --- a/package/madwifi/patches/449-fix_txbuf_leak.patch +++ b/package/madwifi/patches/449-fix_txbuf_leak.patch @@ -1,6 +1,6 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -3725,6 +3725,7 @@ ff_bypass: +@@ -3697,6 +3697,7 @@ ff_bypass: */ skb = ieee80211_encap(ni, skb, &framecnt); if (skb == NULL) { diff --git a/package/madwifi/patches/450-calibration.patch b/package/madwifi/patches/450-calibration.patch index 76ff7a75f6..87397903dc 100644 --- a/package/madwifi/patches/450-calibration.patch +++ b/package/madwifi/patches/450-calibration.patch @@ -1,30 +1,30 @@ --- a/ath/if_ath.c +++ b/ath/if_ath.c -@@ -396,7 +396,6 @@ static int tpc = 1; - static int maxvaps = -1; +@@ -394,7 +394,6 @@ static int rfkill = 0; + static int tpc = 1; static int xchanmode = -1; #include "ath_wprobe.c" -static int beacon_cal = 1; static const struct ath_hw_detect generic_hw_info = { .vendor_name = "Unknown", -@@ -431,7 +430,6 @@ static struct notifier_block ath_event_b +@@ -429,7 +428,6 @@ static struct notifier_block ath_event_b }; #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52)) -MODULE_PARM(beacon_cal, "i"); - MODULE_PARM(maxvaps, "i"); MODULE_PARM(xchanmode, "i"); MODULE_PARM(rfkill, "i"); -@@ -443,7 +441,6 @@ MODULE_PARM(autocreate, "s"); + #ifdef ATH_CAP_TPC +@@ -440,7 +438,6 @@ MODULE_PARM(autocreate, "s"); MODULE_PARM(ratectl, "s"); #else #include -module_param(beacon_cal, int, 0600); - module_param(maxvaps, int, 0600); module_param(xchanmode, int, 0600); module_param(rfkill, int, 0600); -@@ -837,6 +834,7 @@ ath_attach(u_int16_t devid, struct net_d + #ifdef ATH_CAP_TPC +@@ -825,6 +822,7 @@ ath_attach(u_int16_t devid, struct net_d error = EIO; goto bad2; } @@ -32,7 +32,7 @@ init_timer(&sc->sc_cal_ch); sc->sc_cal_ch.function = ath_calibrate; sc->sc_cal_ch.data = (unsigned long) dev; -@@ -2765,8 +2763,7 @@ ath_stop_locked(struct net_device *dev) +@@ -2737,8 +2735,7 @@ ath_stop_locked(struct net_device *dev) } if (!sc->sc_invalid) { del_timer_sync(&sc->sc_dfs_cac_timer); @@ -42,7 +42,7 @@ } ath_draintxq(sc); if (!sc->sc_invalid) { -@@ -2791,10 +2788,9 @@ static void ath_set_beacon_cal(struct at +@@ -2763,10 +2760,9 @@ static void ath_set_beacon_cal(struct at if (val) { del_timer_sync(&sc->sc_cal_ch); } else { @@ -55,7 +55,7 @@ } /* -@@ -3036,7 +3032,7 @@ ath_reset(struct net_device *dev) +@@ -3008,7 +3004,7 @@ ath_reset(struct net_device *dev) * XXX: starting the calibration too early seems to lead to * problems with the beacons. */ @@ -64,7 +64,7 @@ /* * Convert to a HAL channel description with the flags -@@ -5477,10 +5473,9 @@ next: +@@ -5430,10 +5426,9 @@ ath_beacon_send(struct ath_softc *sc, in "Invoking ath_hal_txstart with sc_bhalq: %d\n", sc->sc_bhalq); ath_hal_txstart(ah, sc->sc_bhalq); @@ -78,7 +78,7 @@ sc->sc_stats.ast_be_xmit++; /* XXX per-VAP? */ } -@@ -9161,6 +9156,7 @@ ath_startrecv(struct ath_softc *sc) +@@ -9104,6 +9099,7 @@ ath_startrecv(struct ath_softc *sc) dev->mtu, sc->sc_cachelsz, sc->sc_rxbufsize); sc->sc_rxlink = NULL; @@ -86,7 +86,7 @@ STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) { int error = ath_rxbuf_init(sc, bf); ATH_RXBUF_RESET(bf); -@@ -9377,7 +9373,7 @@ ath_chan_set(struct ath_softc *sc, struc +@@ -9320,7 +9316,7 @@ ath_chan_set(struct ath_softc *sc, struc jiffies + (sc->sc_dfs_cac_period * HZ)); /* This is a good time to start a calibration */ @@ -95,7 +95,7 @@ } /* * re configure beacons when it is a turbo mode switch. -@@ -9471,25 +9467,23 @@ ath_calibrate(unsigned long arg) +@@ -9414,25 +9410,23 @@ ath_calibrate(unsigned long arg) if (isIQdone == AH_TRUE) { /* Unless user has overridden calibration interval, * upgrade to less frequent calibration */ @@ -128,7 +128,7 @@ } static void -@@ -9597,9 +9591,6 @@ ath_newstate(struct ieee80211vap *vap, e +@@ -9540,9 +9534,6 @@ ath_newstate(struct ieee80211vap *vap, e ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); @@ -138,7 +138,7 @@ ath_hal_setledstate(ah, leds[nstate]); /* set LED */ netif_stop_queue(dev); /* before we do anything else */ -@@ -9821,10 +9812,7 @@ ath_newstate(struct ieee80211vap *vap, e +@@ -9764,10 +9755,7 @@ ath_newstate(struct ieee80211vap *vap, e IEEE80211_IS_MODE_DFS_MASTER(vap->iv_opmode)) { DPRINTF(sc, ATH_DEBUG_STATE | ATH_DEBUG_DOTH, "VAP -> DFSWAIT_PENDING \n"); @@ -150,7 +150,7 @@ /* wake the receiver */ netif_wake_queue(dev); /* don't do the other usual stuff... */ -@@ -9866,12 +9854,6 @@ done: +@@ -9809,12 +9797,6 @@ done: /* Invoke the parent method to complete the work. */ error = avp->av_newstate(vap, nstate, arg); @@ -165,7 +165,7 @@ nstate == IEEE80211_S_RUN) --- a/ath/if_athvar.h +++ b/ath/if_athvar.h -@@ -834,7 +834,8 @@ struct ath_softc { +@@ -832,7 +832,8 @@ struct ath_softc { struct ieee80211_channel *sc_last_chan; int sc_beacon_cal; /* use beacon timer for calibration */ diff --git a/package/madwifi/patches/451-ibss_race_fix.patch b/package/madwifi/patches/451-ibss_race_fix.patch new file mode 100644 index 0000000000..9be3311fda --- /dev/null +++ b/package/madwifi/patches/451-ibss_race_fix.patch @@ -0,0 +1,353 @@ +--- a/net80211/ieee80211_input.c ++++ b/net80211/ieee80211_input.c +@@ -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); ++ 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; +- } else if (vap->iv_opmode == IEEE80211_M_IBSS) { +- ni_or_null = ieee80211_find_node(&ic->ic_sta, wh->i_addr2); +- if (ni_or_null) +- 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 +@@ -53,6 +53,7 @@ + + #include + #include ++#include + + /* + * 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); ++ 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); +- IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, +- "%s: ni:%p allocated for " MAC_FMT "\n", +- __func__, ni, MAC_ADDR(vap->iv_myaddr)); +- if (ni == NULL) { +- /* XXX recovery? */ +- return; +- } ++ /* XXX recovery? */ ++ return; + } + + IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr); +@@ -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")); + +- 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 +@@ -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); +- 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); +- } + 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 = { diff --git a/package/madwifi/patches/452-minstrel_no_timer.patch b/package/madwifi/patches/452-minstrel_no_timer.patch new file mode 100644 index 0000000000..e7f2deac1c --- /dev/null +++ b/package/madwifi/patches/452-minstrel_no_timer.patch @@ -0,0 +1,134 @@ +--- a/ath_rate/minstrel/minstrel.c ++++ b/ath_rate/minstrel/minstrel.c +@@ -119,6 +119,7 @@ + #include "minstrel.h" + + #define ONE_SECOND (1000 * 1000) /* 1 second, or 1000 milliseconds; eternity, in other words */ ++#define TIMER_INTERVAL 100 /* msecs */ + + #include "release.h" + +@@ -128,9 +129,6 @@ static char *dev_info = "ath_rate_minstr + #define STALE_FAILURE_TIMEOUT_MS 10000 + #define ENABLE_MRR 1 + +-static int ath_timer_interval = (1000 / 10); /* every 1/10 second, timer runs */ +-static void ath_timer_function(unsigned long data); +- + /* 10% of the time, send a packet at something other than the optimal rate, which fills + * the statistics tables nicely. This percentage is applied to the first packet of the + * multi rate retry chain. */ +@@ -142,7 +140,7 @@ static void ath_rate_ctl_reset(struct at + /* Calculate the throughput and probability of success for each node + * we are talking on, based on the statistics collected during the + * last timer period. */ +-static void ath_rate_statistics(void *arg, struct ieee80211_node *ni); ++static void ath_rate_statistics(struct ieee80211_node *ni); + + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52)) +@@ -204,6 +202,11 @@ ath_rate_findrate(struct ath_softc *sc, + unsigned int ndx, offset; + int mrr; + ++ ++ if (sn->last_update + msecs_to_jiffies(TIMER_INTERVAL) < jiffies) { ++ ath_rate_statistics(&an->an_node); ++ sn->last_update = jiffies; ++ } + if (sn->num_rates <= 0) { + printk(KERN_WARNING "%s: no rates for " MAC_FMT "?\n", + dev_info, +@@ -640,54 +643,11 @@ ath_rate_newstate(struct ieee80211vap *v + } + } + +-static void +-ath_timer_function(unsigned long data) +-{ +- struct minstrel_softc *ssc = (struct minstrel_softc *) data; +- struct ath_softc *sc = ssc->sc; +- struct ieee80211com *ic; +- struct net_device *dev = ssc->sc_dev; +- struct timer_list *timer; +- unsigned int interval = ath_timer_interval; +- +- if (dev == NULL) +- DPRINTF(sc, ATH_DEBUG_RATE, "%s: 'dev' is null in this timer \n", __func__); +- +- if (sc == NULL) +- DPRINTF(sc, ATH_DEBUG_RATE, "%s: 'sc' is null in this timer\n", __func__); +- +- ic = &sc->sc_ic; +- +- if (ssc->close_timer_now) +- return; +- +- if (dev->flags & IFF_RUNNING) { +- sc->sc_stats.ast_rate_calls++; +- +- if (ic->ic_opmode == IEEE80211_M_STA) { +- struct ieee80211vap *tmpvap; +- TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { +- ath_rate_statistics(sc, tmpvap->iv_bss);/* NB: no reference */ +- } +- } else +- ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_statistics, sc); +- } +- +- if (ic->ic_opmode == IEEE80211_M_STA) +- interval = ath_timer_interval >> 1; +- +- timer = &(ssc->timer); +- if (timer == NULL) +- DPRINTF(sc, ATH_DEBUG_RATE, "%s: timer is null - leave it\n", __func__); +- +- timer->expires = jiffies + ((HZ * interval) / 1000); +- add_timer(timer); +-} + + static void +-ath_rate_statistics(void *arg, struct ieee80211_node *ni) ++ath_rate_statistics(struct ieee80211_node *ni) + { +- struct ath_node *an = (struct ath_node *) ni; ++ struct ath_node *an = ATH_NODE(ni); + struct ieee80211_rateset *rs = &ni->ni_rates; + struct minstrel_node *rn = ATH_NODE_MINSTREL(an); + unsigned int i; +@@ -786,15 +746,8 @@ ath_rate_attach(struct ath_softc *sc) + osc->arc.arc_space = sizeof(struct minstrel_node); + osc->arc.arc_vap_space = 0; + +- osc->close_timer_now = 0; +- init_timer(&osc->timer); + osc->sc = sc; + osc->sc_dev = sc->sc_dev; +- osc->timer.function = ath_timer_function; +- osc->timer.data = (unsigned long)osc; +- +- osc->timer.expires = jiffies + HZ; +- add_timer(&osc->timer); + + return &osc->arc; + } +@@ -803,8 +756,6 @@ static void + ath_rate_detach(struct ath_ratectrl *arc) + { + struct minstrel_softc *osc = (struct minstrel_softc *) arc; +- osc->close_timer_now = 1; +- del_timer(&osc->timer); + kfree(osc); + _MOD_DEC_USE(THIS_MODULE); + } +--- a/ath_rate/minstrel/minstrel.h ++++ b/ath_rate/minstrel/minstrel.h +@@ -167,6 +167,8 @@ struct minstrel_node { + packet, or a packet at an optimal rate.*/ + int random_n; + int a, b; /**Coefficients of the random thing */ ++ ++ unsigned long last_update; + }; + +