move a few unmaintained packages from trunk to /packages
[openwrt/svn-archive/archive.git] / package / madwifi / patches / 421-channel_handling.patch
diff --git a/package/madwifi/patches/421-channel_handling.patch b/package/madwifi/patches/421-channel_handling.patch
deleted file mode 100644 (file)
index 2a8ec27..0000000
+++ /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 <linux/moduleparam.h>
- 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);