1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-25 06:05:20 +02:00
openwrt-xburst/package/madwifi/patches/421-channel_handling.patch
nbd a2c8edeafc madwifi: fix various noderef/memleak issues
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18052 3c298f89-4303-0410-b956-a3cf2f4a3e73
2009-10-17 04:56:05 +00:00

1352 lines
42 KiB
Diff

--- 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);