help
Enables Atheros Super A/G Hardware Compression Engine.
-choice
- prompt "Madwifi version"
+config MADWIFI_SINGLE_MODULE
+ bool "Combine driver and net80211 into a single module"
depends on PACKAGE_kmod-madwifi
- default MADWIFI_STABLE
+ default y
help
- This option allows you to select the version of MadWifi to be built.
-
-config MADWIFI_STABLE
- bool "Use the OpenWrt stable version of madwifi"
-
-endchoice
+ This option combines all driver and stack related code (except for HAL)
+ into a single module, thus saving space and removing unnecessary kernel
+ exports
choice
prompt "Rate control algorithm selection"
always wander in directions where he/she feels he/she will get paid
the best for his/her work.
-config MADWIFI_RCA_ONOE
- bool "Use the Onoe rate control algorithm"
- help
- Onoe is a credit based RCA where the value of the credit is determined
- by the frequency of successful, erroneous and retransmissions
- accumulated during a fixed invocation period of 1000 ms. If less than
- 10% of the packets need to be retransmitted at a particular rate, Onoe
- keeps increasing its credit point till the threshold value of 10 is
- reached. At this point, the current transmission rate is increased to
- the next available higher rate and the process repeated with credit
- score of zero. Similar logic holds for deducting the credit score and
- moving to a lower bit-rate for failed packet
- transmission/retransmission attempts. However, once a bit-rate has
- been marked as failure in the previous attempt, Onoe will not attempt
- to select that bit-rate until 10 seconds have elapsed since the last
- attempt. Due to the manner in which it operates, Onoe is conservative
- in rate selection and is less sensitive to individual packet failure.
-
-config MADWIFI_RCA_AMRR
- bool "Use the AMRR rate control algorithm"
- help
- AMRR uses Binary Exponential Backoff (BEB) technique to adapt the
- length (threshold) of the sampling period used to change the values of
- bit-rate and transmission count parameters. It uses probe packets and
- depending on their transmission status adaptively changes the threshold
- value. The adaptation mechanism ensures fewer failed
- transmission/retransmission and higher throughput by not switching to a
- higher rate as specified by the backoff mechanism. In addition to this,
- the AMRR employs heuristics to capture the short-term variations of the
- channel by judiciously setting the rate and transmission count
- parameters.
-
config MADWIFI_RCA_SAMPLERATE
bool "Use the SampleRate rate control algorithm"
help
PKG_REV:=3314
PKG_VERSION:=r$(PKG_REV)
-PKG_RELEASE:=2.2
+PKG_RELEASE:=2.3
PKG_SOURCE_PROTO:=svn
PKG_SOURCE_VERSION:=$(PKG_REV)
RATE_CONTROL:=sample
endif
+ifneq ($(CONFIG_MADWIFI_SINGLE_MODULE),)
+MADWIFI_FILES:= $(PKG_BUILD_DIR)/ath_hal/ath_hal.$(LINUX_KMOD_SUFFIX)
+else
MADWIFI_FILES:= \
$(PKG_BUILD_DIR)/net80211/wlan.$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/net80211/wlan_scan_ap.$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/net80211/wlan_ccmp.$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/net80211/wlan_tkip.$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/net80211/wlan_wep.$(LINUX_KMOD_SUFFIX) \
- $(PKG_BUILD_DIR)/net80211/wlan_xauth.$(LINUX_KMOD_SUFFIX) \
+ $(PKG_BUILD_DIR)/net80211/wlan_xauth.$(LINUX_KMOD_SUFFIX)
+endif
-MADWIFI_AUTOLOAD:= \
+ifneq ($(CONFIG_MADWIFI_SINGLE_MODULE),)
+ MADWIFI_AUTOLOAD:= ath_hal
+else
+ MADWIFI_AUTOLOAD:= \
wlan \
wlan_scan_ap \
wlan_scan_sta \
wlan_ccmp \
wlan_tkip \
wlan_wep \
- wlan_xauth \
+ wlan_xauth
+endif
ifeq ($(findstring AHB,$(BUS)),AHB)
MADWIFI_FILES+= $(PKG_BUILD_DIR)/ath/ath_ahb.$(LINUX_KMOD_SUFFIX)
TOOLPATH="$(KERNEL_CROSS)" \
KERNELPATH="$(LINUX_DIR)" \
LDOPTS="--no-warn-mismatch " \
- ATH_RATE="ath_rate/$(RATE_CONTROL)" \
+ ATH_RATE="$(RATE_CONTROL)" \
ATH_CAP_SUPERG_COMP="$(COMPRESSION)" \
DO_MULTI=1 \
+ SINGLE_MODULE=$(if $(CONFIG_MADWIFI_SINGLE_MODULE),1) \
INCS="$(MADWIFI_INC)" \
$(if $(CONFIG_MADWIFI_DEBUG),,DEBUG=) WARNINGS="-Wno-unused"
MAKE_VARS:= \
- COPTS="-DCONFIG_ATHEROS_RATE_DEFAULT='\"$(RATE_CONTROL)\"' -DATH_REVERSE_ENGINEERING=1" \
+ COPTS="-DATH_REVERSE_ENGINEERING=1" \
define Build/Prepare/HAL
rm -rf $(PKG_BUILD_DIR)/tmp
IEEE80211_KEYIX_NONE);
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
-@@ -343,8 +343,9 @@ struct ieee80211com {
+@@ -343,8 +343,8 @@ struct ieee80211com {
u_int16_t ic_holdover; /* PM hold over duration */
u_int16_t ic_bmissthreshold; /* beacon miss threshold (# beacons) */
unsigned long ic_bmiss_guard; /* when to cease ignoring bmiss (jiffies) */
- u_int16_t ic_newtxpowlimit; /* tx power limit to change to (in 0.5 dBm) */
+ u_int16_t ic_txpowlimit; /* configured global tx power limit (in 0.5 dBm) */
+ u_int16_t ic_max_txpower; /* global hardware tx power limit */
-+ u_int16_t ic_cur_txpower; /* current tx power */
u_int16_t ic_uapsdmaxtriggers; /* max triggers that could arrive */
u_int8_t ic_coverageclass; /* coverage class */
u_int8_t ic_protmode_rssi; /* rssi threshold for protection mode */
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
-@@ -920,17 +920,23 @@ ieee80211_ioctl_giwrange(struct net_devi
+@@ -908,6 +908,21 @@ ieee80211_ioctl_giwessid(struct net_devi
+ return 0;
+ }
+
++static u16
++ieee80211_get_maxtxpow(struct ieee80211com *ic)
++{
++ u_int16_t txp = IEEE80211_TXPOWER_MAX;
++
++ if (ic->ic_bsschan && (ic->ic_bsschan != IEEE80211_CHAN_ANYC))
++ txp = min(txp, (u16) ic->ic_bsschan->ic_maxpower);
++
++ if (ic->ic_max_txpower > 0)
++ txp = min(txp, ic->ic_max_txpower);
++
++ return txp;
++}
++
++
+ static int
+ ieee80211_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+@@ -920,17 +935,21 @@ ieee80211_ioctl_giwrange(struct net_devi
u_int8_t reported[IEEE80211_CHAN_BYTES]; /* XXX stack usage? */
int i, r;
int step = 0;
data->length = sizeof(struct iw_range);
memset(range, 0, sizeof(struct iw_range));
-+ power = ic->ic_max_txpower;
-+ if (ic->ic_bsschan && (ic->ic_bsschan != IEEE80211_CHAN_ANYC))
-+ power = min(power, (u_int16_t) ic->ic_bsschan->ic_maxpower);
++ power = ieee80211_get_maxtxpow(ic);
+
/* txpower (128 values, but will print out only IW_MAX_TXPOWER) */
- range->num_txpower = (ic->ic_txpowlimit >= 8) ? IW_MAX_TXPOWER : ic->ic_txpowlimit;
- (IW_MAX_TXPOWER - i - 1) * step;
range->txpower_capa = IW_TXPOW_DBM;
-@@ -1379,13 +1385,11 @@ ieee80211_ioctl_siwtxpow(struct net_devi
+@@ -1379,13 +1398,11 @@ ieee80211_ioctl_siwtxpow(struct net_devi
int fixed, disabled;
fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED);
goto done;
}
return 0;
-@@ -1396,30 +1400,12 @@ ieee80211_ioctl_siwtxpow(struct net_devi
+@@ -1396,30 +1413,12 @@ ieee80211_ioctl_siwtxpow(struct net_devi
return -EOPNOTSUPP;
if (rrq->flags != IW_TXPOW_DBM)
return -EINVAL;
ic->ic_flags &= ~IEEE80211_F_TXPOW_FIXED;
}
done:
-@@ -1588,9 +1574,22 @@ ieee80211_ioctl_giwtxpow(struct net_devi
+@@ -1588,9 +1587,18 @@ ieee80211_ioctl_giwtxpow(struct net_devi
{
struct ieee80211vap *vap = dev->priv;
struct ieee80211com *ic = vap->iv_ic;
- rrq->fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) != 0;
+ unsigned int power = ic->ic_txpowlimit;
+ struct ieee80211_channel *c;
-+ u_int16_t txp = ic->ic_max_txpower;
++ u_int16_t txp;
+
-+ if (ic->ic_bsschan && (ic->ic_bsschan != IEEE80211_CHAN_ANYC)) {
-+ txp = min(txp, (u16) ic->ic_bsschan->ic_maxpower);
-+ } else if (ic->ic_cur_txpower > 0) {
-+ txp = min(txp, ic->ic_cur_txpower);
-+ }
++ txp = ieee80211_get_maxtxpow(ic);
+ if (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) {
+ txp = min(txp, ic->ic_txpowlimit);
+ rrq->fixed = 1;
- if (new_clamped_maxtxpower != prev_clamped_maxtxpower)
- ath_hal_settxpowlimit(ah, new_clamped_maxtxpower);
+ ath_set_clamped_maxtxpower(sc, ic->ic_txpowlimit);
-+ ic->ic_cur_txpower = ath_get_clamped_maxtxpower(sc);
++ ic->ic_max_txpower = ath_get_clamped_maxtxpower(sc);
}
#ifdef ATH_SUPERG_XR
/* Don't allow to change to channel with radar found */
if (c->ic_flags & IEEE80211_CHAN_RADAR)
-@@ -4625,7 +4597,13 @@ static void
+@@ -4634,7 +4606,13 @@ static void
pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt) {
struct ieee80211vap *vap = dev->priv;
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node *iv_bss; /* information for this node */
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
-@@ -2862,6 +2862,9 @@ ieee80211_ioctl_setparam(struct net_devi
+@@ -2871,6 +2871,9 @@ ieee80211_ioctl_setparam(struct net_devi
case IEEE80211_PARAM_PROBEREQ:
vap->iv_no_probereq = !value;
break;
#ifdef ATH_REVERSE_ENGINEERING
case IEEE80211_PARAM_DUMPREGS:
ieee80211_dump_registers(dev, info, w, extra);
-@@ -3227,6 +3230,9 @@ ieee80211_ioctl_getparam(struct net_devi
+@@ -3236,6 +3239,9 @@ ieee80211_ioctl_getparam(struct net_devi
case IEEE80211_PARAM_PROBEREQ:
param[0] = !vap->iv_no_probereq;
break;
default:
return -EOPNOTSUPP;
}
-@@ -5801,6 +5807,10 @@ static const struct iw_priv_args ieee802
+@@ -5810,6 +5816,10 @@ static const struct iw_priv_args ieee802
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "probereq"},
{ IEEE80211_PARAM_PROBEREQ,
0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_probereq"},
u_int16_t ic_modecaps; /* set of mode capabilities */
u_int16_t ic_curmode; /* current mode */
u_int16_t ic_lintval; /* beacon interval */
-@@ -715,6 +713,7 @@ MALLOC_DECLARE(M_80211_VAP);
+@@ -714,6 +712,7 @@ MALLOC_DECLARE(M_80211_VAP);
int ieee80211_ifattach(struct ieee80211com *);
void ieee80211_ifdetach(struct ieee80211com *);
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);
-@@ -794,6 +793,23 @@ ieee80211_anyhdrspace(struct ieee80211co
+@@ -793,6 +792,23 @@ ieee80211_anyhdrspace(struct ieee80211co
return size;
}
if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
-@@ -2133,7 +2133,7 @@ ieee80211_ioctl_setmode(struct net_devic
+@@ -2142,7 +2142,7 @@ ieee80211_ioctl_setmode(struct net_devic
vap->iv_des_mode = mode;
if (IS_UP_AUTO(vap))
retv = 0;
}
-@@ -4081,46 +4081,60 @@ ieee80211_ioctl_getchanlist(struct net_d
+@@ -4090,46 +4090,60 @@ ieee80211_ioctl_getchanlist(struct net_d
return 0;
}
ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
-@@ -2736,6 +2736,7 @@ ieee80211_ioctl_setparam(struct net_devi
+@@ -2745,6 +2745,7 @@ ieee80211_ioctl_setparam(struct net_devi
case IEEE80211_PARAM_COVERAGE_CLASS:
if (value <= IEEE80211_COVERAGE_CLASS_MAX) {
ic->ic_coverageclass = value;
if (vap->iv_opmode == IEEE80211_M_WDS)
return -EOPNOTSUPP;
-@@ -884,7 +884,7 @@ static int
+@@ -899,7 +899,7 @@ static int
ieee80211_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info,
struct iw_point *data, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node *ni = vap->iv_bss;
struct iw_range *range = (struct iw_range *) extra;
-@@ -1034,7 +1034,7 @@ ieee80211_ioctl_setspy(struct net_device
+@@ -1047,7 +1047,7 @@ ieee80211_ioctl_setspy(struct net_device
struct iw_point *data, char *extra)
{
/* save the list of node addresses */
struct sockaddr address[IW_MAX_SPY];
unsigned int number = data->length;
int i;
-@@ -1072,7 +1072,7 @@ ieee80211_ioctl_getspy(struct net_device
+@@ -1085,7 +1085,7 @@ ieee80211_ioctl_getspy(struct net_device
* locate nodes by mac (ieee80211_find_node()),
* copy out rssi, set updated flag appropriately
*/
struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
struct ieee80211_node *ni;
struct ieee80211com *ic = vap->iv_ic;
-@@ -1120,7 +1120,7 @@ static int
+@@ -1133,7 +1133,7 @@ static int
ieee80211_ioctl_setthrspy(struct net_device *dev, struct iw_request_info *info,
struct iw_point *data, char *extra)
{
struct iw_thrspy threshold;
if (data->length != 1)
-@@ -1157,7 +1157,7 @@ static int
+@@ -1170,7 +1170,7 @@ static int
ieee80211_ioctl_getthrspy(struct net_device *dev, struct iw_request_info *info,
struct iw_point *data, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct iw_thrspy *threshold;
-@@ -1178,7 +1178,7 @@ static int
+@@ -1191,7 +1191,7 @@ static int
ieee80211_ioctl_siwmode(struct net_device *dev, struct iw_request_info *info,
__u32 *mode, char *extra)
{
struct ifmediareq imr;
int valid = 0;
-@@ -1203,7 +1203,7 @@ static int
+@@ -1216,7 +1216,7 @@ static int
ieee80211_ioctl_giwmode(struct net_device *dev, struct iw_request_info *info,
__u32 *mode, char *extra)
{
struct ifmediareq imr;
memset(&imr, 0, sizeof(imr));
-@@ -1226,7 +1226,7 @@ static int
+@@ -1239,7 +1239,7 @@ static int
ieee80211_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info,
struct iw_param *wrq, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
/* XXX: These values, flags, and caps do not seem to be used elsewhere
-@@ -1265,7 +1265,7 @@ static int
+@@ -1278,7 +1278,7 @@ static int
ieee80211_ioctl_giwpower(struct net_device *dev, struct iw_request_info *info,
struct iw_param *rrq, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
rrq->disabled = (ic->ic_flags & IEEE80211_F_PMGTON) == 0;
-@@ -1289,7 +1289,7 @@ static int
+@@ -1302,7 +1302,7 @@ static int
ieee80211_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info,
struct iw_param *rrq, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
if (rrq->disabled) {
-@@ -1321,7 +1321,7 @@ static int
+@@ -1334,7 +1334,7 @@ static int
ieee80211_ioctl_giwretry(struct net_device *dev, struct iw_request_info *info,
struct iw_param *rrq, char *extra)
{
rrq->disabled = (vap->iv_flags & IEEE80211_F_SWRETRY) == 0;
if (!rrq->disabled) {
-@@ -1352,7 +1352,7 @@ static int
+@@ -1365,7 +1365,7 @@ static int
ieee80211_ioctl_siwtxpow(struct net_device *dev, struct iw_request_info *info,
struct iw_param *rrq, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
int fixed, disabled;
-@@ -1389,7 +1389,7 @@ ieee80211_get_txcont(struct net_device *
+@@ -1402,7 +1402,7 @@ ieee80211_get_txcont(struct net_device *
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
params[0] = ic->ic_get_txcont(ic);
return 0;
-@@ -1400,7 +1400,7 @@ ieee80211_get_dfs_cac_time(struct net_de
+@@ -1413,7 +1413,7 @@ ieee80211_get_dfs_cac_time(struct net_de
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
params[0] = ic->ic_get_dfs_cac_time(ic);
return 0;
-@@ -1411,7 +1411,7 @@ ieee80211_get_dfs_excl_period(struct net
+@@ -1424,7 +1424,7 @@ ieee80211_get_dfs_excl_period(struct net
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
params[0] = ic->ic_get_dfs_excl_period(ic);
return 0;
-@@ -1421,7 +1421,7 @@ ieee80211_set_dfs_cac_time(struct net_de
+@@ -1434,7 +1434,7 @@ ieee80211_set_dfs_cac_time(struct net_de
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
ic->ic_set_dfs_cac_time(ic, params[1]);
return 0;
-@@ -1431,7 +1431,7 @@ ieee80211_set_dfs_excl_period (struct n
+@@ -1444,7 +1444,7 @@ ieee80211_set_dfs_excl_period (struct n
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
ic->ic_set_dfs_excl_period(ic, params[1]);
return 0;
-@@ -1442,7 +1442,7 @@ ieee80211_get_dfs_testmode(struct net_de
+@@ -1455,7 +1455,7 @@ ieee80211_get_dfs_testmode(struct net_de
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
params[0] = ic->ic_get_dfs_testmode(ic);
return 0;
-@@ -1453,7 +1453,7 @@ ieee80211_get_txcont_rate(struct net_dev
+@@ -1466,7 +1466,7 @@ ieee80211_get_txcont_rate(struct net_dev
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
params[0] = ic->ic_get_txcont_rate(ic);
return 0;
-@@ -1464,7 +1464,7 @@ ieee80211_set_txcont(struct net_device *
+@@ -1477,7 +1477,7 @@ ieee80211_set_txcont(struct net_device *
void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
ic->ic_set_txcont(ic, params[1]);
return 0;
-@@ -1475,7 +1475,7 @@ ieee80211_set_dfs_testmode(struct net_de
+@@ -1488,7 +1488,7 @@ ieee80211_set_dfs_testmode(struct net_de
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
ic->ic_set_dfs_testmode(ic, params[1]);
return 0;
-@@ -1486,7 +1486,7 @@ ieee80211_set_txcont_rate(struct net_dev
+@@ -1499,7 +1499,7 @@ ieee80211_set_txcont_rate(struct net_dev
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
ic->ic_set_txcont_rate(ic, params[1]);
return 0;
-@@ -1497,7 +1497,7 @@ ieee80211_set_txcont_power(struct net_de
+@@ -1510,7 +1510,7 @@ ieee80211_set_txcont_power(struct net_de
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
ic->ic_set_txcont_power(ic, params[1]);
return 0;
-@@ -1508,7 +1508,7 @@ ieee80211_get_txcont_power(struct net_de
+@@ -1521,7 +1521,7 @@ ieee80211_get_txcont_power(struct net_de
struct iw_request_info *info, void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
params[0] = ic->ic_get_txcont_power(ic);
return 0;
-@@ -1520,7 +1520,7 @@ ieee80211_ioctl_hal_map(struct net_devic
+@@ -1533,7 +1533,7 @@ ieee80211_ioctl_hal_map(struct net_devic
void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
params[0] = ic->ic_dump_hal_map(ic);
return 0;
-@@ -1532,7 +1532,7 @@ ieee80211_ioctl_radar(struct net_device
+@@ -1545,7 +1545,7 @@ ieee80211_ioctl_radar(struct net_device
void *w, char *extra)
{
int *params = (int*) extra;
struct ieee80211com *ic = vap->iv_ic;
if (!(ic->ic_flags & IEEE80211_F_DOTH))
return 0;
-@@ -1544,7 +1544,7 @@ static int
+@@ -1557,7 +1557,7 @@ static int
ieee80211_ioctl_giwtxpow(struct net_device *dev, struct iw_request_info *info,
struct iw_param *rrq, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
unsigned int power = ic->ic_txpowlimit;
struct ieee80211_channel *c;
-@@ -1572,7 +1572,7 @@ static int
+@@ -1581,7 +1581,7 @@ static int
ieee80211_dump_registers(struct net_device *dev, struct iw_request_info *info, void *w, char *extra)
{
unsigned int *params = (unsigned int*) extra;
struct ieee80211com *ic = vap->iv_ic;
switch (params[1]) {
case 2:
-@@ -1595,7 +1595,7 @@ static int
+@@ -1604,7 +1604,7 @@ static int
ieee80211_ioctl_writereg(struct net_device *dev, struct iw_request_info *info, void *w, char *extra)
{
unsigned int *params = (unsigned int*) extra;
struct ieee80211com *ic = vap->iv_ic;
return ic->ic_write_register(ic, params[0], params[1]);
}
-@@ -1606,7 +1606,7 @@ static int
+@@ -1615,7 +1615,7 @@ static int
ieee80211_ioctl_readreg(struct net_device *dev, struct iw_request_info *info, void *w, char *extra)
{
unsigned int *params = (unsigned int*) extra;
struct ieee80211com *ic = vap->iv_ic;
return ic->ic_read_register(ic, params[0], ¶ms[0]);
}
-@@ -1642,7 +1642,7 @@ static int
+@@ -1651,7 +1651,7 @@ static int
ieee80211_ioctl_iwaplist(struct net_device *dev, struct iw_request_info *info,
struct iw_point *data, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct waplistreq req; /* XXX off stack */
-@@ -1664,7 +1664,7 @@ static int
+@@ -1673,7 +1673,7 @@ static int
ieee80211_ioctl_siwscan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *data, char *extra)
{
/*
* XXX don't permit a scan to be started unless we
-@@ -1988,7 +1988,7 @@ static int
+@@ -1997,7 +1997,7 @@ static int
ieee80211_ioctl_giwscan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *data, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct iwscanreq req;
int res = 0;
-@@ -2089,7 +2089,7 @@ static int
+@@ -2098,7 +2098,7 @@ static int
ieee80211_ioctl_setmode(struct net_device *dev, struct iw_request_info *info,
struct iw_point *wri, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ifreq ifr;
char s[6]; /* big enough for ``11adt'' */
-@@ -2213,10 +2213,10 @@ ieee80211_setathcap(struct ieee80211vap
+@@ -2222,10 +2222,10 @@ ieee80211_setathcap(struct ieee80211vap
static int
ieee80211_set_turbo(struct net_device *dev, int flag)
{
int nvap = 0;
TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next)
-@@ -2237,7 +2237,7 @@ static int
+@@ -2246,7 +2246,7 @@ static int
ieee80211_ioctl_setparam(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
unsigned int *i = (unsigned int *) extra;
-@@ -2917,7 +2917,7 @@ static int
+@@ -2926,7 +2926,7 @@ static int
ieee80211_ioctl_getmode(struct net_device *dev, struct iw_request_info *info,
struct iw_point *wri, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ifmediareq imr;
-@@ -2955,7 +2955,7 @@ static int
+@@ -2964,7 +2964,7 @@ static int
ieee80211_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
unsigned int *param = (unsigned int *) extra;
-@@ -3300,7 +3300,7 @@ static int
+@@ -3309,7 +3309,7 @@ static int
ieee80211_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info,
struct iw_point *wri, char *extra)
{
void *ie;
/*
-@@ -3334,7 +3334,7 @@ static int
+@@ -3343,7 +3343,7 @@ static int
ieee80211_ioctl_getoptie(struct net_device *dev, struct iw_request_info *info,
struct iw_point *wri, char *extra)
{
if (vap->iv_opt_ie == NULL) {
wri->length = 0;
-@@ -3398,7 +3398,7 @@ ieee80211_ioctl_setappiebuf(struct net_d
+@@ -3407,7 +3407,7 @@ ieee80211_ioctl_setappiebuf(struct net_d
struct iw_request_info *info,
struct iw_point *data, char *extra)
{
struct ieee80211req_getset_appiebuf *iebuf =
(struct ieee80211req_getset_appiebuf *)extra;
enum ieee80211_opmode chk_opmode;
-@@ -3440,7 +3440,7 @@ static int
+@@ -3449,7 +3449,7 @@ static int
ieee80211_ioctl_getappiebuf(struct net_device *dev, struct iw_request_info *info,
struct iw_point *data, char *extra)
{
struct ieee80211req_getset_appiebuf *iebuf =
(struct ieee80211req_getset_appiebuf *)extra;
int max_iebuf_len;
-@@ -3481,7 +3481,7 @@ static int
+@@ -3490,7 +3490,7 @@ static int
ieee80211_ioctl_setfilter(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct ieee80211req_set_filter *app_filter = (struct ieee80211req_set_filter *)extra;
if ((extra == NULL) || (app_filter->app_filterype & ~IEEE80211_FILTER_TYPE_ALL))
-@@ -3496,7 +3496,7 @@ static int
+@@ -3505,7 +3505,7 @@ static int
ieee80211_ioctl_setkey(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211req_key *ik = (struct ieee80211req_key *)extra;
struct ieee80211_node *ni;
-@@ -3579,7 +3579,7 @@ ieee80211_ioctl_setkey(struct net_device
+@@ -3588,7 +3588,7 @@ ieee80211_ioctl_setkey(struct net_device
static int
ieee80211_ioctl_getkey(struct net_device *dev, struct iwreq *iwr)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node *ni;
struct ieee80211req_key ik;
-@@ -3640,7 +3640,7 @@ static int
+@@ -3649,7 +3649,7 @@ static int
ieee80211_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211req_del_key *dk = (struct ieee80211req_del_key *)extra;
ieee80211_keyix_t kix;
-@@ -3714,7 +3714,7 @@ static int
+@@ -3723,7 +3723,7 @@ static int
ieee80211_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra;
struct ieee80211_node *ni;
-@@ -3817,7 +3817,7 @@ static int
+@@ -3826,7 +3826,7 @@ static int
ieee80211_ioctl_wdsaddmac(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct sockaddr *sa = (struct sockaddr *)extra;
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211vap *avp;
-@@ -3846,7 +3846,7 @@ static int
+@@ -3855,7 +3855,7 @@ static int
ieee80211_ioctl_wdssetmac(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct sockaddr *sa = (struct sockaddr *)extra;
if (vap->iv_opmode != IEEE80211_M_WDS)
-@@ -3913,7 +3913,7 @@ ieee80211_ioctl_setscanlist(struct net_d
+@@ -3922,7 +3922,7 @@ ieee80211_ioctl_setscanlist(struct net_d
struct iw_request_info *info,
struct iw_point *data, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
char *s, *next;
int val = 1;
-@@ -3988,7 +3988,7 @@ static int
+@@ -3997,7 +3997,7 @@ static int
ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct sockaddr *sa = (struct sockaddr *)extra;
const struct ieee80211_aclator *acl = vap->iv_acl;
-@@ -4006,7 +4006,7 @@ static int
+@@ -4015,7 +4015,7 @@ static int
ieee80211_ioctl_delmac(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct sockaddr *sa = (struct sockaddr *)extra;
const struct ieee80211_aclator *acl = vap->iv_acl;
-@@ -4024,7 +4024,7 @@ static int
+@@ -4033,7 +4033,7 @@ static int
ieee80211_ioctl_setchanlist(struct net_device *dev,
struct iw_request_info *info, void *w, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211req_chanlist *list =
(struct ieee80211req_chanlist *)extra;
-@@ -4075,7 +4075,7 @@ static int
+@@ -4084,7 +4084,7 @@ static int
ieee80211_ioctl_getchanlist(struct net_device *dev,
struct iw_request_info *info, void *w, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
memcpy(extra, ic->ic_chan_active, sizeof(ic->ic_chan_active));
-@@ -4096,7 +4096,7 @@ static int
+@@ -4105,7 +4105,7 @@ static int
ieee80211_ioctl_getchaninfo(struct net_device *dev,
struct iw_request_info *info, void *w, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211req_chaninfo *chans =
(struct ieee80211req_chaninfo *)extra;
-@@ -4143,7 +4143,7 @@ static int
+@@ -4152,7 +4152,7 @@ static int
ieee80211_ioctl_setwmmparams(struct net_device *dev,
struct iw_request_info *info, void *w, char *extra)
{
unsigned int *param = (unsigned int *) extra;
unsigned int ac = (param[1] < WME_NUM_AC) ? param[1] : WME_AC_BE;
unsigned int bss = param[2];
-@@ -4231,7 +4231,7 @@ static int
+@@ -4240,7 +4240,7 @@ static int
ieee80211_ioctl_getwmmparams(struct net_device *dev,
struct iw_request_info *info, void *w, char *extra)
{
unsigned int *param = (unsigned int *) extra;
unsigned int ac = (param[1] < WME_NUM_AC) ? param[1] : WME_AC_BE;
struct ieee80211_wme_state *wme = &vap->iv_ic->ic_wme;
-@@ -4266,7 +4266,7 @@ ieee80211_ioctl_getwmmparams(struct net_
+@@ -4275,7 +4275,7 @@ ieee80211_ioctl_getwmmparams(struct net_
static int
ieee80211_ioctl_getwpaie(struct net_device *dev, struct iwreq *iwr)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node *ni;
struct ieee80211req_wpaie wpaie;
-@@ -4300,7 +4300,7 @@ ieee80211_ioctl_getwpaie(struct net_devi
+@@ -4309,7 +4309,7 @@ ieee80211_ioctl_getwpaie(struct net_devi
static int
ieee80211_ioctl_getstastats(struct net_device *dev, struct iwreq *iwr)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node *ni;
u_int8_t macaddr[IEEE80211_ADDR_LEN];
-@@ -4419,7 +4419,7 @@ get_scan_result(void *arg, const struct
+@@ -4428,7 +4428,7 @@ get_scan_result(void *arg, const struct
static int
ieee80211_ioctl_getscanresults(struct net_device *dev, struct iwreq *iwr)
{
struct ieee80211com *ic = vap->iv_ic;
struct scanreq req;
int error;
-@@ -4582,7 +4582,7 @@ get_sta_info(void *arg, struct ieee80211
+@@ -4591,7 +4591,7 @@ get_sta_info(void *arg, struct ieee80211
static int
ieee80211_ioctl_getstainfo(struct net_device *dev, struct iwreq *iwr)
{
struct ieee80211com *ic = vap->iv_ic;
struct stainforeq req;
int error;
-@@ -4616,7 +4616,7 @@ ieee80211_ioctl_getstainfo(struct net_de
+@@ -4625,7 +4625,7 @@ ieee80211_ioctl_getstainfo(struct net_de
static void
pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt) {
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211vap *avp;
-@@ -4634,7 +4634,7 @@ static int
+@@ -4643,7 +4643,7 @@ static int
ieee80211_ioctl_chanswitch(struct net_device *dev, struct iw_request_info *info,
void *w, char *extra)
{
struct ieee80211com *ic = vap->iv_ic;
unsigned int *param = (unsigned int *) extra;
-@@ -4679,7 +4679,7 @@ static int
+@@ -4688,7 +4688,7 @@ static int
ieee80211_ioctl_giwgenie(struct net_device *dev,
struct iw_request_info *info, struct iw_point *out, char *buf)
{
if (out->length < vap->iv_opt_ie_len)
return -E2BIG;
-@@ -5212,7 +5212,7 @@ static int
+@@ -5221,7 +5221,7 @@ static int
ieee80211_ioctl_giwencodeext(struct net_device *dev,
struct iw_request_info *info, struct iw_point *erq, char *extra)
{
struct iw_encode_ext *ext;
struct ieee80211_key *wk;
ieee80211_keyix_t kix;
-@@ -5272,7 +5272,7 @@ static int
+@@ -5281,7 +5281,7 @@ static int
ieee80211_ioctl_siwencodeext(struct net_device *dev,
struct iw_request_info *info, struct iw_point *erq, char *extra)
{
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
struct ieee80211req_key kr;
ieee80211_keyix_t kix;
-@@ -5948,7 +5948,7 @@ static struct iw_handler_def ieee80211_i
+@@ -5957,7 +5957,7 @@ static struct iw_handler_def ieee80211_i
static int
ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
int
ieee80211_vap_setup(struct ieee80211com *ic, struct net_device *dev,
const char *name, int opmode, int flags, struct ieee80211vap *master)
-@@ -470,12 +482,17 @@ ieee80211_vap_setup(struct ieee80211com
+@@ -470,16 +482,21 @@ ieee80211_vap_setup(struct ieee80211com
} else
strncpy(dev->name, name, sizeof(dev->name));
}
dev->hard_start_xmit = ieee80211_hardstart;
dev->set_multicast_list = ieee80211_set_multicast_list;
+ dev->do_ioctl = ieee80211_ioctl;
-+#else
-+ dev->netdev_ops = &ieee80211_netdev_ops;
-+#endif
#if 0
dev->set_mac_address = ieee80211_set_mac_address;
#endif
+ dev->change_mtu = ieee80211_change_mtu;
++#else
++ dev->netdev_ops = &ieee80211_netdev_ops;
++#endif
+ dev->tx_queue_len = 0; /* NB: bypass queuing */
+ dev->hard_header_len = parent->hard_header_len;
+ /*
@@ -1823,7 +1840,11 @@ ieee80211_set_multicast_list(struct net_
IEEE80211_UNLOCK_IRQ(ic);
case NETDEV_CHANGENAME:
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
-@@ -740,6 +740,7 @@ void ieee80211_build_sc_ie(struct ieee80
+@@ -739,6 +739,7 @@ void ieee80211_build_sc_ie(struct ieee80
void ieee80211_dfs_action(struct ieee80211com *);
void ieee80211_expire_channel_excl_restrictions(struct ieee80211com *);
void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
* Iterate through ic_channels to enumerate all distinct ic_ieee channel numbers.
--- a/net80211/ieee80211_wireless.c
+++ b/net80211/ieee80211_wireless.c
-@@ -5945,7 +5945,7 @@ static struct iw_handler_def ieee80211_i
+@@ -5954,7 +5954,7 @@ static struct iw_handler_def ieee80211_i
/*
* Handle private ioctl requests.
*/
ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct ieee80211vap *vap = netdev_priv(dev);
-@@ -6035,7 +6035,6 @@ ieee80211_ioctl_vattach(struct ieee80211
+@@ -6044,7 +6044,6 @@ ieee80211_ioctl_vattach(struct ieee80211
{
struct net_device *dev = vap->iv_dev;
--- /dev/null
+--- a/ath/Makefile
++++ b/ath/Makefile
+@@ -41,7 +41,6 @@
+ #
+
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)/..
+
+ ifeq ($(strip $(BUS)),AHB)
+ BUSNAME=ahb
+@@ -57,7 +56,24 @@ COPTS += -DDFS_DOMAIN_ETSI -DDFS_DOMAIN_
+ include $(TOP)/Makefile.inc
+
+ obj-m += ath_$(BUSNAME).o
+-ath_$(BUSNAME)-objs := if_ath.o if_ath_radar.o if_ath_$(BUSNAME).o
++ath_objs := if_ath.o if_ath_radar.o if_ath_$(BUSNAME).o
++ath_$(BUSNAME)-objs := $(ath_objs)
++
++ifneq ($(SINGLE_MODULE),)
++include $(TOP)/net80211/Makefile
++include $(TOP)/ath_rate/sample/Makefile
++include $(TOP)/ath_rate/minstrel/Makefile
++RC_DECLARE=$(foreach R,$(ATH_RATE),extern void ath_rate_$(R)_init(void);extern void ath_rate_$(R)_exit(void);)
++RC_INIT=$(foreach R,$(ATH_RATE),ath_rate_$(R)_init();)
++RC_EXIT=$(foreach R,$(ATH_RATE),ath_rate_$(R)_exit();)
++
++ath_$(BUSNAME)-objs += $(patsubst %,../net80211/%,$(wlan-objs) $(foreach var,wep tkip ccmp acl xauth scan_sta scan_ap,$(wlan_$(var)-objs))) $(foreach RC,$(ATH_RATE),$(patsubst %,../ath_rate/$(RC)/%,$(ath_rate_$(RC)-objs)))
++ifdef LINUX24
++ ath_$(BUSNAME)-linkobjs := $(ath_objs) $(wlan-objs) $(foreach var,wep tkip ccmp acl xauth scan_sta scan_ap,$(wlan_$(var)-objs)) $(foreach RC,$(ATH_RATE),$(ath_rate_$(RC)-objs))
++endif
++
++EXTRA_CFLAGS += -DSINGLE_MODULE -DRC_INIT="$(RC_INIT)" -DRC_EXIT="$(RC_EXIT)" -DRC_DECLARE="$(RC_DECLARE)"
++endif
+
+ INCS += -I$(TOP) -I$(ATH_HAL) -I$(HAL) -I$(WLAN)
+
+@@ -72,13 +88,8 @@ install:
+ test -d $(DESTDIR)/$(KMODPATH) || mkdir -p $(DESTDIR)/$(KMODPATH)
+ install -m 0644 ath_$(BUSNAME).$(KMODSUF) $(DESTDIR)/$(KMODPATH)
+
+-clean:
+- rm -f *~ *.o *.ko *.mod.c .*.cmd
+- rm -f .depend .version .*.o.flags .*.o.d
+- rm -rf .tmp_versions
+-
+ ath_$(BUSNAME).o: $(ath_$(BUSNAME)-objs)
+- $(LD) $(LDOPTS) -o ath_$(BUSNAME).$(KMODSUF) -r $(ath_$(BUSNAME)-objs)
++ $(LD) $(LDOPTS) -o ath_$(BUSNAME).$(KMODSUF) -r $(if $(ath_$(BUSNAME)-linkobjs),$(ath_$(BUSNAME)-linkobjs),$(ath_$(BUSNAME)-objs))
+
+ if_ath_hal.h: $(HAL)/ah.h
+ $(TOP)/scripts/if_ath_hal_generator.pl $< $@
+--- a/net80211/ieee80211_acl.c
++++ b/net80211/ieee80211_acl.c
+@@ -281,16 +281,6 @@ acl_getpolicy(struct ieee80211vap *vap)
+ return as->as_policy;
+ }
+
+-/*
+- * Module glue.
+- */
+-
+-MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+-MODULE_DESCRIPTION("802.11 wireless support: MAC-based ACL policy");
+-#ifdef MODULE_LICENSE
+-MODULE_LICENSE("Dual BSD/GPL");
+-#endif
+-
+ static const struct ieee80211_aclator mac = {
+ .iac_name = "mac",
+ .iac_attach = acl_attach,
+@@ -303,6 +293,18 @@ static const struct ieee80211_aclator ma
+ .iac_getpolicy = acl_getpolicy,
+ };
+
++#include "module.h"
++/*
++ * Module glue.
++ */
++
++MODULE_AUTHOR("Errno Consulting, Sam Leffler");
++MODULE_DESCRIPTION("802.11 wireless support: MAC-based ACL policy");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual BSD/GPL");
++#endif
++
++
+ static int __init
+ init_ieee80211_acl(void)
+ {
+--- a/net80211/ieee80211_crypto_ccmp.c
++++ b/net80211/ieee80211_crypto_ccmp.c
+@@ -686,6 +686,8 @@ ccmp_decrypt(struct ieee80211_key *key,
+ }
+ #undef CCMP_DECRYPT
+
++#include "module.h"
++
+ /*
+ * Module glue.
+ */
+--- a/net80211/ieee80211_crypto_tkip.c
++++ b/net80211/ieee80211_crypto_tkip.c
+@@ -1046,6 +1046,8 @@ tkip_decrypt(struct tkip_ctx *ctx, struc
+ return 1;
+ }
+
++#include "module.h"
++
+ /*
+ * Module glue.
+ */
+--- a/net80211/ieee80211_crypto_wep.c
++++ b/net80211/ieee80211_crypto_wep.c
+@@ -497,6 +497,8 @@ wep_decrypt(struct ieee80211_key *key, s
+ * Module glue.
+ */
+
++#include "module.h"
++
+ MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+ MODULE_DESCRIPTION("802.11 wireless support: WEP cipher");
+ #ifdef MODULE_LICENSE
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -1015,6 +1015,10 @@ static struct notifier_block ieee80211_e
+ static char *version = RELEASE_VERSION;
+ static char *dev_info = "wlan";
+
++extern void ieee80211_auth_setup(void);
++
++#include "module.h"
++
+ MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+ MODULE_DESCRIPTION("802.11 wireless LAN protocol support");
+ #ifdef MODULE_VERSION
+@@ -1024,8 +1028,6 @@ MODULE_VERSION(RELEASE_VERSION);
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
+-extern void ieee80211_auth_setup(void);
+-
+ static int __init
+ init_wlan(void)
+ {
+--- a/net80211/ieee80211_scan_ap.c
++++ b/net80211/ieee80211_scan_ap.c
+@@ -763,15 +763,6 @@ action_tasklet(IEEE80211_TQUEUE_ARG data
+ (*ss->ss_ops->scan_default)(vap, &as->as_selbss);
+ }
+
+-/*
+- * Module glue.
+- */
+-MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+-MODULE_DESCRIPTION("802.11 wireless support: default ap scanner");
+-#ifdef MODULE_LICENSE
+-MODULE_LICENSE("Dual BSD/GPL");
+-#endif
+-
+ static const struct ieee80211_scanner ap_default = {
+ .scan_name = "default",
+ .scan_attach = ap_attach,
+@@ -789,6 +780,16 @@ static const struct ieee80211_scanner ap
+ .scan_default = ap_default_action,
+ };
+
++#include "module.h"
++
++/*
++ * Module glue.
++ */
++MODULE_AUTHOR("Errno Consulting, Sam Leffler");
++MODULE_DESCRIPTION("802.11 wireless support: default ap scanner");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual BSD/GPL");
++#endif
+
+ static int __init
+ init_scanner_ap(void)
+--- a/net80211/ieee80211_scan_sta.c
++++ b/net80211/ieee80211_scan_sta.c
+@@ -1208,6 +1208,8 @@ action_tasklet(IEEE80211_TQUEUE_ARG data
+ ieee80211_start_scan(vap, ss->ss_flags, ss->ss_duration, ss->ss_nssid, ss->ss_ssid);
+ }
+
++#include "module.h"
++
+ /*
+ * Module glue.
+ */
+@@ -1217,6 +1219,7 @@ MODULE_DESCRIPTION("802.11 wireless supp
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
++
+ static int __init
+ init_scanner_sta(void)
+ {
+--- a/net80211/ieee80211_xauth.c
++++ b/net80211/ieee80211_xauth.c
+@@ -65,15 +65,6 @@
+ #include <net80211/ieee80211_var.h>
+
+ /*
+- * Module glue.
+- */
+-MODULE_AUTHOR("Errno Consulting, Sam Leffler");
+-MODULE_DESCRIPTION("802.11 wireless support: external (user mode) authenticator");
+-#ifdef MODULE_LICENSE
+-MODULE_LICENSE("Dual BSD/GPL");
+-#endif
+-
+-/*
+ * One module handles everything for now. May want
+ * to split things up for embedded applications.
+ */
+@@ -85,6 +76,18 @@ static const struct ieee80211_authentica
+ .ia_node_leave = NULL,
+ };
+
++#include "module.h"
++
++/*
++ * Module glue.
++ */
++MODULE_AUTHOR("Errno Consulting, Sam Leffler");
++MODULE_DESCRIPTION("802.11 wireless support: external (user mode) authenticator");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual BSD/GPL");
++#endif
++
++
+ static int __init
+ init_ieee80211_xauth(void)
+ {
+--- a/net80211/Makefile
++++ b/net80211/Makefile
+@@ -40,7 +40,11 @@
+ # Makefile for the 802.11 WLAN modules.
+ #
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)/..
++
++include $(TOP)/Makefile.inc
++
++ifeq ($(SINGLE_MODULE),)
++
+ #
+ # There is one authenticator mechanism: an in-kernel implementation
+ # (wlan_xauth).
+@@ -59,29 +63,8 @@ MOD_INSTALL := wlan.o wlan_wep.o wlan_tk
+
+ obj-m += $(MOD_INSTALL)
+
+-wlan-objs := if_media.o \
+- ieee80211_skb.o \
+- ieee80211.o ieee80211_beacon.o ieee80211_crypto.o \
+- ieee80211_crypto_none.o ieee80211_input.o ieee80211_node.o \
+- ieee80211_output.o ieee80211_power.o ieee80211_proto.o \
+- ieee80211_scan.o ieee80211_wireless.o ieee80211_linux.o \
+- ieee80211_monitor.o ieee80211_rate.o
+-wlan_wep-objs := ieee80211_crypto_wep.o
+-wlan_tkip-objs := ieee80211_crypto_tkip.o
+-wlan_ccmp-objs := ieee80211_crypto_ccmp.o
+-wlan_acl-objs := ieee80211_acl.o
+-wlan_xauth-objs := ieee80211_xauth.o
+-wlan_scan_sta-objs :=ieee80211_scan_sta.o
+-wlan_scan_ap-objs := ieee80211_scan_ap.o
+-
+-include $(TOP)/Makefile.inc
+-
+ INCS += -I$(TOP) -I$(ATH_HAL) -I$(HAL)
+
+-EXTRA_CFLAGS+=$(INCS) $(COPTS) -DOPT_AH_H=\"public/$(TARGET).opt_ah.h\"
+-
+--include $(TOPDIR)/Rules.make
+-
+ all:
+ $(MAKE) -C $(KERNELPATH) SUBDIRS=$(shell pwd) modules
+
+@@ -108,8 +91,28 @@ install:
+ f=`basename $$i .o`; \
+ install -m 0644 $$f.$(KMODSUF) $(DESTDIR)/$(KMODPATH); \
+ done
++else
++all:
++endif
++
++wlan-objs := if_media.o \
++ ieee80211_skb.o \
++ ieee80211.o ieee80211_beacon.o ieee80211_crypto.o \
++ ieee80211_crypto_none.o ieee80211_input.o ieee80211_node.o \
++ ieee80211_output.o ieee80211_power.o ieee80211_proto.o \
++ ieee80211_scan.o ieee80211_wireless.o ieee80211_linux.o \
++ ieee80211_monitor.o ieee80211_rate.o
++wlan_wep-objs := ieee80211_crypto_wep.o
++wlan_tkip-objs := ieee80211_crypto_tkip.o
++wlan_ccmp-objs := ieee80211_crypto_ccmp.o
++wlan_acl-objs := ieee80211_acl.o
++wlan_xauth-objs := ieee80211_xauth.o
++wlan_scan_sta-objs :=ieee80211_scan_sta.o
++wlan_scan_ap-objs := ieee80211_scan_ap.o
++
++
++EXTRA_CFLAGS+=$(INCS) $(COPTS) -DOPT_AH_H=\"public/$(TARGET).opt_ah.h\"
++
++-include $(TOPDIR)/Rules.make
++
+
+-clean:
+- -rm -f *~ *.o *.ko *.mod.c
+- -rm -f .depend .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd
+- -rm -rf .tmp_versions
+--- /dev/null
++++ b/net80211/module.h
+@@ -0,0 +1,19 @@
++#ifdef SINGLE_MODULE
++
++#undef static
++#define static
++#undef module_init
++#undef module_exit
++#define module_init(...)
++#define module_exit(...)
++
++#undef MODULE_AUTHOR
++#undef MODULE_LICENSE
++#undef MODULE_VERSION
++#undef MODULE_DESCRIPTION
++#define MODULE_AUTHOR(...)
++#define MODULE_LICENSE(...)
++#define MODULE_VERSION(...)
++#define MODULE_DESCRIPTION(...)
++
++#endif
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -13780,3 +13780,5 @@ cleanup_ath_buf(struct ath_softc *sc, st
+ return bf;
+ }
+
++
++
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -42,6 +42,7 @@
+ #include <linux/config.h>
+ #endif
+ #include <linux/version.h>
++#include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
+@@ -2014,3 +2015,65 @@ ieee80211_build_sc_ie(struct ieee80211co
+ int ath_debug_global = 0;
+ EXPORT_SYMBOL(ath_debug_global);
+
++#ifdef SINGLE_MODULE
++typedef void (*initfunc)(void);
++
++extern void init_ieee80211_acl(void);
++extern void init_crypto_ccmp(void);
++extern void init_crypto_tkip(void);
++extern void init_crypto_wep(void);
++extern void init_wlan(void);
++extern void init_scanner_ap(void);
++extern void init_scanner_sta(void);
++extern void init_ieee80211_xauth(void);
++
++extern void exit_ieee80211_acl(void);
++extern void exit_crypto_ccmp(void);
++extern void exit_crypto_tkip(void);
++extern void exit_crypto_wep(void);
++extern void exit_wlan(void);
++extern void exit_scanner_ap(void);
++extern void exit_scanner_sta(void);
++extern void exit_ieee80211_xauth(void);
++
++static __initdata initfunc net80211_init[] = {
++ init_wlan,
++ init_ieee80211_acl,
++ init_crypto_ccmp,
++ init_crypto_tkip,
++ init_crypto_wep,
++ init_ieee80211_xauth,
++ init_scanner_ap,
++ init_scanner_sta,
++};
++
++static __exitdata initfunc net80211_exit[] = {
++ exit_crypto_ccmp,
++ exit_crypto_tkip,
++ exit_crypto_wep,
++ exit_scanner_ap,
++ exit_scanner_sta,
++ exit_ieee80211_xauth,
++ exit_ieee80211_acl,
++ exit_wlan,
++};
++
++void net80211_init_module(void)
++{
++ int i;
++ for (i = 0; i < sizeof(net80211_init)/sizeof(net80211_init[0]); i++) {
++ if (net80211_init[i])
++ net80211_init[i]();
++ }
++}
++
++void net80211_exit_module(void)
++{
++ int i;
++ for (i = 0; i < sizeof(net80211_exit)/sizeof(net80211_exit[0]); i++) {
++ if (net80211_exit[i])
++ net80211_exit[i]();
++ }
++}
++
++#endif
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -447,10 +447,18 @@ MODULE_SUPPORTED_DEVICE("Atheros WLAN ca
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
++#ifdef SINGLE_MODULE
++RC_DECLARE
++#endif
++
+ static int __init
+ init_ath_ahb(void)
+ {
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
++#ifdef SINGLE_MODULE
++ net80211_init_module();
++ RC_INIT
++#endif
+ platform_driver_register(&ahb_wmac_driver);
+ ath_sysctl_register();
+
+@@ -463,6 +471,10 @@ exit_ath_ahb(void)
+ {
+ ath_sysctl_unregister();
+ platform_driver_unregister(&ahb_wmac_driver);
++#ifdef SINGLE_MODULE
++ RC_EXIT
++ net80211_exit_module();
++#endif
+ printk(KERN_INFO "%s: driver unloaded\n", dev_info);
+ }
+ module_exit(exit_ath_ahb);
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -415,11 +415,19 @@ MODULE_SUPPORTED_DEVICE("Atheros WLAN ca
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
++#ifdef SINGLE_MODULE
++RC_DECLARE
++#endif
++
+ static int __init
+ init_ath_pci(void)
+ {
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+
++#ifdef SINGLE_MODULE
++ net80211_init_module();
++ RC_INIT
++#endif
+ if (pci_register_driver(&ath_pci_driver) < 0) {
+ printk(KERN_ERR "%s: No devices found, driver not installed.\n", dev_info);
+ return (-ENODEV);
+@@ -434,6 +442,10 @@ exit_ath_pci(void)
+ {
+ ath_sysctl_unregister();
+ pci_unregister_driver(&ath_pci_driver);
++#ifdef SINGLE_MODULE
++ RC_EXIT
++ net80211_exit_module();
++#endif
+
+ printk(KERN_INFO "%s: driver unloaded\n", dev_info);
+ }
+--- a/ath_rate/minstrel/Makefile
++++ b/ath_rate/minstrel/Makefile
+@@ -39,9 +39,7 @@
+ # Makefile for the Atheros Rate Control Support.
+ #
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)/../..
+
+-obj-m += ath_rate_minstrel.o
+ ath_rate_minstrel-objs := minstrel.o
+
+ include $(TOP)/Makefile.inc
+@@ -50,6 +48,10 @@ INCS += -I$(TOP) -I$(ATH) -I$(ATH_HAL) -
+
+ EXTRA_CFLAGS+= $(INCS) $(COPTS) -DOPT_AH_H=\"public/$(TARGET).opt_ah.h\"
+
++ifeq ($(SINGLE_MODULE),)
++
++obj-m += ath_rate_minstrel.o
++
+ -include $(TOPDIR)/Rules.make
+
+ all:
+@@ -59,10 +61,9 @@ install:
+ test -d $(DESTDIR)/$(KMODPATH) || mkdir -p $(DESTDIR)/$(KMODPATH)
+ install -m 0644 ath_rate_minstrel.$(KMODSUF) $(DESTDIR)/$(KMODPATH)
+
+-clean:
+- -rm -f *~ *.o *.ko *.mod.c
+- -rm -f .depend .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd
+- -rm -rf .tmp_versions
+-
+ ath_rate_minstrel.o: $(ath_rate_minstrel-objs)
+ $(LD) $(LDOPTS) -o ath_rate_minstrel.$(KMODSUF) -r $(ath_rate_minstrel-objs)
++else
++all:
++install:
++endif
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -945,6 +945,8 @@ static struct ieee80211_rate_ops ath_rat
+ .dynamic_proc_register = ath_rate_dynamic_proc_register,
+ };
+
++#include <net80211/module.h>
++
+ MODULE_AUTHOR("John Bicket/Derek Smithies");
+ MODULE_DESCRIPTION("Minstrel Rate bit-rate selection algorithm for Atheros devices");
+ #ifdef MODULE_VERSION
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -47,6 +47,7 @@
+ #include <net80211/ieee80211_power.h>
+ #include <net80211/ieee80211_proto.h>
+ #include <net80211/ieee80211_scan.h>
++#include "symbol.h"
+
+ /* NB:
+ * - Atheros chips use 6 bits when power is specified in whole dBm units, with
+@@ -740,6 +741,8 @@ void ieee80211_dfs_action(struct ieee802
+ void ieee80211_expire_channel_excl_restrictions(struct ieee80211com *);
+ void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
+ int ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
++void net80211_init_module(void);
++void net80211_exit_module(void);
+
+ /*
+ * Iterate through ic_channels to enumerate all distinct ic_ieee channel numbers.
+--- a/net80211/ieee80211_linux.h
++++ b/net80211/ieee80211_linux.h
+@@ -521,7 +521,10 @@ extern struct sk_buff * ieee80211_getmgt
+ #define IF_DRAIN(_q) skb_queue_drain(_q)
+ extern void skb_queue_drain(struct sk_buff_head *q);
+
+-#ifndef __MOD_INC_USE_COUNT
++#ifdef SINGLE_MODULE
++#define _MOD_DEC_USE(_m) do {} while(0)
++#define _MOD_INC_USE(_m, _err) do {} while(0)
++#elif !defined(__MOD_INC_USE_COUNT)
+ #define _MOD_INC_USE(_m, _err) \
+ if (!try_module_get(_m)) { \
+ printk(KERN_WARNING "%s: try_module_get failed\n", \
+--- a/ath_rate/sample/Makefile
++++ b/ath_rate/sample/Makefile
+@@ -39,9 +39,7 @@
+ # Makefile for the Atheros Rate Control Support.
+ #
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)/../..
+
+-obj-m += ath_rate_sample.o
+ ath_rate_sample-objs := sample.o
+
+ include $(TOP)/Makefile.inc
+@@ -50,6 +48,9 @@ INCS += -I$(TOP) -I$(ATH) -I$(ATH_HAL) -
+
+ EXTRA_CFLAGS+= $(INCS) $(COPTS) -DOPT_AH_H=\"public/$(TARGET).opt_ah.h\"
+
++ifeq ($(SINGLE_MODULE),)
++obj-m += ath_rate_sample.o
++
+ -include $(TOPDIR)/Rules.make
+
+ all:
+@@ -59,10 +60,9 @@ install:
+ test -d $(DESTDIR)/$(KMODPATH) || mkdir -p $(DESTDIR)/$(KMODPATH)
+ install -m 0644 ath_rate_sample.$(KMODSUF) $(DESTDIR)/$(KMODPATH)
+
+-clean:
+- -rm -f *~ *.o *.ko *.mod.c
+- -rm -f .depend .version .*.o.flags .*.o.d .*.o.cmd .*.ko.cmd
+- -rm -rf .tmp_versions
+-
+ ath_rate_sample.o: $(ath_rate_sample-objs)
+ $(LD) $(LDOPTS) -o ath_rate_sample.$(KMODSUF) -r $(ath_rate_sample-objs)
++else
++all:
++install:
++endif
+--- a/Makefile
++++ b/Makefile
+@@ -41,7 +41,7 @@
+ #
+
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+-TOP = $(obj)
++export TOP:=$(if $(wildcard $(firstword $(SUBDIRS))/Makefile.inc),$(firstword $(SUBDIRS)),$(CURDIR))
+
+ ifneq (svnversion.h,$(MAKECMDGOALS))
+ include $(TOP)/Makefile.inc
+@@ -54,7 +54,7 @@ all: modules tools
+ modules: configcheck svnversion.h
+ ifdef LINUX24
+ for i in $(obj-y); do \
+- $(MAKE) -C $$i || exit 1; \
++ $(MAKE) -C $$i TOP="$(TOP)" || exit 1; \
+ done
+ else
+ $(MAKE) -C $(KERNELPATH) SUBDIRS=$(shell pwd) modules
+@@ -89,7 +89,7 @@ install-modules: modules
+ sh scripts/find-madwifi-modules.sh -r $(KERNELRELEASE) $(DESTDIR)
+
+ for i in $(obj-y); do \
+- $(MAKE) -C $$i install || exit 1; \
++ $(MAKE) -C $$i install TOP="$(TOP)" || exit 1; \
+ done
+ ifeq ($(DESTDIR),)
+ (export KMODPATH=$(KMODPATH); /sbin/depmod -ae $(KERNELRELEASE))
+@@ -114,12 +114,21 @@ reinstall-tools: uninstall-tools install
+ reinstall-modules: uninstall-modules install-modules
+
+ clean:
+- for i in $(obj-y); do \
+- $(MAKE) -C $$i clean; \
+- done
+- -$(MAKE) -C $(TOOLS) clean
+- rm -rf .tmp_versions
++ -find $(obj-y) -name '*~' \
++ -or -name '*.o' \
++ -or -name '*.o.d' \
++ -or -name '*.o.cmd' \
++ -or -name '*.o.flags' \
++ -or -name '*.ko' \
++ -or -name '*.ko.cmd' \
++ -or -name '*.mod.c' \
++ -or -name '.depend' \
++ -or -name '.version' \
++ -or -name '.symvers' | \
++ xargs -r rm -f
+ rm -f *.symvers svnversion.h
++ rm -rf .tmp_versions
++ make -C tools clean
+
+ info:
+ @echo "The following settings will be used for compilation:"
+@@ -135,18 +144,6 @@ info:
+ @echo "KMODPATH : $(KMODPATH)"
+ @echo "KMODSUF : $(KMODSUF)"
+
+-sanitycheck:
+- @echo -n "Checking requirements... "
+-
+- @# check if specified rate control is available
+- @if [ ! -d $(ATH_RATE) ]; then \
+- echo "FAILED"; \
+- echo "Selected rate control $(ATH_RATE) not available."; \
+- exit 1; \
+- fi
+-
+- @echo "ok."
+-
+ .PHONY: release
+ release:
+ sh scripts/make-release.bash
+@@ -155,7 +152,7 @@ release:
+ unload:
+ bash scripts/madwifi-unload
+
+-configcheck: sanitycheck
++configcheck:
+ @echo -n "Checking kernel configuration... "
+
+ @# check version of kernel
+--- a/Makefile.inc
++++ b/Makefile.inc
+@@ -68,6 +68,9 @@ endif
+ export KERNELPATH
+ endif
+
++# build net80211 and ath_ahb/ath_pci into a single module
++export SINGLE_MODULE=1
++
+ # KERNELRELEASE is the target kernel's version. It's always taken from
+ # the kernel build tree. Kernel Makefile doesn't always know the exact
+ # kernel version (especially for vendor stock kernels), so we get it
+@@ -100,6 +103,7 @@ export ARCH
+ include $(TOP)/ath_hal/ah_target.inc
+ export TARGET
+ COPTS += -DTARGET='"$(TARGET)"'
++COPTS += -DCONFIG_ATHEROS_RATE_DEFAULT='"$(firstword $(ATH_RATE))"'
+
+ # KMODPATH nominates the directory where the modules will be
+ # installed to
+@@ -141,7 +145,7 @@ ATH= $(TOP)/ath
+ #
+ # Path to the rate control algorithms.
+ #
+-ATH_RATE= $(TOP)/ath_rate
++ATH_RATE= minstrel
+ #
+ # Path to the userspace utilities.
+ #
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -991,6 +991,8 @@ static struct ieee80211_rate_ops ath_rat
+ .dynamic_proc_register = ath_rate_dynamic_proc_register,
+ };
+
++#include <net80211/module.h>
++
+ MODULE_AUTHOR("John Bicket");
+ MODULE_DESCRIPTION("SampleRate bit-rate selection algorithm for Atheros devices");
+ #ifdef MODULE_VERSION
+@@ -1000,18 +1002,17 @@ MODULE_VERSION(RELEASE_VERSION);
+ MODULE_LICENSE("Dual BSD/GPL");
+ #endif
+
+-static int __init
+-init_ath_rate_sample(void)
++static int __init ath_rate_sample_init(void)
+ {
+ printk(KERN_INFO "%s: %s\n", dev_info, version);
+ return ieee80211_rate_register(&ath_rate_ops);
+ }
+-module_init(init_ath_rate_sample);
++module_init(ath_rate_sample_init);
+
+ static void __exit
+-exit_ath_rate_sample(void)
++ath_rate_sample_exit(void)
+ {
+ ieee80211_rate_unregister(&ath_rate_ops);
+ printk(KERN_INFO "%s: unloaded\n", dev_info);
+ }
+-module_exit(exit_ath_rate_sample);
++module_exit(ath_rate_sample_exit);
+--- a/net80211/if_media.h
++++ b/net80211/if_media.h
+@@ -42,6 +42,7 @@
+ #define _NET_IF_MEDIA_H_
+
+ #include <net80211/ieee80211_linux.h>
++#include "symbol.h"
+
+ /*
+ * Prototypes and definitions for BSD/OS-compatible network interface
+--- /dev/null
++++ b/net80211/symbol.h
+@@ -0,0 +1,4 @@
++#ifdef SINGLE_MODULE
++#undef EXPORT_SYMBOL
++#define EXPORT_SYMBOL(...)
++#endif
+--- a/ath_rate/Makefile
++++ b/ath_rate/Makefile
+@@ -1,7 +1,7 @@
+ obj := $(firstword $(obj) $(SUBDIRS) .)
+ TOP = $(obj)/..
+
+-obj-y := amrr/ onoe/ sample/ minstrel/
++obj-y := sample/ minstrel/
+
+ include $(TOP)/Makefile.inc
+
--- /dev/null
+--- a/net80211/ieee80211_node.c
++++ b/net80211/ieee80211_node.c
+@@ -647,8 +647,11 @@ ieee80211_sta_join1(struct ieee80211_nod
+ (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */
+ vap->iv_bss = selbs;
+ IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid);
+- if (obss != NULL)
++ if (obss != NULL) {
++ if (obss->ni_table)
++ ieee80211_node_leave(obss);
+ ieee80211_unref_node(&obss);
++ }
+ ic->ic_bsschan = selbs->ni_chan;
+ ic->ic_curchan = ic->ic_bsschan;
+ ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -1512,14 +1512,13 @@ __ieee80211_newstate(struct ieee80211vap
+ if (arg != 0)
+ ieee80211_scan_assoc_fail(ic,
+ vap->iv_bss->ni_macaddr, arg);
++ ieee80211_node_leave(vap->iv_bss);
+ if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
+ ieee80211_check_scan(vap,
+ IEEE80211_SCAN_ACTIVE,
+ IEEE80211_SCAN_FOREVER,
+ vap->iv_des_nssid, vap->iv_des_ssid,
+ NULL);
+- else
+- ieee80211_node_leave(vap->iv_bss);
+ break;
+ case IEEE80211_S_RUN: /* beacon miss */
+ if (vap->iv_opmode == IEEE80211_M_STA) {
--- /dev/null
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -512,7 +512,7 @@ MODULE_PARM_DESC(ieee80211_debug, "Load-
+ * and use the higher bits as the index of the VAP.
+ */
+ #define ATH_SET_VAP_BSSID_MASK(bssid_mask) \
+- ((bssid_mask)[0] &= ~(((ath_maxvaps-1) << 2) | 0x02))
++ ((bssid_mask)[0] &= ~(((ATH_MAXVAPS_MAX-1) << 2) | 0x02))
+ #define ATH_GET_VAP_ID(bssid) ((bssid)[0] >> 2)
+ #define ATH_SET_VAP_BSSID(bssid, id) \
+ do { \
+@@ -604,8 +604,8 @@ ath_attach(u_int16_t devid, struct net_d
+
+ /* Allocate space for dynamically determined maximum VAP count */
+ sc->sc_bslot =
+- kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL);
+- memset(sc->sc_bslot, 0, ath_maxvaps * sizeof(struct ieee80211vap*));
++ kmalloc(ATH_MAXVAPS_MAX * sizeof(struct ieee80211vap*), GFP_KERNEL);
++ memset(sc->sc_bslot, 0, ATH_MAXVAPS_MAX * sizeof(struct ieee80211vap*));
+
+ /*
+ * Cache line size is used to size and align various
+@@ -1349,11 +1349,8 @@ ath_vap_create(struct ieee80211com *ic,
+ return NULL;
+ }
+
+- if (sc->sc_nvaps >= ath_maxvaps) {
+- EPRINTF(sc, "Too many virtual APs (%d already exist).\n",
+- sc->sc_nvaps);
+- return NULL;
+- }
++ if ((sc->sc_nvaps >= ath_maxvaps) && (ath_maxvaps < ATH_MAXVAPS_MAX))
++ ath_maxvaps++;
+
+ dev = alloc_etherdev(sizeof(struct ath_vap) + sc->sc_rc->arc_vap_space);
+ if (dev == NULL) {
+@@ -1451,11 +1448,11 @@ ath_vap_create(struct ieee80211com *ic,
+ /* Assign the VAP to a beacon xmit slot. As
+ * above, this cannot fail to find one. */
+ avp->av_bslot = 0;
+- for (slot = 0; slot < ath_maxvaps; slot++)
++ for (slot = 0; slot < ATH_MAXVAPS_MAX; slot++)
+ if (sc->sc_bslot[slot] == NULL) {
+ /* XXX: Hack, space out slots to better
+ * deal with misses. */
+- if (slot + 1 < ath_maxvaps &&
++ if (slot + 1 < ATH_MAXVAPS_DEFAULT &&
+ sc->sc_bslot[slot+1] == NULL) {
+ avp->av_bslot = slot + 1;
+ break;
+@@ -1463,11 +1460,16 @@ ath_vap_create(struct ieee80211com *ic,
+ avp->av_bslot = slot;
+ /* NB: keep looking for a double slot */
+ }
+- KASSERT(sc->sc_bslot[avp->av_bslot] == NULL,
+- ("beacon slot %u not empty?", avp->av_bslot));
++
++ /* No beacon slot found? */
++ if (sc->sc_bslot[avp->av_bslot]) {
++ free_netdev(dev);
++ return NULL;
++ }
+ sc->sc_bslot[avp->av_bslot] = vap;
+ sc->sc_nbcnvaps++;
+
++#if 0
+ if ((opmode == IEEE80211_M_HOSTAP) && (sc->sc_hastsfadd)) {
+ /*
+ * Multiple VAPs are to transmit beacons and we
+@@ -1485,6 +1487,9 @@ ath_vap_create(struct ieee80211com *ic,
+ sc->sc_stagbeacons = 1;
+ }
+ }
++#else
++ sc->sc_stagbeacons = sc->sc_hastsfadd;
++#endif
+ DPRINTF(sc, ATH_DEBUG_BEACON, "sc->sc_stagbeacons %sabled\n",
+ (sc->sc_stagbeacons ? "en" : "dis"));
+ }
+@@ -4968,7 +4973,7 @@ ath_beacon_alloc_internal(struct ath_sof
+ * has a timestamp in one beacon interval while the
+ * others get a timestamp aligned to the next interval.
+ */
+- tuadjust = (ni->ni_intval * (ath_maxvaps - avp->av_bslot)) / ath_maxvaps;
++ tuadjust = (ni->ni_intval * (ATH_MAXVAPS_DEFAULT - avp->av_bslot)) / ATH_MAXVAPS_DEFAULT;
+ tsfadjust = cpu_to_le64(tuadjust << 10); /* TU->TSF */
+
+ DPRINTF(sc, ATH_DEBUG_BEACON,
+@@ -5358,21 +5363,40 @@ ath_beacon_send(struct ath_softc *sc, in
+ */
+ if (sc->sc_stagbeacons) { /* staggered beacons */
+ struct ieee80211com *ic = &sc->sc_ic;
++ u_int32_t *bflink = NULL;
+ u_int32_t tsftu;
+
+ tsftu = hw_tsf >> 10; /* NB: 64 -> 32: See note far above. */
+- slot = ((tsftu % ic->ic_lintval) * ath_maxvaps) / ic->ic_lintval;
+- vap = sc->sc_bslot[(slot + 1) % ath_maxvaps];
++ slot = ((tsftu % ic->ic_lintval) * ATH_MAXVAPS_DEFAULT) / ic->ic_lintval;
+ DPRINTF(sc, ATH_DEBUG_BEACON_PROC,
+ "Slot %d [tsf %llu tsftu %llu intval %u] vap %p\n",
+ slot, (unsigned long long)hw_tsf,
+ (unsigned long long)tsftu, ic->ic_lintval, vap);
+ bfaddr = 0;
+- if (vap != NULL) {
++ while (slot < ATH_MAXVAPS_MAX) {
++ vap = sc->sc_bslot[slot];
++ if (vap == NULL)
++ goto next;
++
+ bf = ath_beacon_generate(sc, vap, needmark);
+- if (bf != NULL)
++ if (bf == NULL)
++ break;
++
++ if (bflink != NULL)
++#ifdef AH_NEED_DESC_SWAP
++ *bflink = cpu_to_le32(bf->bf_daddr);
++#else
++ *bflink = bf->bf_daddr;
++#endif
++ else
+ bfaddr = bf->bf_daddr;
++
++ bflink = &bf->bf_desc->ds_link;
++next:
++ slot += ATH_MAXVAPS_DEFAULT;
+ }
++ if (bflink != NULL)
++ *bflink = 0; /* link of last frame */
+ } else { /* burst'd beacons */
+ u_int32_t *bflink = NULL;
+
+@@ -5567,7 +5591,7 @@ ath_beacon_config(struct ath_softc *sc,
+ /* NB: the beacon interval is kept internally in TUs */
+ intval = ic->ic_lintval & HAL_BEACON_PERIOD;
+ if (sc->sc_stagbeacons)
+- intval /= ath_maxvaps; /* for staggered beacons */
++ intval /= ATH_MAXVAPS_DEFAULT; /* for staggered beacons */
+ if ((sc->sc_nostabeacons) &&
+ (vap->iv_opmode == IEEE80211_M_HOSTAP))
+ reset_tsf = 1;
+@@ -5889,7 +5913,7 @@ ath_desc_alloc(struct ath_softc *sc)
+
+ /* XXX allocate beacon state together with VAP */
+ error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf,
+- "beacon", ath_maxvaps, 1);
++ "beacon", ATH_MAXVAPS_MAX, 1);
+ if (error != 0) {
+ ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf,
+ BUS_DMA_TODEVICE);
--- /dev/null
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -3725,6 +3725,7 @@ ff_bypass:
+ */
+ skb = ieee80211_encap(ni, skb, &framecnt);
+ if (skb == NULL) {
++ STAILQ_INSERT_TAIL(&bf_head, bf, bf_list);
+ DPRINTF(sc, ATH_DEBUG_XMIT,
+ "Dropping; encapsulation failure\n");
+ sc->sc_stats.ast_tx_encap++;
--- /dev/null
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -396,7 +396,6 @@ static int tpc = 1;
+ static int maxvaps = -1;
+ static int xchanmode = -1;
+ #include "ath_wprobe.c"
+-static int beacon_cal = 1;
+
+ static const struct ath_hw_detect generic_hw_info = {
+ .vendor_name = "Unknown",
+@@ -431,7 +430,6 @@ static struct notifier_block ath_event_b
+ };
+
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
+-MODULE_PARM(beacon_cal, "i");
+ MODULE_PARM(maxvaps, "i");
+ MODULE_PARM(xchanmode, "i");
+ MODULE_PARM(rfkill, "i");
+@@ -443,7 +441,6 @@ MODULE_PARM(autocreate, "s");
+ MODULE_PARM(ratectl, "s");
+ #else
+ #include <linux/moduleparam.h>
+-module_param(beacon_cal, int, 0600);
+ module_param(maxvaps, int, 0600);
+ module_param(xchanmode, int, 0600);
+ module_param(rfkill, int, 0600);
+@@ -837,6 +834,7 @@ ath_attach(u_int16_t devid, struct net_d
+ error = EIO;
+ goto bad2;
+ }
++ sc->sc_cal_interval = ath_calinterval;
+ init_timer(&sc->sc_cal_ch);
+ sc->sc_cal_ch.function = ath_calibrate;
+ sc->sc_cal_ch.data = (unsigned long) dev;
+@@ -2765,8 +2763,7 @@ ath_stop_locked(struct net_device *dev)
+ }
+ if (!sc->sc_invalid) {
+ del_timer_sync(&sc->sc_dfs_cac_timer);
+- if (!sc->sc_beacon_cal)
+- del_timer_sync(&sc->sc_cal_ch);
++ del_timer_sync(&sc->sc_cal_ch);
+ }
+ ath_draintxq(sc);
+ if (!sc->sc_invalid) {
+@@ -2791,10 +2788,9 @@ static void ath_set_beacon_cal(struct at
+ if (val) {
+ del_timer_sync(&sc->sc_cal_ch);
+ } else {
+- sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
+- add_timer(&sc->sc_cal_ch);
++ mod_timer(&sc->sc_cal_ch, jiffies + (sc->sc_cal_interval * HZ));
+ }
+- sc->sc_beacon_cal = !!val && beacon_cal;
++ sc->sc_beacon_cal = !!val;
+ }
+
+ /*
+@@ -3036,7 +3032,7 @@ ath_reset(struct net_device *dev)
+ * XXX: starting the calibration too early seems to lead to
+ * problems with the beacons.
+ */
+- sc->sc_lastcal = jiffies;
++ sc->sc_nextcal = jiffies + msecs_to_jiffies(sc->sc_cal_interval * 1000);
+
+ /*
+ * Convert to a HAL channel description with the flags
+@@ -5477,10 +5473,9 @@ next:
+ "Invoking ath_hal_txstart with sc_bhalq: %d\n",
+ sc->sc_bhalq);
+ ath_hal_txstart(ah, sc->sc_bhalq);
+- if (sc->sc_beacon_cal && (jiffies > sc->sc_lastcal + (ath_calinterval * HZ))) {
+- sc->sc_cal_ch.expires = jiffies + msecs_to_jiffies(10);
+- add_timer(&sc->sc_cal_ch);
+- }
++ if (sc->sc_beacon_cal && ((sc->sc_bmisscount == 3) ||
++ (jiffies > sc->sc_nextcal)))
++ mod_timer(&sc->sc_cal_ch, jiffies + 1);
+
+ sc->sc_stats.ast_be_xmit++; /* XXX per-VAP? */
+ }
+@@ -9161,6 +9156,7 @@ ath_startrecv(struct ath_softc *sc)
+ dev->mtu, sc->sc_cachelsz, sc->sc_rxbufsize);
+
+ sc->sc_rxlink = NULL;
++ ath_set_beacon_cal(sc, IEEE80211_IS_MODE_BEACON(sc->sc_ic.ic_opmode));
+ STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
+ int error = ath_rxbuf_init(sc, bf);
+ ATH_RXBUF_RESET(bf);
+@@ -9377,7 +9373,7 @@ ath_chan_set(struct ath_softc *sc, struc
+ jiffies + (sc->sc_dfs_cac_period * HZ));
+
+ /* This is a good time to start a calibration */
+- ath_set_beacon_cal(sc, 1);
++ mod_timer(&sc->sc_cal_ch, jiffies + 1);
+ }
+ /*
+ * re configure beacons when it is a turbo mode switch.
+@@ -9471,25 +9467,23 @@ ath_calibrate(unsigned long arg)
+ if (isIQdone == AH_TRUE) {
+ /* Unless user has overridden calibration interval,
+ * upgrade to less frequent calibration */
+- if (ath_calinterval == ATH_SHORT_CALINTERVAL)
+- ath_calinterval = ATH_LONG_CALINTERVAL;
++ if (sc->sc_cal_interval == ATH_SHORT_CALINTERVAL)
++ sc->sc_cal_interval = ATH_LONG_CALINTERVAL;
+ }
+ else {
+ /* Unless user has overridden calibration interval,
+ * downgrade to more frequent calibration */
+- if (ath_calinterval == ATH_LONG_CALINTERVAL)
+- ath_calinterval = ATH_SHORT_CALINTERVAL;
++ if (sc->sc_cal_interval == ATH_LONG_CALINTERVAL)
++ sc->sc_cal_interval = ATH_SHORT_CALINTERVAL;
+ }
+
+ DPRINTF(sc, ATH_DEBUG_CALIBRATE, "Channel %u/%x -- IQ %s.\n",
+ sc->sc_curchan.channel, sc->sc_curchan.channelFlags,
+ isIQdone ? "done" : "not done");
+
+- sc->sc_lastcal = jiffies;
+- if (!sc->sc_beacon_cal) {
+- sc->sc_cal_ch.expires = jiffies + (ath_calinterval * HZ);
+- add_timer(&sc->sc_cal_ch);
+- }
++ sc->sc_nextcal = jiffies + msecs_to_jiffies(sc->sc_cal_interval * 1000);
++ if (!sc->sc_beacon_cal)
++ mod_timer(&sc->sc_cal_ch, sc->sc_nextcal);
+ }
+
+ static void
+@@ -9597,9 +9591,6 @@ ath_newstate(struct ieee80211vap *vap, e
+ ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[nstate]);
+
+- if (!sc->sc_beacon_cal)
+- del_timer(&sc->sc_cal_ch); /* periodic calibration timer */
+-
+ ath_hal_setledstate(ah, leds[nstate]); /* set LED */
+ netif_stop_queue(dev); /* before we do anything else */
+
+@@ -9821,10 +9812,7 @@ ath_newstate(struct ieee80211vap *vap, e
+ IEEE80211_IS_MODE_DFS_MASTER(vap->iv_opmode)) {
+ DPRINTF(sc, ATH_DEBUG_STATE | ATH_DEBUG_DOTH,
+ "VAP -> DFSWAIT_PENDING \n");
+- /* start calibration timer with a really small value
+- * 1/10 sec */
+- if (!sc->sc_beacon_cal)
+- mod_timer(&sc->sc_cal_ch, jiffies + (HZ/10));
++ mod_timer(&sc->sc_cal_ch, jiffies + 1);
+ /* wake the receiver */
+ netif_wake_queue(dev);
+ /* don't do the other usual stuff... */
+@@ -9866,12 +9854,6 @@ done:
+ /* Invoke the parent method to complete the work. */
+ error = avp->av_newstate(vap, nstate, arg);
+
+- /* Finally, start any timers. */
+- if (nstate == IEEE80211_S_RUN && !sc->sc_beacon_cal) {
+- /* start periodic recalibration timer */
+- mod_timer(&sc->sc_cal_ch, jiffies + (ath_calinterval * HZ));
+- }
+-
+ #ifdef ATH_SUPERG_XR
+ if (vap->iv_flags & IEEE80211_F_XR &&
+ nstate == IEEE80211_S_RUN)
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -834,7 +834,8 @@ struct ath_softc {
+
+ struct ieee80211_channel *sc_last_chan;
+ int sc_beacon_cal; /* use beacon timer for calibration */
+- u_int64_t sc_lastcal; /* last time the calibration was performed */
++ u_int64_t sc_nextcal; /* last time the calibration was performed */
++ int sc_cal_interval; /* current calibration interval */
+ struct timer_list sc_cal_ch; /* calibration timer */
+ HAL_NODE_STATS sc_halstats; /* station-mode rssi stats */
+