X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=blobdiff_plain;f=package%2Fmadwifi%2Fpatches%2F421-channel_handling.patch;fp=package%2Fmadwifi%2Fpatches%2F421-channel_handling.patch;h=0000000000000000000000000000000000000000;hp=2a8ec27ce3f3ddab626e07a6bff8ceb074f64fee;hb=3989dddaabe614a69432b34a3abb7e29bae9c0b5;hpb=9ab567885aeb883c4bf293e1ad1d84185b676bc6 diff --git a/package/madwifi/patches/421-channel_handling.patch b/package/madwifi/patches/421-channel_handling.patch deleted file mode 100644 index 2a8ec27ce3..0000000000 --- a/package/madwifi/patches/421-channel_handling.patch +++ /dev/null @@ -1,1351 +0,0 @@ ---- a/ath/if_ath.c -+++ b/ath/if_ath.c -@@ -148,7 +148,6 @@ static int ath_key_set(struct ieee80211v - static void ath_key_update_begin(struct ieee80211vap *); - static void ath_key_update_end(struct ieee80211vap *); - static void ath_mode_init(struct net_device *); --static void ath_setslottime(struct ath_softc *); - static void ath_updateslot(struct net_device *); - static int ath_beaconq_setup(struct ath_softc *); - static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *); -@@ -240,7 +239,7 @@ static void ath_setup_stationkey(struct - static void ath_setup_stationwepkey(struct ieee80211_node *); - static void ath_setup_keycacheslot(struct ath_softc *, struct ieee80211_node *); - static void ath_newassoc(struct ieee80211_node *, int); --static int ath_getchannels(struct net_device *, u_int, HAL_BOOL, HAL_BOOL); -+static int ath_getchannels(struct net_device *); - static void ath_led_event(struct ath_softc *, int); - static void ath_update_txpow(struct ath_softc *); - -@@ -265,7 +264,6 @@ static int ath_change_mtu(struct net_dev - static int ath_ioctl(struct net_device *, struct ifreq *, int); - - static int ath_rate_setup(struct net_device *, u_int); --static void ath_setup_subrates(struct net_device *); - #ifdef ATH_SUPERG_XR - static int ath_xr_rate_setup(struct net_device *); - static void ath_grppoll_txq_setup(struct ath_softc *, int, int); -@@ -387,8 +385,6 @@ static void ath_fetch_idle_time(struct a - - /* calibrate every 30 secs in steady state but check every second at first. */ - static int ath_calinterval = ATH_SHORT_CALINTERVAL; --static int ath_countrycode = CTRY_DEFAULT; /* country code */ --static int ath_outdoor = AH_FALSE; /* enable outdoor use */ - 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 */ -@@ -396,9 +392,7 @@ static char *autocreate = NULL; - static char *ratectl = DEF_RATE_CTL; - static int rfkill = 0; - static int tpc = 1; --static int countrycode = -1; - static int maxvaps = -1; --static int outdoor = -1; - static int xchanmode = -1; - #include "ath_wprobe.c" - static int beacon_cal = 1; -@@ -437,9 +431,7 @@ static struct notifier_block ath_event_b - - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52)) - MODULE_PARM(beacon_cal, "i"); --MODULE_PARM(countrycode, "i"); - MODULE_PARM(maxvaps, "i"); --MODULE_PARM(outdoor, "i"); - MODULE_PARM(xchanmode, "i"); - MODULE_PARM(rfkill, "i"); - #ifdef ATH_CAP_TPC -@@ -451,9 +443,7 @@ MODULE_PARM(ratectl, "s"); - #else - #include - module_param(beacon_cal, int, 0600); --module_param(countrycode, int, 0600); - module_param(maxvaps, int, 0600); --module_param(outdoor, int, 0600); - module_param(xchanmode, int, 0600); - module_param(rfkill, int, 0600); - #ifdef ATH_CAP_TPC -@@ -463,9 +453,7 @@ module_param(bstuck_thresh, int, 0600); - module_param(autocreate, charp, 0600); - module_param(ratectl, charp, 0600); - #endif --MODULE_PARM_DESC(countrycode, "Override default country code"); - MODULE_PARM_DESC(maxvaps, "Maximum VAPs"); --MODULE_PARM_DESC(outdoor, "Enable/disable outdoor use"); - MODULE_PARM_DESC(xchanmode, "Enable/disable extended channel mode"); - MODULE_PARM_DESC(rfkill, "Enable/disable RFKILL capability"); - #ifdef ATH_CAP_TPC -@@ -531,6 +519,50 @@ MODULE_PARM_DESC(ieee80211_debug, "Load- - (bssid)[0] |= (((id) << 2) | 0x02); \ - } while (0) - -+static inline int ath_chan2mode(struct ieee80211_channel *c) -+{ -+ if (IEEE80211_IS_CHAN_HALF(c)) -+ return ATH_MODE_HALF; -+ else if (IEEE80211_IS_CHAN_QUARTER(c)) -+ return ATH_MODE_QUARTER; -+ else -+ return ieee80211_chan2mode(c); -+} -+ -+static inline int rate_hal2ieee(int dot11Rate, int f) -+{ -+ int flag = dot11Rate & ~(IEEE80211_RATE_VAL); -+ dot11Rate &= IEEE80211_RATE_VAL; -+ -+ if (f == 4) { /* Quarter */ -+ if (dot11Rate == 4) -+ return 18 | flag; -+ } -+ return (dot11Rate * f) | flag; -+} -+ -+static inline int rate_factor(int mode) -+{ -+ int f; -+ -+ /* -+ * NB: Fix up rates. HAL returns half or quarter dot11Rates, -+ * while the stack deals with full rates only -+ */ -+ switch(mode) { -+ case ATH_MODE_HALF: -+ f = 2; -+ break; -+ case ATH_MODE_QUARTER: -+ f = 4; -+ break; -+ default: -+ f = 1; -+ break; -+ } -+ return f; -+} -+ - /* Initialize ath_softc structure */ - - int -@@ -647,14 +679,6 @@ ath_attach(u_int16_t devid, struct net_d - for (i = 0; i < sc->sc_keymax; i++) - ath_hal_keyreset(ah, i); - -- /* -- * Collect the channel list using the default country -- * code and including outdoor channels. The 802.11 layer -- * is responsible for filtering this list based on settings -- * like the phy mode. -- */ -- if (countrycode != -1) -- ath_countrycode = countrycode; - if (maxvaps != -1) { - ath_maxvaps = maxvaps; - if (ath_maxvaps < ATH_MAXVAPS_MIN) -@@ -662,17 +686,14 @@ ath_attach(u_int16_t devid, struct net_d - else if (ath_maxvaps > ATH_MAXVAPS_MAX) - ath_maxvaps = ATH_MAXVAPS_MAX; - } -- if (outdoor != -1) -- ath_outdoor = outdoor; - if (xchanmode != -1) - ath_xchanmode = xchanmode; -- error = ath_getchannels(dev, ath_countrycode, -- ath_outdoor, ath_xchanmode); -+ error = ath_getchannels(dev); - if (error != 0) - goto bad; - -- ic->ic_country_code = ath_countrycode; -- ic->ic_country_outdoor = ath_outdoor; -+ ic->ic_country_code = CTRY_DEFAULT; -+ ic->ic_country_outdoor = 0; - - IPRINTF(sc, "Switching rfkill capability %s\n", - rfkill ? "on" : "off"); -@@ -686,9 +707,8 @@ ath_attach(u_int16_t devid, struct net_d - ath_rate_setup(dev, IEEE80211_MODE_11G); - ath_rate_setup(dev, IEEE80211_MODE_TURBO_A); - ath_rate_setup(dev, IEEE80211_MODE_TURBO_G); -- -- /* Setup for half/quarter rates */ -- ath_setup_subrates(dev); -+ ath_rate_setup(dev, ATH_MODE_HALF); -+ ath_rate_setup(dev, ATH_MODE_QUARTER); - - /* NB: setup here so ath_rate_update is happy */ - ath_setcurmode(sc, IEEE80211_MODE_11A); -@@ -908,10 +928,6 @@ ath_attach(u_int16_t devid, struct net_d - IEEE80211_ATHC_COMP : 0); - #endif - --#ifdef ATH_SUPERG_DYNTURBO -- ic->ic_ath_cap |= (ath_hal_turboagsupported(ah, ath_countrycode) ? -- (IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR) : 0); --#endif - #ifdef ATH_SUPERG_XR - ic->ic_ath_cap |= (ath_hal_xrsupported(ah) ? IEEE80211_ATHC_XR : 0); - #endif -@@ -4470,17 +4486,17 @@ ath_mode_init(struct net_device *dev) - * Set the slot time based on the current setting. - */ - static void --ath_setslottime(struct ath_softc *sc) -+ath_settiming(struct ath_softc *sc) - { -- struct ieee80211com *ic = &sc->sc_ic; - struct ath_hal *ah = sc->sc_ah; -+ u_int offset = getTimingOffset(sc); - -- if (sc->sc_slottimeconf > 0) /* manual override */ -- ath_hal_setslottime(ah, sc->sc_slottimeconf); -- else if (ic->ic_flags & IEEE80211_F_SHSLOT) -- ath_hal_setslottime(ah, HAL_SLOT_TIME_9); -- else -- ath_hal_setslottime(ah, HAL_SLOT_TIME_20); -+ if (sc->sc_slottimeconf > 0) -+ ath_hal_setslottime(ah, offset + sc->sc_slottimeconf); -+ if (sc->sc_acktimeconf > 0) -+ ath_hal_setacktimeout(ah, 2 * offset + sc->sc_acktimeconf); -+ if (sc->sc_ctstimeconf > 0) -+ ath_hal_setctstimeout(ah, 2 * offset + sc->sc_ctstimeconf); - sc->sc_updateslot = OK; - } - -@@ -4502,7 +4518,7 @@ ath_updateslot(struct net_device *dev) - if (ic->ic_opmode == IEEE80211_M_HOSTAP) - sc->sc_updateslot = UPDATE; - else if (dev->flags & IFF_RUNNING) -- ath_setslottime(sc); -+ ath_settiming(sc); - } - - #ifdef ATH_SUPERG_DYNTURBO -@@ -5346,7 +5362,7 @@ ath_beacon_send(struct ath_softc *sc, in - sc->sc_updateslot = COMMIT; /* commit next beacon */ - sc->sc_slotupdate = slot; - } else if ((sc->sc_updateslot == COMMIT) && (sc->sc_slotupdate == slot)) -- ath_setslottime(sc); /* commit change to hardware */ -+ ath_settiming(sc); /* commit change to hardware */ - - if (bfaddr != 0) { - /* -@@ -7802,12 +7818,14 @@ ath_get_ivlen(struct ieee80211_key *k) - * Get transmit rate index using rate in Kbps - */ - static __inline int --ath_tx_findindex(const HAL_RATE_TABLE *rt, int rate) -+ath_tx_findindex(struct ath_softc *sc, const HAL_RATE_TABLE *rt, int rate) - { - unsigned int i, ndx = 0; -+ int f; - -+ f = rate_factor(sc->sc_curmode); - for (i = 0; i < rt->rateCount; i++) { -- if (rt->info[i].rateKbps == rate) { -+ if ((rt->info[i].rateKbps * f) == rate) { - ndx = i; - break; - } -@@ -8100,7 +8118,7 @@ ath_tx_start(struct net_device *dev, str - atype = HAL_PKT_TYPE_NORMAL; /* default */ - - if (ismcast) { -- rix = ath_tx_findindex(rt, vap->iv_mcast_rate); -+ rix = ath_tx_findindex(sc, rt, vap->iv_mcast_rate); - txrate = rt->info[rix].rateCode; - if (shortPreamble) - txrate |= rt->info[rix].shortPreamble; -@@ -9067,7 +9085,7 @@ ath_chan_change(struct ath_softc *sc, st - struct net_device *dev = sc->sc_dev; - enum ieee80211_phymode mode; - -- mode = ieee80211_chan2mode(chan); -+ mode = ath_chan2mode(chan); - - ath_rate_setup(dev, mode); - ath_setcurmode(sc, mode); -@@ -10124,8 +10142,7 @@ ath_newassoc(struct ieee80211_node *ni, - } - - static int --ath_getchannels(struct net_device *dev, u_int cc, -- HAL_BOOL outdoor, HAL_BOOL xchanmode) -+ath_getchannels(struct net_device *dev) - { - struct ath_softc *sc = dev->priv; - struct ieee80211com *ic = &sc->sc_ic; -@@ -10139,17 +10156,31 @@ ath_getchannels(struct net_device *dev, - EPRINTF(sc, "Insufficient memory for channel table!\n"); - return -ENOMEM; - } -+ -+restart: - if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan, - ic->ic_regclassids, IEEE80211_REGCLASSIDS_MAX, &ic->ic_nregclass, -- cc, HAL_MODE_ALL, outdoor, xchanmode)) { -+ ic->ic_country_code, HAL_MODE_ALL, ic->ic_country_outdoor, ath_xchanmode)) { - u_int32_t rd; - - ath_hal_getregdomain(ah, &rd); - EPRINTF(sc, "Unable to collect channel list from HAL; " -- "regdomain likely %u country code %u\n", rd, cc); -+ "regdomain likely %u country code %u\n", rd, ic->ic_country_code); -+ if ((ic->ic_country_code != CTRY_DEFAULT) || -+ (ic->ic_country_outdoor != 0)) { -+ EPRINTF(sc, "Reverting to defaults\n"); -+ ic->ic_country_code = CTRY_DEFAULT; -+ ic->ic_country_outdoor = 0; -+ goto restart; -+ } - kfree(chans); - return -EINVAL; - } -+#ifdef ATH_SUPERG_DYNTURBO -+ ic->ic_ath_cap &= ~(IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR); -+ ic->ic_ath_cap |= (ath_hal_turboagsupported(ah, ic->ic_country_code) ? -+ (IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR) : 0); -+#endif - /* - * Convert HAL channels to ieee80211 ones. - */ -@@ -10395,7 +10426,7 @@ ath_xr_rate_setup(struct net_device *dev - struct ieee80211com *ic = &sc->sc_ic; - const HAL_RATE_TABLE *rt; - struct ieee80211_rateset *rs; -- unsigned int i, maxrates; -+ unsigned int i, j, maxrates; - sc->sc_xr_rates = ath_hal_getratetable(ah, HAL_MODE_XR); - rt = sc->sc_xr_rates; - if (rt == NULL) -@@ -10408,57 +10439,16 @@ ath_xr_rate_setup(struct net_device *dev - } else - maxrates = rt->rateCount; - rs = &ic->ic_sup_xr_rates; -- for (i = 0; i < maxrates; i++) -- rs->rs_rates[i] = rt->info[i].dot11Rate; -- rs->rs_nrates = maxrates; -+ for (j = 0, i = 0; i < maxrates; i++) { -+ if (!rt->info[i].valid) -+ continue; -+ rs->rs_rates[j++] = rt->info[i].dot11Rate; -+ } -+ rs->rs_nrates = j; - return 1; - } - #endif - --/* Setup half/quarter rate table support */ --static void --ath_setup_subrates(struct net_device *dev) --{ -- struct ath_softc *sc = dev->priv; -- struct ath_hal *ah = sc->sc_ah; -- struct ieee80211com *ic = &sc->sc_ic; -- const HAL_RATE_TABLE *rt; -- struct ieee80211_rateset *rs; -- unsigned int i, maxrates; -- -- sc->sc_half_rates = ath_hal_getratetable(ah, HAL_MODE_11A_HALF_RATE); -- rt = sc->sc_half_rates; -- if (rt != NULL) { -- if (rt->rateCount > IEEE80211_RATE_MAXSIZE) { -- DPRINTF(sc, ATH_DEBUG_ANY, -- "The rate table is too small (%u > %u)\n", -- rt->rateCount, IEEE80211_RATE_MAXSIZE); -- maxrates = IEEE80211_RATE_MAXSIZE; -- } else -- maxrates = rt->rateCount; -- rs = &ic->ic_sup_half_rates; -- for (i = 0; i < maxrates; i++) -- rs->rs_rates[i] = rt->info[i].dot11Rate; -- rs->rs_nrates = maxrates; -- } -- -- sc->sc_quarter_rates = ath_hal_getratetable(ah, HAL_MODE_11A_QUARTER_RATE); -- rt = sc->sc_quarter_rates; -- if (rt != NULL) { -- if (rt->rateCount > IEEE80211_RATE_MAXSIZE) { -- DPRINTF(sc, ATH_DEBUG_ANY, -- "The rate table is too small (%u > %u)\n", -- rt->rateCount, IEEE80211_RATE_MAXSIZE); -- maxrates = IEEE80211_RATE_MAXSIZE; -- } else -- maxrates = rt->rateCount; -- rs = &ic->ic_sup_quarter_rates; -- for (i = 0; i < maxrates; i++) -- rs->rs_rates[i] = rt->info[i].dot11Rate; -- rs->rs_nrates = maxrates; -- } --} -- - static int - ath_rate_setup(struct net_device *dev, u_int mode) - { -@@ -10467,7 +10457,7 @@ ath_rate_setup(struct net_device *dev, u - struct ieee80211com *ic = &sc->sc_ic; - const HAL_RATE_TABLE *rt; - struct ieee80211_rateset *rs; -- unsigned int i, maxrates; -+ unsigned int i, j, maxrates, f; - - switch (mode) { - case IEEE80211_MODE_11A: -@@ -10485,6 +10475,12 @@ ath_rate_setup(struct net_device *dev, u - case IEEE80211_MODE_TURBO_G: - sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_108G); - break; -+ case ATH_MODE_HALF: -+ sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11A_HALF_RATE); -+ break; -+ case ATH_MODE_QUARTER: -+ sc->sc_rates[mode] = ath_hal_getratetable(ah, HAL_MODE_11A_QUARTER_RATE); -+ break; - default: - DPRINTF(sc, ATH_DEBUG_ANY, "Invalid mode %u\n", mode); - return 0; -@@ -10499,10 +10495,16 @@ ath_rate_setup(struct net_device *dev, u - maxrates = IEEE80211_RATE_MAXSIZE; - } else - maxrates = rt->rateCount; -+ -+ /* NB: quarter/half rate channels hijack the 11A rateset */ -+ if (mode >= IEEE80211_MODE_MAX) -+ return 1; -+ - rs = &ic->ic_sup_rates[mode]; - for (i = 0; i < maxrates; i++) - rs->rs_rates[i] = rt->info[i].dot11Rate; - rs->rs_nrates = maxrates; -+ - return 1; - } - -@@ -10531,13 +10533,18 @@ ath_setcurmode(struct ath_softc *sc, enu - { 0, 500, 130 }, - }; - const HAL_RATE_TABLE *rt; -- unsigned int i, j; -+ unsigned int i, j, f; - -+ /* -+ * NB: Fix up rixmap. HAL returns half or quarter dot11Rates, -+ * while the stack deals with full rates only -+ */ -+ f = rate_factor(mode); - memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap)); - rt = sc->sc_rates[mode]; - KASSERT(rt != NULL, ("no h/w rate set for phy mode %u", mode)); - for (i = 0; i < rt->rateCount; i++) -- sc->sc_rixmap[rt->info[i].dot11Rate & IEEE80211_RATE_VAL] = i; -+ sc->sc_rixmap[rate_hal2ieee(rt->info[i].dot11Rate, f) & IEEE80211_RATE_VAL] = i; - memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap)); - for (i = 0; i < 32; i++) { - u_int8_t ix = rt->rateCodeToIndex[i]; -@@ -10547,7 +10554,7 @@ ath_setcurmode(struct ath_softc *sc, enu - continue; - } - sc->sc_hwmap[i].ieeerate = -- rt->info[ix].dot11Rate & IEEE80211_RATE_VAL; -+ rate_hal2ieee(rt->info[ix].dot11Rate, f) & IEEE80211_RATE_VAL; - if (rt->info[ix].shortPreamble || - rt->info[ix].phy == IEEE80211_T_OFDM) - sc->sc_hwmap[i].flags |= IEEE80211_RADIOTAP_F_SHORTPRE; -@@ -10948,9 +10955,106 @@ enum { - ATH_MAXVAPS = 26, - ATH_INTMIT = 27, - ATH_NOISE_IMMUNITY = 28, -- ATH_OFDM_WEAK_DET = 29 -+ ATH_OFDM_WEAK_DET = 29, -+ ATH_CHANBW = 30, -+ ATH_OUTDOOR = 31, - }; - -+/* -+ * perform the channel related sysctl, reload the channel list -+ * and try to stay on the current frequency -+ */ -+static int ath_sysctl_setchanparam(struct ath_softc *sc, unsigned long ctl, u_int val) -+{ -+ struct ieee80211com *ic = &sc->sc_ic; -+ struct ath_hal *ah = sc->sc_ah; -+ struct ieee80211_channel *c = NULL; -+ struct ieee80211vap *vap; -+ u_int16_t freq = 0; -+ struct ifreq ifr; -+ -+ if (ic->ic_curchan != IEEE80211_CHAN_ANYC) -+ freq = ic->ic_curchan->ic_freq; -+ -+ switch(ctl) { -+ case ATH_COUNTRYCODE: -+ ic->ic_country_code = val; -+ break; -+ case ATH_OUTDOOR: -+ ic->ic_country_outdoor = val; -+ break; -+ case ATH_CHANBW: -+ switch(val) { -+ case 0: -+ case 5: -+ case 10: -+ case 20: -+ case 40: -+ if (ath_hal_setcapability(ah, HAL_CAP_CHANBW, 1, val, NULL) == AH_TRUE) { -+ sc->sc_chanbw = val; -+ break; -+ } -+ default: -+ return -EINVAL; -+ } -+ break; -+ } -+ -+ if (ic->ic_curchan != IEEE80211_CHAN_ANYC) -+ freq = ic->ic_curchan->ic_freq; -+ -+ /* clear out any old state */ -+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { -+ vap->iv_des_mode = IEEE80211_MODE_AUTO; -+ vap->iv_des_chan = IEEE80211_CHAN_ANYC; -+ } -+ ieee80211_scan_flush(ic); -+ -+ IEEE80211_LOCK_IRQ(ic); -+ ath_getchannels(sc->sc_dev); -+ ieee80211_update_channels(ic, 0); -+ if (freq) -+ c = ieee80211_find_channel(ic, freq, IEEE80211_MODE_AUTO); -+ if (!c) -+ c = &ic->ic_channels[0]; -+ ic->ic_curchan = c; -+ ic->ic_bsschan = c; -+ ic->ic_curmode = IEEE80211_MODE_AUTO; -+ IEEE80211_UNLOCK_IRQ(ic); -+ -+ if (!(sc->sc_dev->flags & IFF_RUNNING)) { -+ ic->ic_bsschan = IEEE80211_CHAN_ANYC; -+ return 0; -+ } -+ -+#ifndef ifr_media -+#define ifr_media ifr_ifru.ifru_ivalue -+#endif -+ memset(&ifr, 0, sizeof(ifr)); -+ ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media & ~IFM_MMASK; -+ ifr.ifr_media |= IFM_MAKEMODE(IEEE80211_MODE_AUTO); -+ ifmedia_ioctl(ic->ic_dev, &ifr, &ic->ic_media, SIOCSIFMEDIA); -+ -+ /* apply the channel to the hw */ -+ ath_set_channel(ic); -+ -+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { -+ struct net_device *dev = vap->iv_dev; -+ -+ /* reactivate all active vaps */ -+ vap->iv_state = IEEE80211_S_SCAN; -+ if ((vap->iv_opmode == IEEE80211_M_HOSTAP) || -+ (vap->iv_opmode == IEEE80211_M_MONITOR) || -+ (vap->iv_opmode == IEEE80211_M_WDS)) -+ ieee80211_new_state(vap, IEEE80211_S_RUN, 0); -+ else -+ ieee80211_new_state(vap, IEEE80211_S_INIT, -1); -+ } -+ -+ return 0; -+} -+ -+ - static int - ath_sysctl_set_intmit(struct ath_softc *sc, long ctl, u_int val) - { -@@ -11029,6 +11133,7 @@ static int - ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos) - { - struct ath_softc *sc = ctl->extra1; -+ struct ieee80211com *ic = &sc->sc_ic; - struct ath_hal *ah = sc->sc_ah; - u_int val; - u_int tab_3_val[3]; -@@ -11052,25 +11157,34 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl - lenp, ppos); - if (ret == 0) { - switch ((long)ctl->extra2) { -+ case ATH_REGDOMAIN: -+ ath_hal_setregdomain(ah, val); -+ break; -+ case ATH_OUTDOOR: -+ case ATH_COUNTRYCODE: -+ case ATH_CHANBW: -+ ret = ath_sysctl_setchanparam(sc, (long) ctl->extra2, val); -+ break; - case ATH_SLOTTIME: -- if (val > 0) { -- if (!ath_hal_setslottime(ah, val)) -- ret = -EINVAL; -- else -- sc->sc_slottimeconf = val; -- } else { -- /* disable manual override */ -+ if (val > 0) -+ sc->sc_slottimeconf = val; -+ else - sc->sc_slottimeconf = 0; -- ath_setslottime(sc); -- } -+ ath_settiming(sc); - break; - case ATH_ACKTIMEOUT: -- if (!ath_hal_setacktimeout(ah, val)) -- ret = -EINVAL; -+ if (val > 0) -+ sc->sc_acktimeconf = val; -+ else -+ sc->sc_acktimeconf = 0; -+ ath_settiming(sc); - break; - case ATH_CTSTIMEOUT: -- if (!ath_hal_setctstimeout(ah, val)) -- ret = -EINVAL; -+ if (val > 0) -+ sc->sc_ctstimeconf = val; -+ else -+ sc->sc_ctstimeconf = 0; -+ ath_settiming(sc); - break; - case ATH_SOFTLED: - if (val != sc->sc_softled) { -@@ -11223,6 +11337,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl - } - } else { - switch ((long)ctl->extra2) { -+ case ATH_CHANBW: -+ val = sc->sc_chanbw ?: 20; -+ break; - case ATH_SLOTTIME: - val = ath_hal_getslottime(ah); - break; -@@ -11241,6 +11358,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl - case ATH_COUNTRYCODE: - ath_hal_getcountrycode(ah, &val); - break; -+ case ATH_OUTDOOR: -+ val = ic->ic_country_outdoor; -+ break; - case ATH_MAXVAPS: - val = ath_maxvaps; - break; -@@ -11354,11 +11474,17 @@ static const ctl_table ath_sysctl_templa - }, - { .ctl_name = CTL_AUTO, - .procname = "countrycode", -- .mode = 0444, -+ .mode = 0644, - .proc_handler = ath_sysctl_halparam, - .extra2 = (void *)ATH_COUNTRYCODE, - }, - { .ctl_name = CTL_AUTO, -+ .procname = "outdoor", -+ .mode = 0644, -+ .proc_handler = ath_sysctl_halparam, -+ .extra2 = (void *)ATH_OUTDOOR, -+ }, -+ { .ctl_name = CTL_AUTO, - .procname = "maxvaps", - .mode = 0444, - .proc_handler = ath_sysctl_halparam, -@@ -11366,7 +11492,7 @@ static const ctl_table ath_sysctl_templa - }, - { .ctl_name = CTL_AUTO, - .procname = "regdomain", -- .mode = 0444, -+ .mode = 0644, - .proc_handler = ath_sysctl_halparam, - .extra2 = (void *)ATH_REGDOMAIN, - }, -@@ -11429,6 +11555,12 @@ static const ctl_table ath_sysctl_templa - .extra2 = (void *)ATH_ACKRATE, - }, - { .ctl_name = CTL_AUTO, -+ .procname = "channelbw", -+ .mode = 0644, -+ .proc_handler = ath_sysctl_halparam, -+ .extra2 = (void *)ATH_CHANBW, -+ }, -+ { .ctl_name = CTL_AUTO, - .procname = "rp", - .mode = 0200, - .proc_handler = ath_sysctl_halparam, -@@ -11669,13 +11801,6 @@ static ctl_table ath_static_sysctls[] = - }, - #endif - { .ctl_name = CTL_AUTO, -- .procname = "countrycode", -- .mode = 0444, -- .data = &ath_countrycode, -- .maxlen = sizeof(ath_countrycode), -- .proc_handler = proc_dointvec -- }, -- { .ctl_name = CTL_AUTO, - .procname = "maxvaps", - .mode = 0444, - .data = &ath_maxvaps, -@@ -11683,13 +11808,6 @@ static ctl_table ath_static_sysctls[] = - .proc_handler = proc_dointvec - }, - { .ctl_name = CTL_AUTO, -- .procname = "outdoor", -- .mode = 0444, -- .data = &ath_outdoor, -- .maxlen = sizeof(ath_outdoor), -- .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 -@@ -688,17 +688,18 @@ struct ath_softc { - int8_t sc_ofdm_weak_det; /* OFDM weak frames detection, -1 == auto */ - - /* rate tables */ -- const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX]; -+#define ATH_MODE_HALF (IEEE80211_MODE_MAX) -+#define ATH_MODE_QUARTER (IEEE80211_MODE_MAX + 1) -+ const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX + 2]; - const HAL_RATE_TABLE *sc_currates; /* current rate table */ - const HAL_RATE_TABLE *sc_xr_rates; /* XR rate table */ -- const HAL_RATE_TABLE *sc_half_rates; /* half rate table */ -- const HAL_RATE_TABLE *sc_quarter_rates; /* quarter rate table */ - HAL_OPMODE sc_opmode; /* current hal operating mode */ - enum ieee80211_phymode sc_curmode; /* current phy mode */ - u_int sc_poweroffset; /* hardware power offset */ - u_int16_t sc_curtxpow; /* current tx power limit */ - u_int16_t sc_curaid; /* current association id */ - HAL_CHANNEL sc_curchan; /* current h/w channel */ -+ u_int8_t sc_chanbw; /* channel bandwidth */ - u_int8_t sc_curbssid[IEEE80211_ADDR_LEN]; - u_int8_t sc_rixmap[256]; /* IEEE to h/w rate table ix */ - struct { -@@ -809,6 +810,8 @@ struct ath_softc { - u_int32_t sc_dturbo_bw_turbo; /* bandwidth threshold */ - #endif - u_int sc_slottimeconf; /* manual override for slottime */ -+ u_int sc_acktimeconf; /* manual override for acktime */ -+ u_int sc_ctstimeconf; /* manual override for ctstime */ - - struct timer_list sc_dfs_excl_timer; /* mark expiration timer task */ - struct timer_list sc_dfs_cac_timer; /* dfs wait timer */ -@@ -827,6 +830,7 @@ struct ath_softc { - int sc_rp_num; - int sc_rp_min; - HAL_BOOL (*sc_rp_analyse)(struct ath_softc *sc); -+ struct ATH_TQ_STRUCT sc_refresh_tq; - struct ATH_TQ_STRUCT sc_rp_tq; - - int sc_rp_ignored; /* if set, we ignored all -@@ -942,6 +946,48 @@ int ar_device(int devid); - DEV_NAME(_v->iv_ic->ic_dev)) - - void ath_radar_detected(struct ath_softc *sc, const char* message); -+static inline u_int getTimingOffset(struct ath_softc *sc) -+{ -+ struct ieee80211com *ic = &sc->sc_ic; -+ u_int usec = 9; -+ if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) { -+ usec = 20; -+ if (ic->ic_flags & IEEE80211_F_SHSLOT) -+ usec = 9; -+ } else if (IEEE80211_IS_CHAN_A(ic->ic_curchan)) -+ usec = 9; -+ -+ if (IEEE80211_IS_CHAN_TURBO(ic->ic_curchan)) -+ usec = 6; -+ -+ if (IEEE80211_IS_CHAN_HALF(ic->ic_curchan)) -+ usec = 13; -+ else if (IEEE80211_IS_CHAN_QUARTER(ic->ic_curchan)) -+ usec = 21; -+ return usec; -+} -+ -+static inline void ath_get_timings(struct ath_softc *sc, u_int *t_slot, u_int *t_sifs, u_int *t_difs) -+{ -+ struct ieee80211_channel *c = sc->sc_ic.ic_curchan; -+ -+ *t_slot = getTimingOffset(sc) + sc->sc_slottimeconf; -+ -+ if (IEEE80211_IS_CHAN_HALF(c)) { -+ *t_sifs = 32; -+ *t_difs = 56; -+ } else if (IEEE80211_IS_CHAN_QUARTER(c)) { -+ *t_sifs = 64; -+ *t_difs = 112; -+ } else if (IEEE80211_IS_CHAN_TURBO(c)) { -+ *t_sifs = 8; -+ *t_difs = 28; -+ } else { -+ *t_sifs = 16; -+ *t_difs = 28; -+ } -+} -+ - - struct ath_hw_detect { - const char *vendor_name; ---- a/tools/athctrl.c -+++ b/tools/athctrl.c -@@ -118,7 +118,7 @@ CMD(athctrl)(int argc, char *argv[]) - } - - if (distance >= 0) { -- int slottime = 9 + (distance / 300) + ((distance % 300) ? 1 : 0); -+ int slottime = (distance / 300) + ((distance % 300) ? 1 : 0); - int acktimeout = slottime * 2 + 3; - int ctstimeout = slottime * 2 + 3; - ---- a/net80211/ieee80211.c -+++ b/net80211/ieee80211.c -@@ -243,34 +243,17 @@ static const struct country_code_to_str - {CTRY_ZIMBABWE, "ZW"} - }; - --int --ieee80211_ifattach(struct ieee80211com *ic) -+void ieee80211_update_channels(struct ieee80211com *ic, int init) - { -- struct net_device *dev = ic->ic_dev; - struct ieee80211_channel *c; -+ struct ieee80211vap *vap; - struct ifmediareq imr; -+ int ext = 0; - int i; - -- _MOD_INC_USE(THIS_MODULE, return -ENODEV); -- -- /* -- * Pick an initial operating mode until we have a vap -- * created to lock it down correctly. This is only -- * drivers have something defined for configuring the -- * hardware at startup. -- */ -- ic->ic_opmode = IEEE80211_M_STA; /* everyone supports this */ -- -- /* -- * Fill in 802.11 available channel set, mark -- * all available channels as active, and pick -- * a default channel if not already specified. -- */ -- KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX, -- ("invalid number of channels specified: %u", ic->ic_nchans)); - memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail)); -- ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO; - ic->ic_max_txpower = IEEE80211_TXPOWER_MIN; -+ ic->ic_modecaps = 1 << IEEE80211_MODE_AUTO; - - for (i = 0; i < ic->ic_nchans; i++) { - c = &ic->ic_channels[i]; -@@ -298,6 +281,8 @@ ieee80211_ifattach(struct ieee80211com * - ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_A; - if (IEEE80211_IS_CHAN_108G(c)) - ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_G; -+ if (IEEE80211_IS_CHAN_HALF(c) || IEEE80211_IS_CHAN_QUARTER(c)) -+ ext = 1; - } - /* Initialize candidate channels to all available */ - memcpy(ic->ic_chan_active, ic->ic_chan_avail, -@@ -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. - */ -- if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G)) -+ if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11G)) && !ext) - ieee80211_set11gbasicrates( - &ic->ic_sup_rates[IEEE80211_MODE_11G], - IEEE80211_MODE_11G); - -+ 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); -+ -+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { -+ struct ieee80211vap *avp; -+ TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) { -+ (void) ieee80211_media_setup(ic, &vap->iv_media, vap->iv_caps, NULL, NULL); -+ ieee80211_media_status(vap->iv_dev, &imr); -+ ifmedia_set(&vap->iv_media, imr.ifm_active); -+ } -+ (void) ieee80211_media_setup(ic, &vap->iv_media, vap->iv_caps, NULL, NULL); -+ ieee80211_media_status(vap->iv_dev, &imr); -+ ifmedia_set(&vap->iv_media, imr.ifm_active); -+ } -+} -+EXPORT_SYMBOL(ieee80211_update_channels); -+ -+int -+ieee80211_ifattach(struct ieee80211com *ic) -+{ -+ struct net_device *dev = ic->ic_dev; -+ struct ieee80211_channel *c; -+ struct ifmediareq imr; -+ -+ _MOD_INC_USE(THIS_MODULE, return -ENODEV); -+ -+ /* -+ * Pick an initial operating mode until we have a vap -+ * created to lock it down correctly. This is only -+ * drivers have something defined for configuring the -+ * hardware at startup. -+ */ -+ ic->ic_opmode = IEEE80211_M_STA; /* everyone supports this */ -+ -+ /* -+ * Fill in 802.11 available channel set, mark -+ * all available channels as active, and pick -+ * a default channel if not already specified. -+ */ -+ KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX, -+ ("invalid number of channels specified: %u", ic->ic_nchans)); -+ ieee80211_update_channels(ic, 1); -+ - /* Setup initial channel settings */ - ic->ic_bsschan = IEEE80211_CHAN_ANYC; - /* Arbitrarily pick the first channel */ -@@ -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; -+ - (void) ieee80211_setmode(ic, ic->ic_curmode); - - /* Store default beacon interval, as nec. */ -@@ -763,7 +797,8 @@ ieee80211_media_setup(struct ieee80211co - struct ieee80211_rateset allrates; - - /* Fill in media characteristics. */ -- ifmedia_init(media, 0, media_change, media_stat); -+ if (media_change || media_stat) -+ ifmedia_init(media, 0, media_change, media_stat); - maxrate = 0; - memset(&allrates, 0, sizeof(allrates)); - -@@ -793,7 +828,7 @@ ieee80211_media_setup(struct ieee80211co - ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_WDS); - if (mode == IEEE80211_MODE_AUTO) - continue; -- rs = &ic->ic_sup_rates[mode]; -+ rs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]; - - for (i = 0; i < rs->rs_nrates; i++) { - rate = rs->rs_rates[i]; -@@ -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]); -- rs = &ic->ic_sup_rates[mode]; -+ rs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]; - for (i = 0; i < rs->rs_nrates; i++) { - rate = rs->rs_rates[i]; - mword = ieee80211_rate2media(ic, rate, mode); -@@ -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")); -- vap->iv_bss->ni_rates = ic->ic_sup_rates[newphymode]; -+ vap->iv_bss->ni_rates = ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, newphymode)]; - } - error = -ENETRESET; - } -@@ -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) -- int i, nrates = ic->ic_sup_rates[mode].rs_nrates; -+ int i, nrates = ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)].rs_nrates; - for (i = 0; i < nrates; i++) - if (IEEERATE(ic, mode, i) == rate) - return i; -@@ -1877,11 +1912,6 @@ ieee80211_build_countryie(struct ieee802 - if (ieee80211_chan2mode(c) != curmode_noturbo) - continue; - -- /* Skip half/quarter rate channels */ -- if (IEEE80211_IS_CHAN_HALF(c) || -- IEEE80211_IS_CHAN_QUARTER(c)) -- continue; -- - if (*cur_runlen == 0) { - (*cur_runlen)++; - *cur_pow = c->ic_maxregpower; -@@ -1915,7 +1945,7 @@ void - ieee80211_build_sc_ie(struct ieee80211com *ic) - { - struct ieee80211_ie_sc *ie = &ic->ic_sc_ie; -- int i, j; -+ int i, j, k; - struct ieee80211_channel *c; - u_int8_t prevchan; - ---- a/net80211/ieee80211_var.h -+++ b/net80211/ieee80211_var.h -@@ -336,8 +336,6 @@ struct ieee80211com { - u_int8_t ic_nopened; /* VAPs been opened */ - struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX]; - struct ieee80211_rateset ic_sup_xr_rates; -- struct ieee80211_rateset ic_sup_half_rates; -- struct ieee80211_rateset ic_sup_quarter_rates; - u_int16_t ic_modecaps; /* set of mode capabilities */ - u_int16_t ic_curmode; /* current mode */ - u_int16_t ic_lintval; /* beacon interval */ -@@ -714,6 +712,7 @@ MALLOC_DECLARE(M_80211_VAP); - - int ieee80211_ifattach(struct ieee80211com *); - void ieee80211_ifdetach(struct ieee80211com *); -+void ieee80211_update_channels(struct ieee80211com *ic, int); - int ieee80211_vap_setup(struct ieee80211com *, struct net_device *, - const char *, int, int, struct ieee80211vap *); - int ieee80211_vap_attach(struct ieee80211vap *, ifm_change_cb_t, ifm_stat_cb_t); -@@ -793,6 +792,23 @@ ieee80211_anyhdrspace(struct ieee80211co - return size; - } - -+static __inline int -+ieee80211_chan2ratemode(struct ieee80211_channel *c, int mode) -+{ -+ if (mode == -1) -+ mode = ieee80211_chan2mode(c); -+ -+ /* -+ * Use 11a rateset for half/quarter to restrict things -+ * to pure OFDM -+ */ -+ if (IEEE80211_IS_CHAN_HALF(c) || -+ IEEE80211_IS_CHAN_QUARTER(c)) -+ return IEEE80211_MODE_11A; -+ -+ return mode; -+} -+ - /* Macros to print MAC address used in 802.11 headers */ - - #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" ---- a/net80211/ieee80211_node.c -+++ b/net80211/ieee80211_node.c -@@ -287,7 +287,7 @@ ieee80211_node_set_chan(struct ieee80211 - ni->ni_rates = ic->ic_sup_xr_rates; - else - #endif -- ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(chan)]; -+ ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2ratemode(chan, -1)]; - } - - static __inline void -@@ -387,6 +387,8 @@ ieee80211_create_ibss(struct ieee80211va - ic->ic_bsschan = chan; - ieee80211_node_set_chan(ic, ni); - ic->ic_curmode = ieee80211_chan2mode(chan); -+ ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2ratemode(chan, -1)]; -+ - spin_lock_irqsave(&channel_lock, flags); - ieee80211_scan_set_bss_channel(ic, ic->ic_bsschan); - spin_unlock_irqrestore(&channel_lock, flags); -@@ -394,14 +396,8 @@ ieee80211_create_ibss(struct ieee80211va - /* Update country ie information */ - ieee80211_build_countryie(ic); - -- if (IEEE80211_IS_CHAN_HALF(chan)) { -- ni->ni_rates = ic->ic_sup_half_rates; -- } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { -- ni->ni_rates = ic->ic_sup_quarter_rates; -- } -- -- if ((vap->iv_flags & IEEE80211_F_PUREG) && -- IEEE80211_IS_CHAN_ANYG(chan)) { -+ if ((ieee80211_chan2ratemode(chan, -1) != IEEE80211_MODE_11A) && -+ IEEE80211_IS_CHAN_ANYG(chan) && (vap->iv_flags & IEEE80211_F_PUREG)) { - ieee80211_setpuregbasicrates(&ni->ni_rates); - } - ---- a/net80211/ieee80211_scan_sta.c -+++ b/net80211/ieee80211_scan_sta.c -@@ -490,12 +490,7 @@ check_rate(struct ieee80211vap *vap, con - - okrate = badrate = fixedrate = 0; - -- if (IEEE80211_IS_CHAN_HALF(se->se_chan)) -- srs = &ic->ic_sup_half_rates; -- else if (IEEE80211_IS_CHAN_QUARTER(se->se_chan)) -- srs = &ic->ic_sup_quarter_rates; -- else -- srs = &ic->ic_sup_rates[ieee80211_chan2mode(se->se_chan)]; -+ srs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, -1)]; - nrs = se->se_rates[1]; - rs = se->se_rates + 2; - fixedrate = IEEE80211_FIXED_RATE_NONE; ---- a/net80211/ieee80211_output.c -+++ b/net80211/ieee80211_output.c -@@ -1676,8 +1676,8 @@ ieee80211_send_probereq(struct ieee80211 - - frm = ieee80211_add_ssid(frm, ssid, ssidlen); - mode = ieee80211_chan2mode(ic->ic_curchan); -- frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]); -- frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]); -+ frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]); -+ frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, mode)]); - - if (optie != NULL) { - memcpy(frm, optie, optielen); ---- a/net80211/ieee80211_proto.c -+++ b/net80211/ieee80211_proto.c -@@ -404,7 +404,7 @@ ieee80211_fix_rate(struct ieee80211_node - - error = 0; - okrate = badrate = fixedrate = 0; -- srs = &ic->ic_sup_rates[ieee80211_chan2mode(ni->ni_chan)]; -+ srs = &ic->ic_sup_rates[ieee80211_chan2ratemode(ic->ic_curchan, -1)]; - nrs = &ni->ni_rates; - fixedrate = IEEE80211_FIXED_RATE_NONE; - for (i = 0; i < nrs->rs_nrates;) { -@@ -1407,6 +1407,7 @@ ieee80211_new_state(struct ieee80211vap - IEEE80211_VAPS_UNLOCK_IRQ(ic); - return rc; - } -+EXPORT_SYMBOL(ieee80211_new_state); - - static int - __ieee80211_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) ---- a/ath_rate/minstrel/minstrel.c -+++ b/ath_rate/minstrel/minstrel.c -@@ -195,31 +195,7 @@ calc_usecs_unicast_packet(struct ath_sof - return 0; - } - -- /* XXX: Getting MAC/PHY level timings should be fixed for turbo -- * rates, and there is probably a way to get this from the -- * HAL... */ -- switch (rt->info[rix].phy) { -- case IEEE80211_T_OFDM: --#if 0 -- t_slot = 9; -- t_sifs = 16; -- t_difs = 28; -- /* fall through */ --#endif -- case IEEE80211_T_TURBO: -- t_slot = 9; -- t_sifs = 8; -- t_difs = 28; -- break; -- case IEEE80211_T_DS: -- /* Fall through to default */ -- default: -- /* pg. 205 ieee.802.11.pdf */ -- t_slot = 20; -- t_difs = 50; -- t_sifs = 10; -- } -- -+ ath_get_timings(sc, &t_slot, &t_sifs, &t_difs); - if ((ic->ic_flags & IEEE80211_F_USEPROT) && - (rt->info[rix].phy == IEEE80211_T_OFDM)) { - if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) ---- a/ath_rate/sample/sample.c -+++ b/ath_rate/sample/sample.c -@@ -172,26 +172,7 @@ calc_usecs_unicast_packet(struct ath_sof - * rates, and there is probably a way to get this from the - * hal... - */ -- switch (rt->info[rix].phy) { -- case IEEE80211_T_OFDM: -- t_slot = 9; -- t_sifs = 16; -- t_difs = 28; -- /* fall through */ -- case IEEE80211_T_TURBO: -- t_slot = 9; -- t_sifs = 8; -- t_difs = 28; -- break; -- case IEEE80211_T_DS: -- /* fall through to default */ -- default: -- /* pg 205 ieee.802.11.pdf */ -- t_slot = 20; -- t_difs = 50; -- t_sifs = 10; -- } -- -+ ath_get_timings(sc, &t_slot, &t_sifs, &t_difs); - rts = cts = 0; - - if ((ic->ic_flags & IEEE80211_F_USEPROT) && ---- a/net80211/ieee80211_wireless.c -+++ b/net80211/ieee80211_wireless.c -@@ -2142,7 +2142,7 @@ ieee80211_ioctl_setmode(struct net_devic - - vap->iv_des_mode = mode; - if (IS_UP_AUTO(vap)) -- ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); -+ ieee80211_init(vap->iv_dev, 0); - - retv = 0; - } -@@ -4090,46 +4090,60 @@ ieee80211_ioctl_getchanlist(struct net_d - return 0; - } - -+static int alreadyListed(struct ieee80211req_chaninfo *chans, u_int16_t mhz) -+{ -+ int i; -+ for (i = 0; i < chans->ic_nchans; i++) { -+ if (chans->ic_chans[i].ic_freq == mhz) -+ return 1; -+ } -+ return 0; -+} -+ - static int - ieee80211_ioctl_getchaninfo(struct net_device *dev, -- struct iw_request_info *info, void *w, char *extra) -+ struct iw_request_info *info, void *w, char *extra) - { - struct ieee80211vap *vap = dev->priv; - struct ieee80211com *ic = vap->iv_ic; -- struct ieee80211req_chaninfo chans; -+ struct ieee80211req_chaninfo *chans = -+ (struct ieee80211req_chaninfo *)extra; -+ - u_int8_t reported[IEEE80211_CHAN_BYTES]; /* XXX stack usage? */ - int i; - -- memset(&chans, 0, sizeof(chans)); -- memset(&reported, 0, sizeof(reported)); -+ memset(chans, 0, sizeof(*chans)); -+ memset(reported, 0, sizeof(reported)); - for (i = 0; i < ic->ic_nchans; i++) { - const struct ieee80211_channel *c = &ic->ic_channels[i]; - const struct ieee80211_channel *c1 = c; - -- if (isclr(reported, c->ic_ieee)) { -+ if (!alreadyListed(chans, c->ic_freq)) { - setbit(reported, c->ic_ieee); - -- /* pick turbo channel over non-turbo channel, and -- * 11g channel over 11b channel */ - if (IEEE80211_IS_CHAN_A(c)) -- c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_A); -+ c1 = findchannel(ic, c->ic_freq, -+ IEEE80211_MODE_TURBO_A); - if (IEEE80211_IS_CHAN_ANYG(c)) -- c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G); -+ c1 = findchannel(ic, c->ic_freq, -+ IEEE80211_MODE_TURBO_G); - else if (IEEE80211_IS_CHAN_B(c)) { -- c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_TURBO_G); -+ c1 = findchannel(ic, c->ic_freq, -+ IEEE80211_MODE_TURBO_G); - if (!c1) -- c1 = findchannel(ic, c->ic_ieee, IEEE80211_MODE_11G); -+ c1 = findchannel(ic, c->ic_freq, -+ IEEE80211_MODE_11G); - } - - if (c1) - c = c1; -- /* Copy the entire structure, whereas it used to just copy a few fields */ -- memcpy(&chans.ic_chans[chans.ic_nchans], c, sizeof(struct ieee80211_channel)); -- if (++chans.ic_nchans >= IEEE80211_CHAN_MAX) -+ chans->ic_chans[chans->ic_nchans].ic_ieee = c->ic_ieee; -+ chans->ic_chans[chans->ic_nchans].ic_freq = c->ic_freq; -+ chans->ic_chans[chans->ic_nchans].ic_flags = c->ic_flags; -+ if (++chans->ic_nchans >= IEEE80211_CHAN_MAX) - break; - } - } -- memcpy(extra, &chans, sizeof(struct ieee80211req_chaninfo)); - return 0; - } - ---- a/net80211/ieee80211_scan_ap.c -+++ b/net80211/ieee80211_scan_ap.c -@@ -512,12 +512,13 @@ pick_channel(struct ieee80211_scan_state - int ss_last = ss->ss_last; - struct ieee80211_channel *best; - struct ap_state *as = ss->ss_priv; -- struct channel chans[ss_last]; /* actually ss_last-1 is required */ -+ struct channel *chans; /* actually ss_last-1 is required */ - struct channel *c = NULL; - struct pc_params params = { vap, ss, flags }; - int benefit = 0; - int sta_assoc = 0; - -+ chans = (struct channel *)kmalloc(ss_last*sizeof(struct channel),GFP_ATOMIC); - for (i = 0; i < ss_last; i++) { - chans[i].chan = ss->ss_chans[i]; - chans[i].orig = i; -@@ -571,6 +572,7 @@ pick_channel(struct ieee80211_scan_state - "%s: best: channel %u rssi %d\n", - __func__, i, as->as_maxrssi[i]); - } -+ kfree(chans); - return best; - } - -@@ -609,6 +611,7 @@ ap_end(struct ieee80211_scan_state *ss, - res = 1; /* Do NOT restart scan */ - } else { - struct ieee80211_scan_entry se; -+ int i; - /* XXX: notify all VAPs? */ - /* if this is a dynamic turbo frequency , start with normal - * mode first */ -@@ -623,6 +626,11 @@ ap_end(struct ieee80211_scan_state *ss, - return 0; - } - } -+ for (i = (bestchan - &ic->ic_channels[0])/sizeof(*bestchan) + 1; i < ic->ic_nchans; i++) { -+ if ((ic->ic_channels[i].ic_freq == bestchan->ic_freq) && -+ IEEE80211_IS_CHAN_ANYG(&ic->ic_channels[i])) -+ bestchan = &ic->ic_channels[i]; -+ } - memset(&se, 0, sizeof(se)); - se.se_chan = bestchan; - ---- a/tools/wlanconfig.c -+++ b/tools/wlanconfig.c -@@ -737,7 +737,7 @@ list_channels(const char *ifname, int al - if (get80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO, &chans, sizeof(chans)) < 0) - errx(1, "unable to get channel information"); - if (!allchans) { -- uint8_t active[32]; -+ uint8_t active[IEEE80211_CHAN_BYTES]; - - if (get80211priv(ifname, IEEE80211_IOCTL_GETCHANLIST, &active, sizeof(active)) < 0) - errx(1, "unable to get active channel list"); ---- a/net80211/ieee80211_scan.c -+++ b/net80211/ieee80211_scan.c -@@ -1044,6 +1044,7 @@ ieee80211_scan_assoc_fail(struct ieee802 - ss->ss_ops->scan_assoc_fail(ss, mac, reason); - } - } -+EXPORT_SYMBOL(ieee80211_scan_flush); - - /* - * Iterate over the contents of the scan cache. ---- a/ath/if_ath_hal_wrappers.h -+++ b/ath/if_ath_hal_wrappers.h -@@ -111,6 +111,11 @@ static inline HAL_BOOL ath_hal_getregdom - return (ath_hal_getcapability(ah, HAL_CAP_REG_DMN, 0, destination) == HAL_OK); - } - -+static inline HAL_BOOL ath_hal_setregdomain(struct ath_hal *ah, u_int32_t v) -+{ -+ return (ath_hal_setcapability(ah, HAL_CAP_REG_DMN, 0, v, NULL)); -+} -+ - static inline HAL_BOOL ath_hal_gettkipmic(struct ath_hal *ah) - { - return (ath_hal_getcapability(ah, HAL_CAP_TKIP_MIC, 1, NULL) == HAL_OK);