PKG_REV:=3314
PKG_VERSION:=r$(PKG_REV)
-PKG_RELEASE:=1.1
+PKG_RELEASE:=2
PKG_SOURCE_PROTO:=svn
PKG_SOURCE_VERSION:=$(PKG_REV)
PATCH_DIR=./patches
+HAL_VERSION:=20090508
+HAL_FILE:=ath_hal-$(HAL_VERSION).tgz
+HAL_MD5SUM:=4ab7ae8bdb96c0be388c98bf8f92d5ca
+
PKG_BUILD_DEPENDS:=wprobe
include $(INCLUDE_DIR)/package.mk
+COMPRESSION:=1
+
+define Download/hal
+ FILE:=$(HAL_FILE)
+ URL:=http://mirror2.openwrt.org/sources
+ MD5SUM:=$(HAL_MD5SUM)
+endef
+$(eval $(call Download,hal))
+
+
ifneq ($(CONFIG_TARGET_atheros),)
BUS:=AHB
else
MADWIFI_AUTOLOAD+= ath_pci
endif
-MADWIFI_APPLETS:=80211stats athchans athctrl athkey athstats wlanconfig ath_info
+MADWIFI_APPLETS:=80211stats athchans athkey athstats wlanconfig ath_info
ifdef CONFIG_MADWIFI_DEBUG
MADWIFI_APPLETS += athdebug 80211debug
endif
MAKE_ARGS:= \
PATH="$(TARGET_PATH)" \
ARCH="$(LINUX_KARCH)" \
+ ARCH-y="$(LINUX_KARCH)" \
CROSS_COMPILE="$(TARGET_CROSS)" \
TARGET="$(HAL_TARGET)" \
TOOLPREFIX="$(KERNEL_CROSS)" \
KERNELPATH="$(LINUX_DIR)" \
LDOPTS="--no-warn-mismatch " \
ATH_RATE="ath_rate/$(RATE_CONTROL)" \
+ ATH_CAP_SUPERG_COMP="$(COMPRESSION)" \
DO_MULTI=1 \
INCS="$(MADWIFI_INC)" \
$(if $(CONFIG_MADWIFI_DEBUG),,DEBUG=) WARNINGS="-Wno-unused"
COPTS="-DCONFIG_ATHEROS_RATE_DEFAULT='\"$(RATE_CONTROL)\"' -DATH_REVERSE_ENGINEERING=1" \
ifeq ($(CONFIG_MADWIFI_UPSTREAM),)
- HALFILE:=$(lastword $(sort $(wildcard ./ath_hal-*.tgz)))
-endif
-
-ifneq ($(HALFILE),)
define Build/Prepare/HAL
rm -rf $(PKG_BUILD_DIR)/tmp
mkdir -p $(PKG_BUILD_DIR)/tmp
- tar xvzf $(HALFILE) -C $(PKG_BUILD_DIR)/tmp
+ tar xvzf $(DL_DIR)/$(HAL_FILE) -C $(PKG_BUILD_DIR)/tmp
$(CP) $(PKG_BUILD_DIR)/tmp/ath_hal*/* $(PKG_BUILD_DIR)/hal/
rm -rf $(PKG_BUILD_DIR)/tmp
endef
struct ieee80211_spy iv_spy; /* IWSPY support */
struct ieee80211_app_ie app_ie[IEEE80211_APPIE_NUM_OF_FRAME]; /* app-specified IEs by frame type */
u_int32_t app_filter; /* filters which management frames are forwarded to app */
-+ int iv_maxrateindex;
++ u_int iv_maxrateindex;
};
/* Debug functions need the defintion of struct ieee80211vap because iv_debug
IEEE80211_PARAM_BEACON_MISS_THRESH = 73, /* Beacon miss threshold (in beacons) */
IEEE80211_PARAM_BEACON_MISS_THRESH_MS = 74, /* Beacon miss threshold (in ms) */
IEEE80211_PARAM_MAXRATE = 75, /* Maximum rate (by table index) */
-+ IEEE80211_PARAM_MINRATE = 76, /* Maximum rate (by table index) */
++ IEEE80211_PARAM_MINRATE = 76, /* Minimum rate (by table index) */
};
#define SIOCG80211STATS (SIOCDEVPRIVATE+2)
@@ -282,6 +282,7 @@ struct ieee80211vap {
struct ieee80211_app_ie app_ie[IEEE80211_APPIE_NUM_OF_FRAME]; /* app-specified IEs by frame type */
u_int32_t app_filter; /* filters which management frames are forwarded to app */
- int iv_maxrateindex;
-+ int iv_minrateindex;
+ u_int iv_maxrateindex;
++ u_int iv_minrateindex;
};
/* Debug functions need the defintion of struct ieee80211vap because iv_debug
@@ -643,6 +643,8 @@ enum {
IEEE80211_PARAM_BEACON_MISS_THRESH_MS = 74, /* Beacon miss threshold (in ms) */
IEEE80211_PARAM_MAXRATE = 75, /* Maximum rate (by table index) */
- IEEE80211_PARAM_MINRATE = 76, /* Maximum rate (by table index) */
+ IEEE80211_PARAM_MINRATE = 76, /* Minimum rate (by table index) */
+ IEEE80211_PARAM_PROTMODE_RSSI = 77, /* RSSI Threshold for enabling protection mode */
+ IEEE80211_PARAM_PROTMODE_TIMEOUT = 78, /* Timeout for expiring protection mode */
};
--- a/net80211/ieee80211_ioctl.h
+++ b/net80211/ieee80211_ioctl.h
@@ -646,6 +646,7 @@ enum {
- IEEE80211_PARAM_MINRATE = 76, /* Maximum rate (by table index) */
+ IEEE80211_PARAM_MINRATE = 76, /* Minimum rate (by table index) */
IEEE80211_PARAM_PROTMODE_RSSI = 77, /* RSSI Threshold for enabling protection mode */
IEEE80211_PARAM_PROTMODE_TIMEOUT = 78, /* Timeout for expiring protection mode */
+ IEEE80211_PARAM_BGSCAN_THRESH = 79, /* bg scan rssi threshold */
sc->sc_curchan.channel = ic->ic_curchan->ic_freq;
sc->sc_curchan.channelFlags = ath_chan2flags(ic->ic_curchan);
if (!ath_hal_reset(ah, sc->sc_opmode, &sc->sc_curchan, AH_FALSE, &status)) {
-@@ -2914,6 +2916,40 @@ ath_hw_check_atim(struct ath_softc *sc,
+@@ -2913,6 +2915,48 @@ ath_hw_check_atim(struct ath_softc *sc,
+ return 0;
}
-
++#define AR5K_MIBC 0x0040
++#define AR5K_MIBC_FREEZE (1 << 1)
++#define AR5K_TXFC 0x80ec
++#define AR5K_RXFC 0x80f0
+#define AR5K_RXCLEAR 0x80f4
+#define AR5K_CYCLES 0x80f8
+static void
+ if (!ic->ic_curchan || (ic->ic_curchan == IEEE80211_CHAN_ANYC))
+ return;
+
++ OS_REG_WRITE(ah, AR5K_MIBC, AR5K_MIBC_FREEZE);
+ rx = OS_REG_READ(ah, AR5K_RXCLEAR);
+ cc = OS_REG_READ(ah, AR5K_CYCLES);
++
+ if (!cc)
+ return;
+
+ if (rx > cc)
-+ return; /* wraparound */
++ return; /* should not happen */
+
+ if (sc->sc_last_chan)
+ sc->sc_last_chan->ic_idletime = 100 * (cc - rx) / cc;
+
+ OS_REG_WRITE(ah, AR5K_RXCLEAR, 0);
+ OS_REG_WRITE(ah, AR5K_CYCLES, 0);
++ OS_REG_WRITE(ah, AR5K_TXFC, 0);
++ OS_REG_WRITE(ah, AR5K_RXFC, 0);
++ OS_REG_WRITE(ah, AR5K_MIBC, 0);
+}
+#undef AR5K_RXCLEAR
+#undef AR5K_CYCLES
-+
+
/*
* Reset the hardware w/o losing operational state. This is
- * basically a more efficient way of doing ath_stop, ath_init,
-@@ -2940,6 +2976,7 @@ ath_reset(struct net_device *dev)
+@@ -2940,6 +2984,7 @@ ath_reset(struct net_device *dev)
* Convert to a HAL channel description with the flags
* constrained to reflect the current operating mode.
*/
c = ic->ic_curchan;
sc->sc_curchan.channel = c->ic_freq;
sc->sc_curchan.channelFlags = ath_chan2flags(c);
-@@ -9022,6 +9059,7 @@ ath_chan_set(struct ath_softc *sc, struc
+@@ -9022,6 +9067,7 @@ ath_chan_set(struct ath_softc *sc, struc
u_int8_t channel_change_required = 0;
struct timeval tv;
-+ ath_fetch_idle_time(sc);
++
/*
* Convert to a HAL channel description with
* the flags constrained to reflect the current
+@@ -9030,6 +9076,14 @@ ath_chan_set(struct ath_softc *sc, struc
+ memset(&hchan, 0, sizeof(HAL_CHANNEL));
+ hchan.channel = chan->ic_freq;
+ hchan.channelFlags = ath_chan2flags(chan);
++
++ /* don't do duplicate channel changes, but do
++ * store the available idle time */
++ ath_fetch_idle_time(sc);
++ if ((sc->sc_curchan.channel == hchan.channel) &&
++ (sc->sc_curchan.channelFlags == hchan.channelFlags))
++ return 0;
++
+ KASSERT(hchan.channel != 0,
+ ("bogus channel %u/0x%x", hchan.channel, hchan.channelFlags));
+ do_gettimeofday(&tv);
--- a/ath/if_athvar.h
+++ b/ath/if_athvar.h
@@ -773,6 +773,7 @@ struct ath_softc {
EVALUATE_CRITERION(sc, ic, a, b);
/* XXX: rssi useless? pick_channel evaluates it anyway */
EVALUATE_CRITERION(rssi, params->ss->ss_priv, a, b);
+@@ -519,16 +533,9 @@ pick_channel(struct ieee80211_scan_state
+ #endif
+
+ best = NULL;
+- best_rssi = 0xff; /* If signal is bigger than 0xff, we'd be melting. */
+
+ for (i = 0; i < ss_last; i++) {
+ c = &chans[i];
+- benefit = best_rssi - as->as_maxrssi[c->chan->ic_ieee];
+- sta_assoc = ic->ic_sta_assoc;
+-
+- /* Don't switch... */
+- if (benefit <= 0)
+- continue;
+
+ /* Verify channel is not marked for non-occupancy */
+ if (IEEE80211_IS_CHAN_RADAR(c->chan))
+@@ -546,31 +553,8 @@ pick_channel(struct ieee80211_scan_state
+ break;
+ }
+
+- if (sta_assoc != 0) {
+- int sl = ic->ic_cn_total -
+- ic->ic_chan_nodes[c->chan->ic_ieee]; /* count */
+- if (ic->ic_sc_algorithm == IEEE80211_SC_LOOSE) {
+- int sl_max = ic->ic_sc_sldg * benefit;
+- sl = 1000 * sl / sta_assoc; /* permil */
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+- "%s: chan %d, dB gained: %d, "
+- "STAs lost: %d permil (max %d)\n",
+- __func__, c->chan->ic_ieee,
+- benefit, sl, sl_max);
+- if (sl > sl_max)
+- continue;
+- } else if (((ic->ic_sc_algorithm ==
+- IEEE80211_SC_TIGHT) ||
+- (ic->ic_sc_algorithm ==
+- IEEE80211_SC_STRICT)) &&
+- (sl > 0)) {
+- /* Break the loop as the subsequent chans
+- * won't be better. */
+- break;
+- }
+- }
+ best = c->chan;
+- best_rssi = as->as_maxrssi[best->ic_ieee];
++ break;
+ }
+
+ if (best != NULL) {
+@@ -599,6 +583,9 @@ ap_end(struct ieee80211_scan_state *ss,
+ ("wrong opmode %u", vap->iv_opmode));
+
+ ic = vap->iv_ic;
++
++ /* record stats for the channel that was scanned last */
++ ic->ic_set_channel(ic);
+ bestchan = pick_channel(ss, vap, flags);
+ if (bestchan == NULL) {
+ if (ss->ss_last > 0) {
+--- a/net80211/ieee80211_scan.c
++++ b/net80211/ieee80211_scan.c
+@@ -1002,20 +1002,34 @@ ieee80211_scan_add_channels(struct ieee8
+ {
+ struct ieee80211_channel *c, *cg;
+ u_int modeflags;
++ int has_non_turbo = 0;
+ int i;
+
+ KASSERT(mode < ARRAY_SIZE(chanflags), ("Unexpected mode %u", mode));
+ modeflags = chanflags[mode];
+ for (i = 0; i < ic->ic_nchans; i++) {
+ c = &ic->ic_channels[i];
++ if (c->ic_flags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO))
++ continue;
++
++ has_non_turbo = 1;
++ break;
++ }
++ for (i = 0; i < ic->ic_nchans; i++) {
++ c = &ic->ic_channels[i];
+ if (c == NULL || isclr(ic->ic_chan_active, c->ic_ieee))
+ continue;
+ if (c->ic_scanflags & IEEE80211_NOSCAN_SET)
+ continue;
+- if (modeflags &&
+- ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
+- (modeflags & IEEE80211_CHAN_ALLTURBO)))
+- continue;
++ if (modeflags) {
++ if ((c->ic_flags & IEEE80211_CHAN_ALLTURBO) !=
++ (modeflags & IEEE80211_CHAN_ALLTURBO))
++ continue;
++ } else if (has_non_turbo) {
++ if ((ss->ss_vap->iv_opmode == IEEE80211_M_HOSTAP) &&
++ (c->ic_flags & (IEEE80211_CHAN_TURBO | IEEE80211_CHAN_STURBO)))
++ continue;
++ }
+ if (mode == IEEE80211_MODE_AUTO) {
+ /*
+ * XXX special-case 11b/g channels so we select
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
-@@ -6580,9 +6580,8 @@ ath_recv_mgmt(struct ieee80211vap * vap,
+@@ -6588,9 +6588,8 @@ ath_recv_mgmt(struct ieee80211vap * vap,
sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
(const struct ieee80211_frame_min *)skb->data);
if (ni == NULL) {
DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
-@@ -6737,7 +6736,9 @@ ath_rx_poll(struct net_device *dev, int
+@@ -6745,7 +6744,9 @@ ath_rx_poll(struct net_device *dev, int
struct ath_desc *ds;
struct ath_rx_status *rs;
struct sk_buff *skb = NULL;
unsigned int len;
int type;
u_int phyerr;
-@@ -6892,12 +6893,15 @@ rx_accept:
+@@ -6900,12 +6901,15 @@ rx_accept:
skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
if (mic_fail) {
if (ni && ni->ni_table) {
ieee80211_check_mic(ni, skb);
-@@ -6959,11 +6963,24 @@ drop_micfail:
+@@ -6967,11 +6971,24 @@ drop_micfail:
* for its use. If the sender is unknown spam the
* frame; it'll be dropped where it's not wanted.
*/
ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
ieee80211_unref_node(&ni);
-@@ -6972,24 +6989,35 @@ drop_micfail:
+@@ -6980,24 +6997,35 @@ drop_micfail:
* No key index or no entry, do a lookup and
* add the node to the mapping table if possible.
*/
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
-@@ -13511,7 +13511,7 @@ cleanup_ath_buf(struct ath_softc *sc, st
+@@ -13527,7 +13527,7 @@ cleanup_ath_buf(struct ath_softc *sc, st
bus_unmap_single(
sc->sc_bdev,
bf->bf_skbaddrff[i],
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
-@@ -6725,10 +6725,10 @@ ath_rx_poll(struct net_device *dev, int
+@@ -6733,10 +6733,10 @@ ath_rx_poll(struct net_device *dev, int
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
struct ath_softc *sc = container_of(napi, struct ath_softc, sc_napi);
struct net_device *dev = sc->sc_dev;
#endif
struct ath_buf *bf;
struct ieee80211com *ic = &sc->sc_ic;
-@@ -6771,13 +6771,15 @@ process_rx_again:
+@@ -6779,13 +6779,15 @@ process_rx_again:
break;
}
skb = bf->bf_skb;
if (skb == NULL) {
-@@ -7061,8 +7063,8 @@ rx_next:
+@@ -7069,8 +7071,8 @@ rx_next:
if (sc->sc_isr & HAL_INT_RX) {
u_int64_t hw_tsf = ath_hal_gettsf64(ah);
sc->sc_isr &= ~HAL_INT_RX;
/*
* Check if the MAC has multi-rate retry support.
* We do this by trying to setup a fake extended
-@@ -7555,7 +7563,7 @@ ath_txq_setup(struct ath_softc *sc, int
+@@ -7563,7 +7571,7 @@ ath_txq_setup(struct ath_softc *sc, int
if (qtype == HAL_TX_QUEUE_UAPSD)
qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE;
else
/*
* The functions in this section are not intended to be invoked by MadWifi
+--- a/ath/if_ath_hal.h
++++ b/ath/if_ath_hal.h
+@@ -778,17 +778,6 @@ static inline HAL_STATUS ath_hal_getcapa
+ return ret;
+ }
+
+-static inline HAL_BOOL ath_hal_radar_wait(struct ath_hal *ah, HAL_CHANNEL *a1)
+-{
+- HAL_BOOL ret;
+- ATH_HAL_LOCK_IRQ(ah->ah_sc);
+- ath_hal_set_function(__func__);
+- ret = ah->ah_radarWait(ah, a1);
+- ath_hal_set_function(NULL);
+- ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
+- return ret;
+-}
+-
+ static inline HAL_BOOL ath_hal_setmcastfilterindex(struct ath_hal *ah,
+ u_int32_t index)
+ {
+@@ -1268,8 +1257,6 @@ static inline void ath_hal_dump_map(stru
+ /* HAL_STATUS ah_getCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE a1, u_int32_t capability, u_int32_t *result) */
+ __print_symbol("%s=ah_getCapability\n",
+ (unsigned long)ah->ah_getCapability);
+- /* HAL_BOOL ah_radarWait(struct ath_hal *ah, HAL_CHANNEL *a1) */
+- __print_symbol("%s=ah_radarWait\n", (unsigned long)ah->ah_radarWait);
+ /* HAL_BOOL ah_setMulticastFilterIndex(struct ath_hal *ah, u_int32_t index) */
+ __print_symbol("%s=ah_setMulticastFilterIndex\n",
+ (unsigned long)ah->ah_setMulticastFilterIndex);
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
-@@ -6521,7 +6521,7 @@ ath_capture(struct net_device *dev, cons
+@@ -6529,7 +6529,7 @@ ath_capture(struct net_device *dev, cons
/* Never copy the SKB, as it is ours on the RX side, and this is the
* last process on the TX side and we only modify our own headers. */
if (tskb == NULL) {
DPRINTF(sc, ATH_DEBUG_ANY,
"Dropping; ath_skb_removepad failed!\n");
-@@ -6529,6 +6529,8 @@ ath_capture(struct net_device *dev, cons
+@@ -6537,6 +6537,8 @@ ath_capture(struct net_device *dev, cons
}
ieee80211_input_monitor(ic, tskb, bf, tx, tsf, sc);
Please let us know if you think your name should be mentioned here!
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
-@@ -3138,7 +3138,7 @@ ath_tx_startraw(struct net_device *dev,
+@@ -3146,7 +3146,7 @@ ath_tx_startraw(struct net_device *dev,
struct ath_softc *sc = dev->priv;
struct ath_hal *ah = sc->sc_ah;
struct ieee80211_phy_params *ph = (struct ieee80211_phy_params *)
+ else
+ bias += get_overlap(ch->freq, c->ic_freq, ch->bw, bw);
+ }
-+ return min(bias, (u32) 100);
++ return bias;
+}
+EXPORT_SYMBOL(ieee80211_scan_get_bias);
+
void
ieee80211_scan_attach(struct ieee80211com *ic)
{
-@@ -1155,7 +1272,7 @@ ieee80211_scan_dfs_action(struct ieee802
+@@ -1169,7 +1286,7 @@ ieee80211_scan_dfs_action(struct ieee802
IEEE80211_RADAR_CHANCHANGE_TBTT_COUNT;
ic->ic_flags |= IEEE80211_F_CHANSWITCH;
} else {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
"%s: directly switching to channel "
"%3d (%4d MHz)\n", __func__,
-@@ -1166,6 +1283,9 @@ ieee80211_scan_dfs_action(struct ieee802
+@@ -1180,6 +1297,9 @@ ieee80211_scan_dfs_action(struct ieee802
* change the channel here. */
change_channel(ic, new_channel);
ic->ic_bsschan = new_channel;
}
-@@ -605,6 +613,7 @@ ap_end(struct ieee80211_scan_state *ss,
+@@ -575,6 +583,7 @@ ap_end(struct ieee80211_scan_state *ss,
struct ap_state *as = ss->ss_priv;
struct ieee80211_channel *bestchan = NULL;
struct ieee80211com *ic = NULL;
int res = 1;
SCAN_AP_LOCK_IRQ(as);
-@@ -613,8 +622,11 @@ ap_end(struct ieee80211_scan_state *ss,
- ("wrong opmode %u", vap->iv_opmode));
+@@ -586,8 +595,11 @@ ap_end(struct ieee80211_scan_state *ss,
- ic = vap->iv_ic;
+ /* record stats for the channel that was scanned last */
+ ic->ic_set_channel(ic);
+ spin_lock_irqsave(&channel_lock, sflags);
+ ieee80211_scan_set_bss_channel(ic, NULL);
bestchan = pick_channel(ss, vap, flags);
if (ss->ss_last > 0) {
/* no suitable channel, should not happen */
printk(KERN_ERR "%s: %s: no suitable channel! "
-@@ -633,6 +645,7 @@ ap_end(struct ieee80211_scan_state *ss,
+@@ -606,6 +618,7 @@ ap_end(struct ieee80211_scan_state *ss,
bestchan->ic_freq, bestchan->ic_flags &
~IEEE80211_CHAN_TURBO)) == NULL) {
/* should never happen ?? */
SCAN_AP_UNLOCK_IRQ_EARLY(as);
return 0;
}
-@@ -645,6 +658,9 @@ ap_end(struct ieee80211_scan_state *ss,
+@@ -618,6 +631,9 @@ ap_end(struct ieee80211_scan_state *ss,
as->as_action = action;
as->as_selbss = se;
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
-@@ -3675,6 +3675,7 @@ ff_bypass:
+@@ -3683,6 +3683,7 @@ ff_bypass:
* already alloc'd
*/
ATH_TXBUF_LOCK_IRQ(sc);
static void ath_poll_disable(struct net_device *dev);
static void ath_poll_enable(struct net_device *dev);
-@@ -3159,7 +3158,7 @@ ath_tx_startraw(struct net_device *dev,
+@@ -3167,7 +3166,7 @@ ath_tx_startraw(struct net_device *dev,
try0 = ph->try0;
rt = sc->sc_currates;
txrate = dot11_to_ratecode(sc, rt, ph->rate0);
hdrlen = ieee80211_anyhdrsize(wh);
pktlen = skb->len + IEEE80211_CRC_LEN;
-@@ -8381,7 +8380,7 @@ ath_tx_start(struct net_device *dev, str
+@@ -8389,7 +8388,7 @@ ath_tx_start(struct net_device *dev, str
pktlen, /* packet length */
hdrlen, /* header length */
atype, /* Atheros packet type */
txrate, try0, /* series 0 rate/tries */
keyix, /* key cache index */
antenna, /* antenna mode */
-@@ -10364,59 +10363,16 @@ ath_get_clamped_maxtxpower(struct ath_so
+@@ -10380,59 +10379,16 @@ ath_get_clamped_maxtxpower(struct ath_so
/* XXX: this function needs some locking to avoid being called
* twice/interrupted */
/* NB: memory is reclaimed through dev->destructor callback */
if (decrease)
sc->sc_nvaps--;
-@@ -5931,6 +5934,7 @@ ath_node_cleanup(struct ieee80211_node *
+@@ -5939,6 +5942,7 @@ ath_node_cleanup(struct ieee80211_node *
/* Clean up node-specific rate things - this currently appears to
* always be a no-op */
sc->sc_rc->ops->node_cleanup(sc, ATH_NODE(ni));
ATH_NODE_UAPSD_LOCK_IRQ(an);
#ifdef IEEE80211_DEBUG_REFCNT
-@@ -7001,6 +7005,8 @@ drop_micfail:
+@@ -7009,6 +7013,8 @@ drop_micfail:
goto lookup_slowpath;
}
ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
ieee80211_unref_node(&ni);
} else {
-@@ -7011,15 +7017,22 @@ drop_micfail:
+@@ -7019,15 +7025,22 @@ drop_micfail:
lookup_slowpath:
vap = ieee80211_find_rxvap(ic, wh->i_addr1);
type = ieee80211_input(vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
/*
* If the station has a key cache slot assigned
-@@ -8599,6 +8612,7 @@ ath_tx_processq(struct ath_softc *sc, st
+@@ -8607,6 +8620,7 @@ ath_tx_processq(struct ath_softc *sc, st
sc->sc_stats.ast_tx_rssi = ts->ts_rssi;
ATH_RSSI_LPF(an->an_halstats.ns_avgtxrssi,
ts->ts_rssi);
if (bf->bf_skb->priority == WME_AC_VO ||
bf->bf_skb->priority == WME_AC_VI)
ni->ni_ic->ic_wme.wme_hipri_traffic++;
-@@ -10090,6 +10104,7 @@ ath_newassoc(struct ieee80211_node *ni,
+@@ -10106,6 +10120,7 @@ ath_newassoc(struct ieee80211_node *ni,
struct ath_softc *sc = ic->ic_dev->priv;
sc->sc_rc->ops->newassoc(sc, ATH_NODE(ni), isnew);
static int countrycode = -1;
static int maxvaps = -1;
static int outdoor = -1;
-@@ -4923,6 +4923,7 @@ ath_beacon_setup(struct ath_softc *sc, s
+@@ -4931,6 +4931,7 @@ ath_beacon_setup(struct ath_softc *sc, s
(((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
== IEEE80211_F_SHPREAMBLE)
struct ieee80211com *ic = bf->bf_node->ni_ic;
struct sk_buff *skb = bf->bf_skb;
struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds;
-@@ -4990,7 +4991,7 @@ ath_beacon_setup(struct ath_softc *sc, s
+@@ -4998,7 +4999,7 @@ ath_beacon_setup(struct ath_softc *sc, s
skb->len + IEEE80211_CRC_LEN, /* frame length */
sizeof(struct ieee80211_frame), /* header length */
HAL_PKT_TYPE_BEACON, /* Atheros packet type */
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
-@@ -13477,7 +13477,7 @@ cleanup_ath_buf(struct ath_softc *sc, st
+@@ -13493,7 +13493,7 @@ cleanup_ath_buf(struct ath_softc *sc, st
if (bf == NULL)
return bf;
bus_unmap_single(
sc->sc_bdev,
bf->bf_skbaddr,
-@@ -13485,8 +13485,6 @@ cleanup_ath_buf(struct ath_softc *sc, st
+@@ -13501,8 +13501,6 @@ cleanup_ath_buf(struct ath_softc *sc, st
sc->sc_rxbufsize : bf->bf_skb->len),
direction);
bf->bf_skbaddr = 0;
/*
* Setup the hardware after reset: the key cache
* is filled as needed and the receive engine is
-@@ -3010,7 +3006,6 @@ ath_reset(struct net_device *dev)
+@@ -3018,7 +3014,6 @@ ath_reset(struct net_device *dev)
ath_setintmit(sc);
ath_update_txpow(sc); /* update tx power state */
ath_radar_update(sc);
if (ath_startrecv(sc) != 0) /* restart recv */
EPRINTF(sc, "Unable to start receive logic.\n");
if (sc->sc_softled)
-@@ -5344,27 +5339,6 @@ ath_beacon_send(struct ath_softc *sc, in
+@@ -5352,27 +5347,6 @@ ath_beacon_send(struct ath_softc *sc, in
} else if ((sc->sc_updateslot == COMMIT) && (sc->sc_slotupdate == slot))
ath_setslottime(sc); /* commit change to hardware */
if (bfaddr != 0) {
/*
* Stop any current DMA and put the new frame(s) on the queue.
-@@ -6725,9 +6699,8 @@ ath_setdefantenna(struct ath_softc *sc,
+@@ -6733,9 +6707,8 @@ ath_setdefantenna(struct ath_softc *sc,
{
struct ath_hal *ah = sc->sc_ah;
if (sc->sc_defant != antenna)
sc->sc_stats.ast_ant_defswitch++;
sc->sc_defant = antenna;
-@@ -11138,7 +11111,7 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+@@ -11154,7 +11127,7 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
break;
}
sc->sc_diversity = val;
#ifdef ATH_SUPERG_XR
ic->ic_ath_cap |= (ath_hal_xrsupported(ah) ? IEEE80211_ATHC_XR : 0);
#endif
-@@ -4461,17 +4477,17 @@ ath_mode_init(struct net_device *dev)
+@@ -4469,17 +4485,17 @@ ath_mode_init(struct net_device *dev)
* Set the slot time based on the current setting.
*/
static void
sc->sc_updateslot = OK;
}
-@@ -4493,7 +4509,7 @@ ath_updateslot(struct net_device *dev)
+@@ -4501,7 +4517,7 @@ ath_updateslot(struct net_device *dev)
if (ic->ic_opmode == IEEE80211_M_HOSTAP)
sc->sc_updateslot = UPDATE;
else if (dev->flags & IFF_RUNNING)
}
#ifdef ATH_SUPERG_DYNTURBO
-@@ -5337,7 +5353,7 @@ ath_beacon_send(struct ath_softc *sc, in
+@@ -5345,7 +5361,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))
if (bfaddr != 0) {
/*
-@@ -7790,12 +7806,14 @@ ath_get_ivlen(struct ieee80211_key *k)
+@@ -7798,12 +7814,14 @@ ath_get_ivlen(struct ieee80211_key *k)
* Get transmit rate index using rate in Kbps
*/
static __inline int
ndx = i;
break;
}
-@@ -8088,7 +8106,7 @@ ath_tx_start(struct net_device *dev, str
+@@ -8096,7 +8114,7 @@ ath_tx_start(struct net_device *dev, str
atype = HAL_PKT_TYPE_NORMAL; /* default */
if (ismcast) {
txrate = rt->info[rix].rateCode;
if (shortPreamble)
txrate |= rt->info[rix].shortPreamble;
-@@ -9055,7 +9073,7 @@ ath_chan_change(struct ath_softc *sc, st
+@@ -9063,7 +9081,7 @@ ath_chan_change(struct ath_softc *sc, st
struct net_device *dev = sc->sc_dev;
enum ieee80211_phymode mode;
ath_rate_setup(dev, mode);
ath_setcurmode(sc, mode);
-@@ -10104,8 +10122,7 @@ ath_newassoc(struct ieee80211_node *ni,
+@@ -10120,8 +10138,7 @@ ath_newassoc(struct ieee80211_node *ni,
}
static int
{
struct ath_softc *sc = dev->priv;
struct ieee80211com *ic = &sc->sc_ic;
-@@ -10119,17 +10136,31 @@ ath_getchannels(struct net_device *dev,
+@@ -10135,17 +10152,31 @@ ath_getchannels(struct net_device *dev,
EPRINTF(sc, "Insufficient memory for channel table!\n");
return -ENOMEM;
}
/*
* Convert HAL channels to ieee80211 ones.
*/
-@@ -10373,7 +10404,7 @@ ath_xr_rate_setup(struct net_device *dev
+@@ -10389,7 +10420,7 @@ ath_xr_rate_setup(struct net_device *dev
struct ieee80211com *ic = &sc->sc_ic;
const HAL_RATE_TABLE *rt;
struct ieee80211_rateset *rs;
sc->sc_xr_rates = ath_hal_getratetable(ah, HAL_MODE_XR);
rt = sc->sc_xr_rates;
if (rt == NULL)
-@@ -10386,57 +10417,16 @@ ath_xr_rate_setup(struct net_device *dev
+@@ -10402,57 +10433,16 @@ ath_xr_rate_setup(struct net_device *dev
} else
maxrates = rt->rateCount;
rs = &ic->ic_sup_xr_rates;
static int
ath_rate_setup(struct net_device *dev, u_int mode)
{
-@@ -10445,7 +10435,7 @@ ath_rate_setup(struct net_device *dev, u
+@@ -10461,7 +10451,7 @@ ath_rate_setup(struct net_device *dev, u
struct ieee80211com *ic = &sc->sc_ic;
const HAL_RATE_TABLE *rt;
struct ieee80211_rateset *rs;
switch (mode) {
case IEEE80211_MODE_11A:
-@@ -10463,6 +10453,12 @@ ath_rate_setup(struct net_device *dev, u
+@@ -10479,6 +10469,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;
default:
DPRINTF(sc, ATH_DEBUG_ANY, "Invalid mode %u\n", mode);
return 0;
-@@ -10477,10 +10473,16 @@ ath_rate_setup(struct net_device *dev, u
+@@ -10493,10 +10489,16 @@ ath_rate_setup(struct net_device *dev, u
maxrates = IEEE80211_RATE_MAXSIZE;
} else
maxrates = rt->rateCount;
return 1;
}
-@@ -10509,13 +10511,18 @@ ath_setcurmode(struct ath_softc *sc, enu
+@@ -10525,13 +10527,18 @@ ath_setcurmode(struct ath_softc *sc, enu
{ 0, 500, 130 },
};
const HAL_RATE_TABLE *rt;
memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap));
for (i = 0; i < 32; i++) {
u_int8_t ix = rt->rateCodeToIndex[i];
-@@ -10525,7 +10532,7 @@ ath_setcurmode(struct ath_softc *sc, enu
+@@ -10541,7 +10548,7 @@ ath_setcurmode(struct ath_softc *sc, enu
continue;
}
sc->sc_hwmap[i].ieeerate =
if (rt->info[ix].shortPreamble ||
rt->info[ix].phy == IEEE80211_T_OFDM)
sc->sc_hwmap[i].flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
-@@ -10926,9 +10933,106 @@ enum {
+@@ -10942,9 +10949,106 @@ enum {
ATH_MAXVAPS = 26,
ATH_INTMIT = 27,
ATH_NOISE_IMMUNITY = 28,
static int
ath_sysctl_set_intmit(struct ath_softc *sc, long ctl, u_int val)
{
-@@ -11007,6 +11111,7 @@ static int
+@@ -11023,6 +11127,7 @@ static int
ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
{
struct ath_softc *sc = ctl->extra1;
struct ath_hal *ah = sc->sc_ah;
u_int val;
u_int tab_3_val[3];
-@@ -11030,25 +11135,34 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+@@ -11046,25 +11151,34 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
lenp, ppos);
if (ret == 0) {
switch ((long)ctl->extra2) {
break;
case ATH_SOFTLED:
if (val != sc->sc_softled) {
-@@ -11201,6 +11315,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+@@ -11217,6 +11331,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
}
} else {
switch ((long)ctl->extra2) {
case ATH_SLOTTIME:
val = ath_hal_getslottime(ah);
break;
-@@ -11219,6 +11336,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+@@ -11235,6 +11352,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
case ATH_COUNTRYCODE:
ath_hal_getcountrycode(ah, &val);
break;
case ATH_MAXVAPS:
val = ath_maxvaps;
break;
-@@ -11332,11 +11452,17 @@ static const ctl_table ath_sysctl_templa
+@@ -11348,11 +11468,17 @@ static const ctl_table ath_sysctl_templa
},
{ .ctl_name = CTL_AUTO,
.procname = "countrycode",
.procname = "maxvaps",
.mode = 0444,
.proc_handler = ath_sysctl_halparam,
-@@ -11344,7 +11470,7 @@ static const ctl_table ath_sysctl_templa
+@@ -11360,7 +11486,7 @@ static const ctl_table ath_sysctl_templa
},
{ .ctl_name = CTL_AUTO,
.procname = "regdomain",
.proc_handler = ath_sysctl_halparam,
.extra2 = (void *)ATH_REGDOMAIN,
},
-@@ -11407,6 +11533,12 @@ static const ctl_table ath_sysctl_templa
+@@ -11423,6 +11549,12 @@ static const ctl_table ath_sysctl_templa
.extra2 = (void *)ATH_ACKRATE,
},
{ .ctl_name = CTL_AUTO,
.procname = "rp",
.mode = 0200,
.proc_handler = ath_sysctl_halparam,
-@@ -11647,13 +11779,6 @@ static ctl_table ath_static_sysctls[] =
+@@ -11663,13 +11795,6 @@ static ctl_table ath_static_sysctls[] =
},
#endif
{ .ctl_name = CTL_AUTO,
.procname = "maxvaps",
.mode = 0444,
.data = &ath_maxvaps,
-@@ -11661,13 +11786,6 @@ static ctl_table ath_static_sysctls[] =
+@@ -11677,13 +11802,6 @@ static ctl_table ath_static_sysctls[] =
.proc_handler = proc_dointvec
},
{ .ctl_name = CTL_AUTO,
for (i = 0; i < ss_last; i++) {
chans[i].chan = ss->ss_chans[i];
chans[i].orig = i;
-@@ -601,6 +602,7 @@ pick_channel(struct ieee80211_scan_state
+@@ -571,6 +572,7 @@ pick_channel(struct ieee80211_scan_state
"%s: best: channel %u rssi %d\n",
__func__, i, as->as_maxrssi[i]);
}
return best;
}
-@@ -636,6 +638,7 @@ ap_end(struct ieee80211_scan_state *ss,
+@@ -609,6 +611,7 @@ ap_end(struct ieee80211_scan_state *ss,
res = 1; /* Do NOT restart scan */
} else {
struct ieee80211_scan_entry se;
/* XXX: notify all VAPs? */
/* if this is a dynamic turbo frequency , start with normal
* mode first */
-@@ -650,6 +653,11 @@ ap_end(struct ieee80211_scan_state *ss,
+@@ -623,6 +626,11 @@ ap_end(struct ieee80211_scan_state *ss,
return 0;
}
}
--- /dev/null
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -4390,13 +4390,12 @@ ath_key_update_end(struct ieee80211vap *
+ static u_int32_t
+ ath_calcrxfilter(struct ath_softc *sc)
+ {
+-#define RX_FILTER_PRESERVE (HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR)
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct net_device *dev = ic->ic_dev;
+ struct ath_hal *ah = sc->sc_ah;
+ u_int32_t rfilt;
+
+- rfilt = (ath_hal_getrxfilter(ah) & RX_FILTER_PRESERVE) |
++ rfilt = ath_hal_getrxfilter(ah) |
+ HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST |
+ HAL_RX_FILTER_MCAST;
+ if (ic->ic_opmode != IEEE80211_M_STA)
+@@ -4415,9 +4414,8 @@ ath_calcrxfilter(struct ath_softc *sc)
+ if (sc->sc_hasintmit && !sc->sc_needmib && ath_hal_getintmit(ah, NULL))
+ rfilt |= HAL_RX_FILTER_PHYERR;
+ if (sc->sc_curchan.privFlags & CHANNEL_DFS)
+- rfilt |= (HAL_RX_FILTER_PHYERR | HAL_RX_FILTER_PHYRADAR);
++ rfilt |= HAL_RX_FILTER_PHYRADAR;
+ return rfilt;
+-#undef RX_FILTER_PRESERVE
+ }
+
+ /*
--- /dev/null
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -382,6 +382,7 @@ static u_int32_t ath_set_clamped_maxtxpo
+ static void ath_poll_disable(struct net_device *dev);
+ static void ath_poll_enable(struct net_device *dev);
+ static void ath_fetch_idle_time(struct ath_softc *sc);
++static void ath_set_timing(struct ath_softc *sc);
+
+ /* calibrate every 30 secs in steady state but check every second at first. */
+ static int ath_calinterval = ATH_SHORT_CALINTERVAL;
+@@ -1185,6 +1186,7 @@ ath_attach(u_int16_t devid, struct net_d
+ sc->sc_intmit = -1;
+ sc->sc_noise_immunity = -1;
+ sc->sc_ofdm_weak_det = -1;
++ sc->sc_coverage = 7; /* 2100 meters */
+
+ return 0;
+ bad3:
+@@ -2672,6 +2674,7 @@ ath_init(struct net_device *dev)
+ */
+ ath_chan_change(sc, ic->ic_curchan);
+ ath_set_ack_bitrate(sc, sc->sc_ackrate);
++ ath_set_timing(sc);
+ dev->flags |= IFF_RUNNING; /* we are ready to go */
+ ieee80211_start_running(ic); /* start all VAPs */
+ #ifdef ATH_TX99_DIAG
+@@ -4483,17 +4486,52 @@ ath_mode_init(struct net_device *dev)
+ * Set the slot time based on the current setting.
+ */
+ static void
+-ath_settiming(struct ath_softc *sc)
++ath_set_timing(struct ath_softc *sc)
+ {
++ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+- u_int offset = getTimingOffset(sc);
++ struct ath_timings *t = &sc->sc_timings;
++ u_int offset = 9;
++
++ t->sifs = 16;
++ if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
++ offset = 20;
++ if (ic->ic_flags & IEEE80211_F_SHSLOT)
++ offset = 9;
++ } else if (IEEE80211_IS_CHAN_A(ic->ic_curchan)) {
++ offset = 9;
++ }
++
++ if (IEEE80211_IS_CHAN_TURBO(ic->ic_curchan)) {
++ offset = 6;
++ t->sifs = 8;
++ } else if (IEEE80211_IS_CHAN_HALF(ic->ic_curchan)) {
++ offset = 13;
++ t->sifs = 32;
++ } else if (IEEE80211_IS_CHAN_QUARTER(ic->ic_curchan)) {
++ offset = 21;
++ t->sifs = 64;
++ }
++
++ t->slot = offset + sc->sc_coverage;
++ t->ack = t->slot * 2 + 3;
++ t->cts = t->slot * 2 + 3;
+
+ if (sc->sc_slottimeconf > 0)
+- ath_hal_setslottime(ah, offset + sc->sc_slottimeconf);
++ t->slot = sc->sc_slottimeconf;
+ if (sc->sc_acktimeconf > 0)
+- ath_hal_setacktimeout(ah, 2 * offset + sc->sc_acktimeconf);
++ t->ack = sc->sc_acktimeconf;
+ if (sc->sc_ctstimeconf > 0)
+- ath_hal_setctstimeout(ah, 2 * offset + sc->sc_ctstimeconf);
++ t->cts = sc->sc_ctstimeconf;
++
++ t->difs = 2 * t->sifs + t->slot;
++ t->eifs = t->sifs + t->difs + 3;
++
++ ath_hal_setslottime(ah, t->slot);
++ ath_hal_setacktimeout(ah, t->ack);
++ ath_hal_setctstimeout(ah, t->cts);
++ ath_hal_seteifstime(ah, t->eifs);
++
+ sc->sc_updateslot = OK;
+ }
+
+@@ -4515,7 +4553,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_settiming(sc);
++ ath_set_timing(sc);
+ }
+
+ #ifdef ATH_SUPERG_DYNTURBO
+@@ -5359,7 +5397,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_settiming(sc); /* commit change to hardware */
++ ath_set_timing(sc); /* commit change to hardware */
+
+ if (bfaddr != 0) {
+ /*
+@@ -9429,7 +9467,8 @@ ath_set_coverageclass(struct ieee80211co
+ {
+ struct ath_softc *sc = ic->ic_dev->priv;
+
+- ath_hal_setcoverageclass(sc->sc_ah, ic->ic_coverageclass, 0);
++ sc->sc_coverage = ic->ic_coverageclass * 3;
++ ath_set_timing(sc);
+
+ return;
+ }
+@@ -10950,6 +10989,7 @@ enum {
+ ATH_OFDM_WEAK_DET = 29,
+ ATH_CHANBW = 30,
+ ATH_OUTDOOR = 31,
++ ATH_DISTANCE = 32,
+ };
+
+ /*
+@@ -11162,21 +11202,31 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ sc->sc_slottimeconf = val;
+ else
+ sc->sc_slottimeconf = 0;
+- ath_settiming(sc);
++ ath_set_timing(sc);
+ break;
+ case ATH_ACKTIMEOUT:
+ if (val > 0)
+ sc->sc_acktimeconf = val;
+ else
+ sc->sc_acktimeconf = 0;
+- ath_settiming(sc);
++ ath_set_timing(sc);
+ break;
+ case ATH_CTSTIMEOUT:
+ if (val > 0)
+ sc->sc_ctstimeconf = val;
+ else
+ sc->sc_ctstimeconf = 0;
+- ath_settiming(sc);
++ ath_set_timing(sc);
++ break;
++ case ATH_DISTANCE:
++ if (val > 0) {
++ sc->sc_coverage = ((val - 1) / 300) + 1;
++ ic->ic_coverageclass = ((sc->sc_coverage - 1) / 3) + 1;
++ } else {
++ sc->sc_coverage = 0;
++ ic->ic_coverageclass = 0;
++ }
++ ath_set_timing(sc);
+ break;
+ case ATH_SOFTLED:
+ if (val != sc->sc_softled) {
+@@ -11332,6 +11382,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl
+ case ATH_CHANBW:
+ val = sc->sc_chanbw ?: 20;
+ break;
++ case ATH_DISTANCE:
++ val = sc->sc_coverage * 300;
++ break;
+ case ATH_SLOTTIME:
+ val = ath_hal_getslottime(ah);
+ break;
+@@ -11453,6 +11506,12 @@ static const ctl_table ath_sysctl_templa
+ .extra2 = (void *)ATH_CTSTIMEOUT,
+ },
+ { .ctl_name = CTL_AUTO,
++ .procname = "distance",
++ .mode = 0644,
++ .proc_handler = ath_sysctl_halparam,
++ .extra2 = (void *)ATH_DISTANCE,
++ },
++ { .ctl_name = CTL_AUTO,
+ .procname = "softled",
+ .mode = 0644,
+ .proc_handler = ath_sysctl_halparam,
+--- a/ath/if_ath_hal.h
++++ b/ath/if_ath_hal.h
+@@ -284,6 +284,17 @@ static inline u_int ath_hal_getslottime(
+ return ret;
+ }
+
++static inline u_int ath_hal_geteifstime(struct ath_hal *ah)
++{
++ u_int ret;
++ ATH_HAL_LOCK_IRQ(ah->ah_sc);
++ ath_hal_set_function(__func__);
++ ret = ah->ah_getEifsTime(ah);
++ ath_hal_set_function(NULL);
++ ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
++ return ret;
++}
++
+ static inline void ath_hal_beaconinit(struct ath_hal *ah, u_int32_t nexttbtt,
+ u_int32_t intval)
+ {
+@@ -841,6 +852,17 @@ static inline HAL_BOOL ath_hal_setslotti
+ return ret;
+ }
+
++static inline HAL_BOOL ath_hal_seteifstime(struct ath_hal *ah, u_int a1)
++{
++ HAL_BOOL ret;
++ ATH_HAL_LOCK_IRQ(ah->ah_sc);
++ ath_hal_set_function(__func__);
++ ret = ah->ah_setEifsTime(ah, a1);
++ ath_hal_set_function(NULL);
++ ATH_HAL_UNLOCK_IRQ(ah->ah_sc);
++ return ret;
++}
++
+ static inline void ath_hal_setledstate(struct ath_hal *ah, HAL_LED_STATE a1)
+ {
+ ATH_HAL_LOCK_IRQ(ah->ah_sc);
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -613,6 +613,15 @@ struct ath_rp {
+ int rp_analyzed;
+ };
+
++struct ath_timings {
++ u_int slot;
++ u_int ack;
++ u_int cts;
++ u_int sifs;
++ u_int difs;
++ u_int eifs;
++};
++
+ struct ath_softc {
+ struct ieee80211com sc_ic; /* NB: must be first */
+ struct net_device *sc_dev;
+@@ -838,6 +847,8 @@ struct ath_softc {
+ * detected radars */
+ u_int32_t sc_nexttbtt;
+ u_int64_t sc_last_tsf;
++ u_int sc_coverage;
++ struct ath_timings sc_timings;
+ };
+
+ typedef void (*ath_callback) (struct ath_softc *);
+@@ -945,49 +956,76 @@ 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;
++#ifndef MIN
++#define MIN(a,b) ((a) < (b) ? (a) : (b))
++#endif
++#ifndef MAX
++#define MAX(a,b) ((a) > (b) ? (a) : (b))
++#endif
+
+- *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;
+- }
++/* Calculate the transmit duration of a frame. */
++static inline unsigned
++calc_usecs_unicast_packet(struct ath_softc *sc, int length,
++ int rix, int short_retries, int long_retries)
++{
++ const HAL_RATE_TABLE *rt = sc->sc_currates;
++ struct ieee80211com *ic = &sc->sc_ic;
++ struct ath_timings *t = &sc->sc_timings;
++ unsigned int x = 0, tt = 0;
++ unsigned int cix = rt->info[rix].controlRate;
++ int rts = 0, cts = 0;
++ int cw = ATH_DEFAULT_CWMIN;
++
++ KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
++
++ if (!rt->info[rix].rateKbps) {
++ printk(KERN_WARNING "rix %d (%d) bad ratekbps %d mode %u\n",
++ rix, rt->info[rix].dot11Rate,
++ rt->info[rix].rateKbps,
++ sc->sc_curmode);
++ return 0;
++ }
++
++ if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
++ (rt->info[rix].phy == IEEE80211_T_OFDM)) {
++
++ if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
++ rts = 1;
++ else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
++ cts = 1;
++
++ cix = rt->info[sc->sc_protrix].controlRate;
++ }
++
++ if ((rts || cts) && rt->info[cix].rateKbps) {
++ int ctsrate = rt->info[cix].rateCode;
++ int ctsduration = 0;
++
++ ctsrate |= rt->info[cix].shortPreamble;
++ if (rts) /* SIFS + CTS */
++ ctsduration += rt->info[cix].spAckDuration;
++
++ ctsduration += ath_hal_computetxtime(sc->sc_ah,
++ rt, length, rix, AH_TRUE);
++
++ if (cts) /* SIFS + ACK */
++ ctsduration += rt->info[cix].spAckDuration;
++
++ tt += (short_retries + 1) * ctsduration;
++ }
++ tt += t->difs;
++ tt += (long_retries + 1) * (t->sifs + rt->info[rix].spAckDuration);
++ tt += (long_retries + 1) * ath_hal_computetxtime(sc->sc_ah, rt, length,
++ rix, AH_TRUE);
++ for (x = 0; x <= short_retries + long_retries; x++) {
++ cw = MIN(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
++ tt += (t->slot * cw / 2);
++ }
++ return tt;
+ }
+
+-
+ struct ath_hw_detect {
+ const char *vendor_name;
+ const char *card_name;
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -170,85 +170,6 @@ rate_to_ndx(struct minstrel_node *sn, in
+ return -1;
+ }
+
+-/* Calculate the transmit duration of a frame. */
+-static unsigned
+-calc_usecs_unicast_packet(struct ath_softc *sc, int length,
+- int rix, int short_retries, int long_retries)
+-{
+- const HAL_RATE_TABLE *rt = sc->sc_currates;
+- struct ieee80211com *ic = &sc->sc_ic;
+- unsigned t_slot = 20;
+- unsigned t_difs = 50;
+- unsigned t_sifs = 10;
+- unsigned int x = 0, tt = 0;
+- unsigned int cix = rt->info[rix].controlRate;
+- int rts = 0, cts = 0;
+- int cw = ATH_DEFAULT_CWMIN;
+-
+- KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+-
+- if (!rt->info[rix].rateKbps) {
+- printk(KERN_WARNING "rix %d (%d) bad ratekbps %d mode %u\n",
+- rix, rt->info[rix].dot11Rate,
+- rt->info[rix].rateKbps,
+- sc->sc_curmode);
+- return 0;
+- }
+-
+- 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)
+- rts = 1;
+- else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
+- cts = 1;
+-
+- cix = rt->info[sc->sc_protrix].controlRate;
+- }
+-
+-#if 0
+- if (length > ic->ic_rtsthreshold)
+- rts = 1;
+-#endif
+-
+- if (rts || cts) {
+- int ctsrate = rt->info[cix].rateCode;
+- int ctsduration = 0;
+-
+- if (!rt->info[cix].rateKbps) {
+-#if 0
+- printk(KERN_WARNING "cix %d (%d) bad ratekbps %d mode %u\n",
+- cix, rt->info[cix].dot11Rate,
+- rt->info[cix].rateKbps,
+- sc->sc_curmode);
+-#endif
+- return 0;
+- }
+-
+-
+- ctsrate |= rt->info[cix].shortPreamble;
+- if (rts) /* SIFS + CTS */
+- ctsduration += rt->info[cix].spAckDuration;
+-
+- ctsduration += ath_hal_computetxtime(sc->sc_ah,
+- rt, length, rix, AH_TRUE);
+-
+- if (cts) /* SIFS + ACK */
+- ctsduration += rt->info[cix].spAckDuration;
+-
+- tt += (short_retries + 1) * ctsduration;
+- }
+- tt += t_difs;
+- tt += (long_retries + 1) * (t_sifs + rt->info[rix].spAckDuration);
+- tt += (long_retries + 1) * ath_hal_computetxtime(sc->sc_ah, rt, length,
+- rix, AH_TRUE);
+- for (x = 0; x <= short_retries + long_retries; x++) {
+- cw = MIN(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
+- tt += (t_slot * cw / 2);
+- }
+- return tt;
+-}
+-
+ static void
+ ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
+ {
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -137,92 +137,6 @@ rate_to_ndx(struct sample_node *sn, int
+ return -1;
+ }
+
+-/*
+- * Calculate the transmit duration of a frame.
+- */
+-static unsigned
+-calc_usecs_unicast_packet(struct ath_softc *sc, int length,
+- int rix, int short_retries, int long_retries)
+-{
+- const HAL_RATE_TABLE *rt = sc->sc_currates;
+- int rts, cts;
+-
+- unsigned t_slot;
+- unsigned t_difs;
+- unsigned t_sifs;
+- struct ieee80211com *ic = &sc->sc_ic;
+- unsigned int tt = 0;
+- unsigned int x;
+- unsigned int cw = ATH_DEFAULT_CWMIN;
+- unsigned int cix = rt->info[rix].controlRate;
+- KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
+-
+- if (!rt->info[rix].rateKbps) {
+- printk(KERN_WARNING "rix %u (%u) bad ratekbps %u mode %u\n",
+- rix, rt->info[rix].dot11Rate,
+- rt->info[rix].rateKbps,
+- sc->sc_curmode);
+-
+- return 0;
+- }
+-
+- cix = rt->info[rix].controlRate;
+- /*
+- * XXX getting mac/phy level timings should be fixed for turbo
+- * rates, and there is probably a way to get this from the
+- * hal...
+- */
+- ath_get_timings(sc, &t_slot, &t_sifs, &t_difs);
+- rts = cts = 0;
+-
+- if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
+- rt->info[rix].phy == IEEE80211_T_OFDM) {
+- if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
+- rts = 1;
+- else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
+- cts = 1;
+-
+- cix = rt->info[sc->sc_protrix].controlRate;
+- }
+-
+- if (0 /*length > ic->ic_rtsthreshold */)
+- rts = 1;
+-
+- if (rts || cts) {
+- int ctsrate;
+- int ctsduration = 0;
+-
+- if (!rt->info[cix].rateKbps) {
+- printk(KERN_WARNING "cix %u (%u) bad ratekbps %u mode %u\n",
+- cix, rt->info[cix].dot11Rate,
+- rt->info[cix].rateKbps,
+- sc->sc_curmode);
+- return 0;
+- }
+-
+-
+- ctsrate = rt->info[cix].rateCode | rt->info[cix].shortPreamble;
+- if (rts) /* SIFS + CTS */
+- ctsduration += rt->info[cix].spAckDuration;
+-
+- ctsduration += ath_hal_computetxtime(sc->sc_ah,
+- rt, length, rix, AH_TRUE);
+-
+- if (cts) /* SIFS + ACK */
+- ctsduration += rt->info[cix].spAckDuration;
+-
+- tt += (short_retries + 1) * ctsduration;
+- }
+- tt += t_difs;
+- tt += (long_retries+1)*(t_sifs + rt->info[rix].spAckDuration);
+- tt += (long_retries+1)*ath_hal_computetxtime(sc->sc_ah, rt, length,
+- rix, AH_TRUE);
+- for (x = 0; x <= short_retries + long_retries; x++) {
+- cw = MIN(ATH_DEFAULT_CWMAX, (cw + 1) * 2);
+- tt += (t_slot * cw / 2);
+- }
+- return tt;
+-}
+
+ static void
+ 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
+ case IEEE80211_PARAM_COVERAGE_CLASS:
+ if (value <= IEEE80211_COVERAGE_CLASS_MAX) {
+ ic->ic_coverageclass = value;
++ ic->ic_set_coverageclass(ic);
+ if (IS_UP_AUTO(vap))
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
+ retv = 0;
+--- a/net80211/ieee80211_var.h
++++ b/net80211/ieee80211_var.h
+@@ -94,7 +94,7 @@
+
+ #define IEEE80211_BGSCAN_TRIGGER_INTVL 20 /* min trigger interval for thresh based bgscan (secs) */
+
+-#define IEEE80211_COVERAGE_CLASS_MAX 31 /* max coverage class */
++#define IEEE80211_COVERAGE_CLASS_MAX 255 /* max coverage class */
+ #define IEEE80211_REGCLASSIDS_MAX 10 /* max regclass id list */
+
+ #define IEEE80211_PS_SLEEP 0x1 /* STA is in power saving mode */
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -50,7 +50,7 @@ all: compile
+
+ DEBUG = -DAR_DEBUG
+
+-ALLPROGS= athstats 80211stats athkey athchans athctrl \
++ALLPROGS= athstats 80211stats athkey athchans \
+ athdebug 80211debug wlanconfig ath_info
+
+ OBJS= $(patsubst %,%.o,$(ALLPROGS))
+--- a/tools/athctrl.c
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/*-
+- * Copyright (c) 2002-2004 Gunter Burchardt, Local-Web AG
+- * All rights reserved.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- * notice, this list of conditions and the following disclaimer,
+- * without modification.
+- * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+- * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+- * redistribution must be conditioned upon including a substantially
+- * similar Disclaimer requirement for further binary redistribution.
+- * 3. Neither the names of the above-listed copyright holders nor the names
+- * of any contributors may be used to endorse or promote products derived
+- * from this software without specific prior written permission.
+- *
+- * Alternatively, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") version 2 as published by the Free
+- * Software Foundation.
+- *
+- * NO WARRANTY
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+- * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+- * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+- * THE POSSIBILITY OF SUCH DAMAGES.
+- *
+- * $Id: athctrl.c 2394 2007-05-30 01:41:18Z mtaylor $
+- */
+-
+-/*
+- * Simple Atheros-specific tool to inspect and set atheros specific values
+- * athctrl [-i interface] [-d distance]
+- * (default interface is wifi0).
+- */
+-#include <sys/types.h>
+-#include <sys/file.h>
+-
+-#include <getopt.h>
+-
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-#include <err.h>
+-
+-#include <net/if.h>
+-#include "do_multi.h"
+-
+-static int
+-setsysctrl(const char *dev, const char *control , u_long value)
+-{
+- char buffer[256];
+- FILE * fd;
+-
+- snprintf(buffer, sizeof(buffer), "/proc/sys/dev/%s/%s", dev, control);
+- fd = fopen(buffer, "w");
+- if (fd != NULL) {
+- fprintf(fd, "%li", value);
+- fclose(fd);
+- } else
+- fprintf(stderr, "Could not open %s for writing!\n", buffer);
+-
+- return 0;
+-}
+-
+-static void usage(void)
+-{
+- fprintf(stderr,
+- "Atheros driver control\n"
+- "Copyright (c) 2002-2004 Gunter Burchardt, Local-Web AG\n"
+- "\n"
+- "usage: athctrl [-i interface] [-d distance]\n"
+- "\n"
+- "options:\n"
+- " -h show this usage\n"
+- " -i interface (default interface is wifi0)\n"
+- " -d specify the maximum distance of a sta or the distance\n"
+- " of the master\n");
+-
+- exit(1);
+-}
+-
+-int
+-CMD(athctrl)(int argc, char *argv[])
+-{
+- char device[IFNAMSIZ + 1];
+- int distance = -1;
+- int c;
+-
+- strncpy(device, "wifi0", sizeof (device));
+-
+- for (;;) {
+- c = getopt(argc, argv, "d:i:h");
+- if (c < 0)
+- break;
+- switch (c) {
+- case 'h':
+- usage();
+- break;
+- case 'd':
+- distance = atoi(optarg);
+- break;
+- case 'i':
+- strncpy(device, optarg, sizeof (device));
+- break;
+- default:
+- usage();
+- break;
+- }
+- }
+-
+- if (distance >= 0) {
+- int slottime = (distance / 300) + ((distance % 300) ? 1 : 0);
+- int acktimeout = slottime * 2 + 3;
+- int ctstimeout = slottime * 2 + 3;
+-
+- printf("Setting distance on interface %s to %i meters\n",
+- device, distance);
+- setsysctrl(device, "slottime", slottime);
+- setsysctrl(device, "acktimeout", acktimeout);
+- setsysctrl(device, "ctstimeout", ctstimeout);
+- } else
+- usage();
+- return 0;
+-}
+--- a/tools/do_multi.c
++++ b/tools/do_multi.c
+@@ -18,8 +18,6 @@ main(int argc, char *argv[])
+ ret = a80211stats_init(argc, argv);
+ if(strcmp(progname, "athchans") == 0)
+ ret = athchans_init(argc, argv);
+- if(strcmp(progname, "athctrl") == 0)
+- ret = athctrl_init(argc, argv);
+ #ifdef AR_DEBUG
+ if(strcmp(progname, "athdebug") == 0)
+ ret = athdebug_init(argc, argv);
+--- a/tools/do_multi.h
++++ b/tools/do_multi.h
+@@ -2,7 +2,6 @@
+ int a80211debug_init(int argc, char *argv[]);
+ int a80211stats_init(int argc, char *argv[]);
+ int athchans_init(int argc, char *argv[]);
+-int athctrl_init(int argc, char *argv[]);
+ int athdebug_init(int argc, char *argv[]);
+ int athkey_init(int argc, char *argv[]);
+ int athstats_init(int argc, char *argv[]);
+--- a/ath_rate/minstrel/minstrel.h
++++ b/ath_rate/minstrel/minstrel.h
+@@ -172,14 +172,6 @@ struct minstrel_node {
+
+ #define ATH_NODE_MINSTREL(an) ((struct minstrel_node *)&an[1])
+
+-
+-#ifndef MIN
+-#define MIN(a,b) ((a) < (b) ? (a) : (b))
+-#endif
+-#ifndef MAX
+-#define MAX(a,b) ((a) > (b) ? (a) : (b))
+-#endif
+-
+ /*
+ * Definitions for pulling the rate and trie counts from
+ * a 5212 h/w descriptor. These Don't belong here; the
+--- a/ath_rate/sample/sample.h
++++ b/ath_rate/sample/sample.h
+@@ -98,14 +98,6 @@ struct sample_node {
+ };
+ #define ATH_NODE_SAMPLE(an) ((struct sample_node *)&an[1])
+
+-
+-#ifndef MIN
+-#define MIN(a,b) ((a) < (b) ? (a) : (b))
+-#endif
+-#ifndef MAX
+-#define MAX(a,b) ((a) > (b) ? (a) : (b))
+-#endif
+-
+ /*
+ * Definitions for pulling the rate and trie counts from
+ * a 5212 h/w descriptor. These Don't belong here; the
--- /dev/null
+--- a/net80211/ieee80211_rate.h
++++ b/net80211/ieee80211_rate.h
+@@ -81,6 +81,8 @@ struct ieee80211vap;
+
+ /* Multi-rare retry: 3 additional rate/retry pairs */
+ struct ieee80211_mrr {
++ int rate0;
++ int retries0;
+ int rate1;
+ int retries1;
+ int rate2;
+@@ -142,7 +144,7 @@ struct ieee80211_rate_ops {
+ * for packets that were successfully sent and for those that
+ * failed (consult the descriptor for details). */
+ void (*tx_complete)(struct ath_softc *sc, struct ath_node *an,
+- const struct ath_buf *bf);
++ const struct ath_buf *bf, const struct ieee80211_mrr *mrr);
+ };
+
+ struct ath_ratectrl {
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -8634,6 +8634,8 @@ ath_tx_processq(struct ath_softc *sc, st
+
+ ni = bf->bf_node;
+ if (ni != NULL) {
++ struct ieee80211_mrr mrr;
++
+ an = ATH_NODE(ni);
+ if (ts->ts_status == 0) {
+ u_int8_t txant = ts->ts_antenna;
+@@ -8686,15 +8688,43 @@ ath_tx_processq(struct ath_softc *sc, st
+ lr = ts->ts_longretry;
+ sc->sc_stats.ast_tx_shortretry += sr;
+ sc->sc_stats.ast_tx_longretry += lr;
++ memset(&mrr, 0, sizeof(mrr));
++
++ switch(ah->ah_macType) {
++ case 5210:
++ case 5211:
++ goto skip_mrr;
++
++ case 5212:
++ mrr.rate0 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate0)].ieeerate;
++ mrr.rate1 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate1)].ieeerate;
++ mrr.rate2 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate2)].ieeerate;
++ mrr.rate3 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate3)].ieeerate;
++ break;
++
++ case 5416:
++ mrr.rate0 = sc->sc_hwmap[MS(ds->ds_ctl3, AR5416_XmitRate0)].ieeerate;
++ mrr.rate1 = sc->sc_hwmap[MS(ds->ds_ctl3, AR5416_XmitRate1)].ieeerate;
++ mrr.rate2 = sc->sc_hwmap[MS(ds->ds_ctl3, AR5416_XmitRate2)].ieeerate;
++ mrr.rate3 = sc->sc_hwmap[MS(ds->ds_ctl3, AR5416_XmitRate3)].ieeerate;
++ break;
++ }
++
++ mrr.retries0 = MS(ds->ds_ctl2, AR_XmitDataTries0);
++ mrr.retries1 = MS(ds->ds_ctl2, AR_XmitDataTries1);
++ mrr.retries2 = MS(ds->ds_ctl2, AR_XmitDataTries2);
++ mrr.retries3 = MS(ds->ds_ctl2, AR_XmitDataTries3);
++
+ /*
+ * Hand the descriptor to the rate control algorithm
+ * if the frame wasn't dropped for filtering or sent
+ * w/o waiting for an ack. In those cases the rssi
+ * and retry counts will be meaningless.
+ */
++skip_mrr:
+ if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
+ (bf->bf_flags & HAL_TXDESC_NOACK) == 0)
+- sc->sc_rc->ops->tx_complete(sc, an, bf);
++ sc->sc_rc->ops->tx_complete(sc, an, bf, &mrr);
+ }
+
+ bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -595,6 +595,46 @@ struct ath_vap {
+ (_tqs)->axq_link = NULL; \
+ } while (0)
+
++/*
++ * Definitions for pulling the rate and trie counts from
++ * a 5212 h/w descriptor. These Don't belong here; the
++ * driver should record this information so the rate control
++ * code doesn't go groveling around in the descriptor bits.
++ */
++#define ds_ctl2 ds_hw[0]
++#define ds_ctl3 ds_hw[1]
++
++/* TX ds_ctl3 */
++#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */
++#define AR_XmitDataTries0_S 16
++#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */
++#define AR_XmitDataTries1_S 20
++#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */
++#define AR_XmitDataTries2_S 24
++#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */
++#define AR_XmitDataTries3_S 28
++
++/* TX ds_ctl3 */
++#define AR_XmitRate0 0x0000001f /* series 0 tx rate */
++#define AR_XmitRate0_S 0
++#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */
++#define AR_XmitRate1_S 5
++#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */
++#define AR_XmitRate2_S 10
++#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */
++#define AR_XmitRate3_S 15
++
++#define AR5416_XmitRate0 0x000000ff
++#define AR5416_XmitRate0_S 0
++#define AR5416_XmitRate1 0x0000ff00
++#define AR5416_XmitRate1_S 8
++#define AR5416_XmitRate2 0x00ff0000
++#define AR5416_XmitRate2_S 16
++#define AR5416_XmitRate3 0xff000000
++#define AR5416_XmitRate3_S 24
++
++#define MS(_v, _f) (((_v) & (_f)) >> _f##_S)
++
+ /*
+ * concat buffers from one queue to other
+ */
+--- a/ath_rate/amrr/amrr.c
++++ b/ath_rate/amrr/amrr.c
+@@ -123,7 +123,8 @@ ath_rate_get_mrr(struct ath_softc *sc, s
+
+ static void
+ ath_rate_tx_complete(struct ath_softc *sc,
+- struct ath_node *an, const struct ath_buf *bf)
++ struct ath_node *an, const struct ath_buf *bf,
++ const struct ieee80211_mrr *mrr)
+ {
+ struct amrr_node *amn = ATH_NODE_AMRR(an);
+ const struct ath_tx_status *ts = &bf->bf_dsstatus.ds_txstat;
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -333,7 +333,8 @@ ath_rate_get_mrr(struct ath_softc *sc, s
+
+ static void
+ ath_rate_tx_complete(struct ath_softc *sc,
+- struct ath_node *an, const struct ath_buf *bf)
++ struct ath_node *an, const struct ath_buf *bf,
++ const struct ieee80211_mrr *mrr)
+ {
+ struct minstrel_node *sn = ATH_NODE_MINSTREL(an);
+ struct ieee80211com *ic = &sc->sc_ic;
+@@ -341,12 +342,9 @@ ath_rate_tx_complete(struct ath_softc *s
+ const struct ath_desc *ds = &bf->bf_desc[0];
+ int final_rate = 0;
+ int tries = 0;
+- int mrr;
++ int use_mrr;
+ int final_ndx;
+- int rate0, tries0, ndx0;
+- int rate1, tries1, ndx1;
+- int rate2, tries2, ndx2;
+- int rate3, tries3, ndx3;
++ int ndx0, ndx1, ndx2, ndx3;
+
+ /* This is the index in the retry chain we finish at.
+ * With no retransmits, it is always 0.
+@@ -376,9 +374,9 @@ ath_rate_tx_complete(struct ath_softc *s
+ if (!ts->ts_status) /* Success when sending a packet*/
+ sn->rs_ratesuccess[final_ndx]++;
+
+- mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
++ use_mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
+
+- if (!mrr) {
++ if (!use_mrr) {
+ if ((0 <= final_ndx) && (final_ndx < sn->num_rates)) {
+ sn->rs_rateattempts[final_ndx] += tries; /* only one rate was used */
+ }
+@@ -388,47 +386,36 @@ ath_rate_tx_complete(struct ath_softc *s
+ /* Now, query the hal/hardware to find out the contents of the multirate retry chain.
+ * If we have it set to 6,3,2,2, this call will always return 6,3,2,2. For some packets, we can
+ * get a mrr of 0, -1, -1, -1, which indicates there is no chain installed for that packet */
+- rate0 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate0)].ieeerate;
+- tries0 = MS(ds->ds_ctl2, AR_XmitDataTries0);
+- ndx0 = rate_to_ndx(sn, rate0);
++ ndx0 = rate_to_ndx(sn, mrr->rate0);
++ ndx1 = rate_to_ndx(sn, mrr->rate1);
++ ndx2 = rate_to_ndx(sn, mrr->rate2);
++ ndx3 = rate_to_ndx(sn, mrr->rate3);
+
+- rate1 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate1)].ieeerate;
+- tries1 = MS(ds->ds_ctl2, AR_XmitDataTries1);
+- ndx1 = rate_to_ndx(sn, rate1);
+-
+- rate2 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate2)].ieeerate;
+- tries2 = MS(ds->ds_ctl2, AR_XmitDataTries2);
+- ndx2 = rate_to_ndx(sn, rate2);
+-
+- rate3 = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate3)].ieeerate;
+- tries3 = MS(ds->ds_ctl2, AR_XmitDataTries3);
+- ndx3 = rate_to_ndx(sn, rate3);
+-
+- sn->rs_rateattempts[ndx0] += MIN(tries, tries0);
+- if (tries <= tries0)
++ sn->rs_rateattempts[ndx0] += MIN(tries, mrr->retries0);
++ if (tries <= mrr->retries0)
+ return;
+
+- if (tries1 < 0)
++ if (mrr->retries1 < 0)
+ return;
+- tries = tries - tries0;
+- sn->rs_rateattempts[ndx1] += MIN(tries, tries1);
+- if (tries <= tries1)
++ tries = tries - mrr->retries0;
++ sn->rs_rateattempts[ndx1] += MIN(tries, mrr->retries1);
++ if (tries <= mrr->retries1)
+ return;
+
+ if (bf->rcflags)
+ sn->sample_count++;
+
+- if (tries2 < 0)
++ if (mrr->retries2 < 0)
+ return;
+- tries = tries - tries1;
+- sn->rs_rateattempts[ndx2] += MIN(tries, tries2);
+- if (tries <= tries2)
++ tries = tries - mrr->retries1;
++ sn->rs_rateattempts[ndx2] += MIN(tries, mrr->retries2);
++ if (tries <= mrr->retries2)
+ return;
+
+- if (tries3 < 0)
++ if (mrr->retries3 < 0)
+ return;
+- tries = tries - tries2;
+- sn->rs_rateattempts[ndx3] += MIN(tries, tries3);
++ tries = tries - mrr->retries2;
++ sn->rs_rateattempts[ndx3] += MIN(tries, mrr->retries3);
+ }
+
+ static void
+--- a/ath_rate/minstrel/minstrel.h
++++ b/ath_rate/minstrel/minstrel.h
+@@ -172,36 +172,6 @@ struct minstrel_node {
+
+ #define ATH_NODE_MINSTREL(an) ((struct minstrel_node *)&an[1])
+
+-/*
+- * Definitions for pulling the rate and trie counts from
+- * a 5212 h/w descriptor. These Don't belong here; the
+- * driver should record this information so the rate control
+- * code doesn't go groveling around in the descriptor bits.
+- */
+-#define ds_ctl2 ds_hw[0]
+-#define ds_ctl3 ds_hw[1]
+-
+-/* TX ds_ctl3 */
+-#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */
+-#define AR_XmitDataTries0_S 16
+-#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */
+-#define AR_XmitDataTries1_S 20
+-#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */
+-#define AR_XmitDataTries2_S 24
+-#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */
+-#define AR_XmitDataTries3_S 28
+-
+-/* TX ds_ctl3 */
+-#define AR_XmitRate0 0x0000001f /* series 0 tx rate */
+-#define AR_XmitRate0_S 0
+-#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */
+-#define AR_XmitRate1_S 5
+-#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */
+-#define AR_XmitRate2_S 10
+-#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */
+-#define AR_XmitRate3_S 15
+-
+-#define MS(_v, _f) (((_v) & (_f)) >> _f##_S)
+ #endif /* _DEV_ATH_RATE_MINSTEL_H */
+
+ /* The comment below is magic for those who use emacs to edit this file. */
+--- a/ath_rate/onoe/onoe.c
++++ b/ath_rate/onoe/onoe.c
+@@ -137,7 +137,8 @@ ath_rate_get_mrr(struct ath_softc *sc, s
+
+ static void
+ ath_rate_tx_complete(struct ath_softc *sc,
+- struct ath_node *an, const struct ath_buf *bf)
++ struct ath_node *an, const struct ath_buf *bf,
++ const struct ieee80211_mrr *mrr)
+ {
+ struct onoe_node *on = ATH_NODE_ONOE(an);
+ const struct ath_tx_status *ts = &bf->bf_dsstatus.ds_txstat;
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -178,10 +178,6 @@ static __inline int best_rate_ndx(struct
+ !sn->stats[size_bin][x].packets_acked))
+ continue;
+
+- /* 9 megabits never works better than 12 */
+- if (sn->rates[x].rate == 18)
+- continue;
+-
+ /* don't use a bit-rate that has been failing */
+ if (sn->stats[size_bin][x].successive_failures > 3)
+ continue;
+@@ -234,10 +230,6 @@ pick_sample_ndx(struct sample_node *sn,
+ if (sn->rates[ndx].rate > 22 && ndx > current_ndx + 2)
+ continue;
+
+- /* 9 megabits never works better than 12 */
+- if (sn->rates[ndx].rate == 18)
+- continue;
+-
+ /* if we're using 11 megabits, only sample up to 12 megabits
+ */
+ if (sn->rates[current_ndx].rate == 22 && ndx > current_ndx + 1)
+@@ -531,7 +523,8 @@ update_stats(struct ath_softc *sc, struc
+
+ static void
+ ath_rate_tx_complete(struct ath_softc *sc,
+- struct ath_node *an, const struct ath_buf *bf)
++ struct ath_node *an, const struct ath_buf *bf,
++ const struct ieee80211_mrr *mrr)
+ {
+ struct sample_node *sn = ATH_NODE_SAMPLE(an);
+ struct ieee80211com *ic = &sc->sc_ic;
+@@ -541,7 +534,7 @@ ath_rate_tx_complete(struct ath_softc *s
+ unsigned int short_tries;
+ unsigned int long_tries;
+ unsigned int frame_size;
+- unsigned int mrr;
++ unsigned int use_mrr;
+
+ final_rate = sc->sc_hwmap[ts->ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
+ short_tries = ts->ts_shortretry + 1;
+@@ -557,7 +550,7 @@ ath_rate_tx_complete(struct ath_softc *s
+ return;
+ }
+
+- mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
++ use_mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
+
+
+ if (sc->sc_mrretry && ts->ts_status) {
+@@ -566,22 +559,15 @@ ath_rate_tx_complete(struct ath_softc *s
+ dev_info,
+ MAC_ADDR(an->an_node.ni_macaddr),
+ bin_to_size(size_to_bin(frame_size)),
+- sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate0)].ieeerate,
+- MS(ds->ds_ctl2, AR_XmitDataTries0),
+- sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate1)].ieeerate,
+- MS(ds->ds_ctl2, AR_XmitDataTries1),
+- sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate2)].ieeerate,
+- MS(ds->ds_ctl2, AR_XmitDataTries2),
+- sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate3)].ieeerate,
+- MS(ds->ds_ctl2, AR_XmitDataTries3),
++ mrr->rate0,
++ mrr->rate1,
++ mrr->rate2,
++ mrr->rate3,
+ ts->ts_status ? "FAIL" : "OK",
+ short_tries, long_tries);
+ }
+
+- mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) && ENABLE_MRR;
+-
+-
+- if (!mrr || !(ts->ts_rate & HAL_TXSTAT_ALTRATE)) {
++ if (!use_mrr || !(ts->ts_rate & HAL_TXSTAT_ALTRATE)) {
+ /* only one rate was used */
+ int ndx = rate_to_ndx(sn, final_rate);
+ if ((ndx >= 0) && (ndx < sn->num_rates)) {
+@@ -593,7 +579,6 @@ ath_rate_tx_complete(struct ath_softc *s
+ short_tries, long_tries, ts->ts_status);
+ }
+ } else {
+- unsigned int rate[4], tries[4];
+ int ndx[4];
+ int finalTSIdx = ts->ts_finaltsi;
+
+@@ -601,21 +586,10 @@ ath_rate_tx_complete(struct ath_softc *s
+ * Process intermediate rates that failed.
+ */
+
+- rate[0] = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate0)].ieeerate;
+- tries[0] = MS(ds->ds_ctl2, AR_XmitDataTries0);
+- ndx[0] = rate_to_ndx(sn, rate[0]);
+-
+- rate[1] = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate1)].ieeerate;
+- tries[1] = MS(ds->ds_ctl2, AR_XmitDataTries1);
+- ndx[1] = rate_to_ndx(sn, rate[1]);
+-
+- rate[2] = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate2)].ieeerate;
+- tries[2] = MS(ds->ds_ctl2, AR_XmitDataTries2);
+- ndx[2] = rate_to_ndx(sn, rate[2]);
+-
+- rate[3] = sc->sc_hwmap[MS(ds->ds_ctl3, AR_XmitRate3)].ieeerate;
+- tries[3] = MS(ds->ds_ctl2, AR_XmitDataTries3);
+- ndx[3] = rate_to_ndx(sn, rate[3]);
++ ndx[0] = rate_to_ndx(sn, mrr->rate0);
++ ndx[1] = rate_to_ndx(sn, mrr->rate1);
++ ndx[2] = rate_to_ndx(sn, mrr->rate2);
++ ndx[3] = rate_to_ndx(sn, mrr->rate3);
+
+ #if 0
+ DPRINTF(sc, ATH_DEBUG_RATE, "%s: " MAC_FMT " size %u finaltsidx %u tries %u status %u rate/try %u/%u %u/%u %u/%u %u/%u\n",
+@@ -636,43 +610,43 @@ ath_rate_tx_complete(struct ath_softc *s
+ * sample higher rates 1 try at a time doing so
+ * may unfairly penalize them.
+ */
+- if (tries[0] && ndx[0] >= 0) {
++ if (mrr->retries0 && ndx[0] >= 0) {
+ update_stats(sc, an, frame_size,
+- ndx[0], tries[0],
+- ndx[1], tries[1],
+- ndx[2], tries[2],
+- ndx[3], tries[3],
++ ndx[0], mrr->retries0,
++ ndx[1], mrr->retries1,
++ ndx[2], mrr->retries2,
++ ndx[3], mrr->retries3,
+ short_tries, long_tries,
+- long_tries > tries[0]);
+- long_tries -= tries[0];
++ long_tries > mrr->retries0);
++ long_tries -= mrr->retries0;
+
+ }
+
+- if (tries[1] && ndx[1] >= 0 && finalTSIdx > 0) {
++ if (mrr->retries1 && ndx[1] >= 0 && finalTSIdx > 0) {
+ update_stats(sc, an, frame_size,
+- ndx[1], tries[1],
+- ndx[2], tries[2],
+- ndx[3], tries[3],
++ ndx[1], mrr->retries1,
++ ndx[2], mrr->retries2,
++ ndx[3], mrr->retries3,
+ 0, 0,
+ short_tries, long_tries,
+ ts->ts_status);
+- long_tries -= tries[1];
++ long_tries -= mrr->retries1;
+ }
+
+- if (tries[2] && ndx[2] >= 0 && finalTSIdx > 1) {
++ if (mrr->retries2 && ndx[2] >= 0 && finalTSIdx > 1) {
+ update_stats(sc, an, frame_size,
+- ndx[2], tries[2],
+- ndx[3], tries[3],
++ ndx[2], mrr->retries2,
++ ndx[3], mrr->retries3,
+ 0, 0,
+ 0, 0,
+ short_tries, long_tries,
+ ts->ts_status);
+- long_tries -= tries[2];
++ long_tries -= mrr->retries2;
+ }
+
+- if (tries[3] && ndx[3] >= 0 && finalTSIdx > 2) {
++ if (mrr->retries3 && ndx[3] >= 0 && finalTSIdx > 2) {
+ update_stats(sc, an, frame_size,
+- ndx[3], tries[3],
++ ndx[3], mrr->retries3,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+--- a/ath_rate/sample/sample.h
++++ b/ath_rate/sample/sample.h
+@@ -98,35 +98,4 @@ struct sample_node {
+ };
+ #define ATH_NODE_SAMPLE(an) ((struct sample_node *)&an[1])
+
+-/*
+- * Definitions for pulling the rate and trie counts from
+- * a 5212 h/w descriptor. These Don't belong here; the
+- * driver should record this information so the rate control
+- * code doesn't go groveling around in the descriptor bits.
+- */
+-#define ds_ctl2 ds_hw[0]
+-#define ds_ctl3 ds_hw[1]
+-
+-/* TX ds_ctl3 */
+-#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */
+-#define AR_XmitDataTries0_S 16
+-#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */
+-#define AR_XmitDataTries1_S 20
+-#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */
+-#define AR_XmitDataTries2_S 24
+-#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */
+-#define AR_XmitDataTries3_S 28
+-
+-/* TX ds_ctl3 */
+-#define AR_XmitRate0 0x0000001f /* series 0 tx rate */
+-#define AR_XmitRate0_S 0
+-#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */
+-#define AR_XmitRate1_S 5
+-#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */
+-#define AR_XmitRate2_S 10
+-#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */
+-#define AR_XmitRate3_S 15
+-
+-#define MS(_v, _f) (((_v) & (_f)) >> _f##_S)
+-
+ #endif /* _DEV_ATH_RATE_SAMPLE_H */
--- /dev/null
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -888,9 +888,6 @@ ath_attach(u_int16_t devid, struct net_d
+ IEEE80211_ADDR_LEN +
+ IEEE80211_WEP_IVLEN +
+ IEEE80211_WEP_KIDLEN;
+-#ifdef ATH_SUPERG_FF
+- dev->hard_header_len += ATH_FF_MAX_HDR;
+-#endif
+ #endif
+ dev->type = ARPHRD_IEEE80211;
+
--- /dev/null
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -915,7 +915,7 @@ ath_attach(u_int16_t devid, struct net_d
+ ic->ic_ath_cap = 0;
+ sc->sc_fftxqmin = ATH_FF_TXQMIN;
+ #ifdef ATH_SUPERG_FF
+- ic->ic_ath_cap |= (ath_hal_fastframesupported(ah) ?
++ ic->ic_ath_cap |= (ah->ah_macType >= 5212 ?
+ IEEE80211_ATHC_FF : 0);
+ #endif
+ ic->ic_ath_cap |= (ath_hal_burstsupported(ah) ?
--- /dev/null
+--- a/ath/ath_wprobe.c
++++ b/ath/ath_wprobe.c
+@@ -119,7 +119,7 @@ ath_wprobe_sync(struct wprobe_iface *dev
+ struct ath_vap *avp = container_of(dev, struct ath_vap, av_wpif);
+ struct ieee80211vap *vap = &avp->av_vap;
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u32 cc, busy, rx, tx;
+ s16 noise;
+@@ -192,7 +192,7 @@ ath_lookup_rateval(struct ieee80211_node
+ {
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ const HAL_RATE_TABLE *rt = sc->sc_currates;
+
+ if ((!rt) || (rate < 0) || (rate >= ARRAY_SIZE(sc->sc_hwmap)))
+--- a/ath/if_ath_ahb.c
++++ b/ath/if_ath_ahb.c
+@@ -268,7 +268,7 @@ static int ahb_wmac_probe(struct platfor
+ if (!dev)
+ return -ENOMEM;
+
+- sc = dev->priv;
++ sc = netdev_priv(dev);
+ sc->aps_sc.sc_dev = dev;
+
+ dev->irq = platform_get_irq(pdev, 0);
+@@ -365,7 +365,7 @@ init_ath_wmac(u_int16_t devid, u_int16_t
+ printk(KERN_ERR "%s: no memory for device state\n", dev_info);
+ goto bad2;
+ }
+- sc = dev->priv;
++ sc = netdev_priv(dev);
+ sc->aps_sc.sc_dev = dev;
+
+ /*
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -569,7 +569,7 @@ static inline int rate_factor(int mode)
+ int
+ ath_attach(u_int16_t devid, struct net_device *dev, HAL_BUS_TAG tag)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap;
+ struct ath_hal *ah;
+@@ -1206,7 +1206,7 @@ bad:
+ int
+ ath_detach(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+
+ HAL_INT tmp;
+@@ -1266,7 +1266,7 @@ static struct ieee80211vap *
+ ath_vap_create(struct ieee80211com *ic, const char *name,
+ int opmode, int flags, struct net_device *mdev, struct ieee80211vap *master)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct net_device *dev;
+ struct ath_vap *avp;
+@@ -1344,7 +1344,7 @@ ath_vap_create(struct ieee80211com *ic,
+ return NULL;
+ }
+
+- avp = dev->priv;
++ avp = netdev_priv(dev);
+ ieee80211_vap_setup(ic, dev, name, opmode, flags, master);
+ /* override with driver methods */
+ vap = &avp->av_vap;
+@@ -1570,7 +1570,7 @@ static void
+ ath_vap_delete(struct ieee80211vap *vap)
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_vap *avp = ATH_VAP(vap);
+ int decrease = 1;
+@@ -1672,7 +1672,7 @@ void
+ ath_suspend(struct net_device *dev)
+ {
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ #endif
+
+ DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags);
+@@ -1683,7 +1683,7 @@ void
+ ath_resume(struct net_device *dev)
+ {
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ #endif
+
+ DPRINTF(sc, ATH_DEBUG_ANY, "flags=%x\n", dev->flags);
+@@ -2247,7 +2247,7 @@ ath_intr(int irq, void *dev_id, struct p
+ #endif
+ {
+ struct net_device *dev = dev_id;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int64_t hw_tsf = 0;
+ HAL_INT status;
+@@ -2468,7 +2468,7 @@ static void
+ ath_fatal_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ EPRINTF(sc, "Hardware error; resetting.\n");
+ ath_reset(dev);
+@@ -2478,7 +2478,7 @@ static void
+ ath_rxorn_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ EPRINTF(sc, "Receive FIFO overrun; resetting.\n");
+ ath_reset(dev);
+@@ -2488,7 +2488,7 @@ static void
+ ath_bmiss_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (time_before(jiffies, sc->sc_ic.ic_bmiss_guard)) {
+ /* Beacon miss interrupt occured too short after last beacon
+@@ -2567,7 +2567,7 @@ done:
+ static int
+ ath_init(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ HAL_STATUS status;
+@@ -2692,7 +2692,7 @@ done:
+ static int
+ ath_stop_locked(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+
+@@ -2777,7 +2777,7 @@ static void ath_set_beacon_cal(struct at
+ static int
+ ath_stop(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ int error;
+
+ ATH_LOCK(sc);
+@@ -2997,7 +2997,7 @@ ath_fetch_idle_time(struct ath_softc *sc
+ static int
+ ath_reset(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_channel *c;
+@@ -3163,7 +3163,7 @@ dot11_to_ratecode(struct ath_softc *sc,
+ static int
+ ath_tx_startraw(struct net_device *dev, struct ath_buf *bf, struct sk_buff *skb)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_phy_params *ph = (struct ieee80211_phy_params *)
+ (SKB_CB(skb) + 1); /* NB: SKB_CB casts to CB struct*. */
+@@ -3476,7 +3476,7 @@ _take_txbuf(struct ath_softc *sc, int fo
+ static int
+ ath_hardstart(struct sk_buff *skb, struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211_node *ni = NULL;
+ struct ath_buf *bf = NULL;
+ ath_bufhead bf_head;
+@@ -3791,7 +3791,7 @@ static int
+ ath_mgtstart(struct ieee80211com *ic, struct sk_buff *skb)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_buf *bf = NULL;
+ int error;
+
+@@ -4150,7 +4150,7 @@ static ieee80211_keyix_t
+ ath_key_alloc(struct ieee80211vap *vap, const struct ieee80211_key *k)
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ /*
+ * Group key allocation must be handled specially for
+@@ -4215,7 +4215,7 @@ ath_key_delete(struct ieee80211vap *vap,
+ struct ieee80211_node *ninfo)
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_node *ni = NULL;
+ const struct ieee80211_cipher *cip = k->wk_cipher;
+@@ -4291,14 +4291,14 @@ ath_key_set(struct ieee80211vap *vap, co
+ const u_int8_t mac[IEEE80211_ADDR_LEN])
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ return ath_keyset(sc, k, mac, vap->iv_bss);
+ }
+
+ static void ath_poll_disable(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ /*
+ * XXX Using in_softirq is not right since we might
+@@ -4316,7 +4316,7 @@ static void ath_poll_disable(struct net_
+
+ static void ath_poll_enable(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ /* NB: see above */
+ if (!in_softirq()) {
+@@ -4342,7 +4342,7 @@ ath_key_update_begin(struct ieee80211vap
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ #endif
+
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE, "Begin\n");
+@@ -4360,7 +4360,7 @@ ath_key_update_end(struct ieee80211vap *
+ {
+ struct net_device *dev = vap->iv_ic->ic_dev;
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ #endif
+
+ DPRINTF(sc, ATH_DEBUG_KEYCACHE, "End\n");
+@@ -4453,7 +4453,7 @@ ath_merge_mcast(struct ath_softc *sc, u_
+ static void
+ ath_mode_init(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int32_t rfilt, mfilt[2];
+
+@@ -4539,7 +4539,7 @@ ath_set_timing(struct ath_softc *sc)
+ static void
+ ath_updateslot(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+
+ /*
+@@ -4569,7 +4569,7 @@ ath_beacon_dturbo_config(struct ieee8021
+ (vap->iv_bss && (vap->iv_bss->ni_ath_flags & (IEEE80211_ATHC_TURBOP)) == \
+ (IEEE80211_ATHC_TURBOP))
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP && IS_CAPABLE(vap)) {
+
+@@ -4617,7 +4617,7 @@ static void
+ ath_beacon_dturbo_update(struct ieee80211vap *vap, int *needmark, u_int8_t dtim)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ u_int32_t bss_traffic;
+
+ if (sc->sc_ignore_ar) {
+@@ -4758,7 +4758,7 @@ static void
+ ath_turbo_switch_mode(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ unsigned int newflags;
+
+@@ -5437,7 +5437,7 @@ static void
+ ath_bstuck_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ /*
+ * XXX:if the bmisscount is cleared while the
+ * tasklet execution is pending, the following
+@@ -5890,7 +5890,7 @@ ath_node_alloc_debug(struct ieee80211vap
+ ath_node_alloc(struct ieee80211vap *vap)
+ #endif
+ {
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space;
+ struct ath_node *an = kmalloc(space, GFP_ATOMIC);
+ if (an != NULL) {
+@@ -5926,7 +5926,7 @@ ath_node_cleanup(struct ieee80211_node *
+ #endif
+ {
+ struct ieee80211com *ic = ni->ni_ic;
+- struct ath_softc *sc = ni->ni_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ni->ni_ic->ic_dev);
+ struct ath_node *an = ATH_NODE(ni);
+ struct ath_buf *bf;
+
+@@ -5984,7 +5984,7 @@ ath_node_free_debug(struct ieee80211_nod
+ ath_node_free(struct ieee80211_node *ni)
+ #endif
+ {
+- struct ath_softc *sc = ni->ni_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ni->ni_ic->ic_dev);
+
+ #ifdef IEEE80211_DEBUG_REFCNT
+ sc->sc_node_free_debug(ni, func, line);
+@@ -6032,7 +6032,7 @@ ath_node_move_data(const struct ieee8021
+ #ifdef NOT_YET
+ struct ath_txq *txq = NULL;
+ struct ieee80211com *ic = ni->ni_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_buf *bf, *prev, *bf_tmp, *bf_tmp1;
+ struct ath_hal *ah = sc->sc_ah;
+ struct sk_buff *skb = NULL;
+@@ -6552,7 +6552,7 @@ static void
+ ath_capture(struct net_device *dev, const struct ath_buf *bf,
+ struct sk_buff *skb, u_int64_t tsf, unsigned int tx)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct sk_buff *tskb = NULL;
+
+@@ -6612,7 +6612,7 @@ static void
+ ath_recv_mgmt(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null,
+ struct sk_buff *skb, int subtype, int rssi, u_int64_t rtsf)
+ {
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ #ifdef AR_DEBUG
+ struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
+ #endif
+@@ -6779,7 +6779,7 @@ ath_rx_poll(struct net_device *dev, int
+ struct net_device *dev = sc->sc_dev;
+ int rx_limit = budget;
+ #else
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ int rx_limit = min(dev->quota, *budget);
+ #endif
+ struct ath_buf *bf;
+@@ -7301,7 +7301,7 @@ static void ath_grppoll_start(struct iee
+ struct sk_buff *skb = NULL;
+ struct ath_buf *bf, *head = NULL;
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int8_t rate;
+ unsigned int ctsrate = 0, ctsduration = 0;
+@@ -7519,7 +7519,7 @@ static void ath_grppoll_start(struct iee
+ static void ath_grppoll_stop(struct ieee80211vap *vap)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_txq *txq = &sc->sc_grpplq;
+ struct ath_buf *bf;
+@@ -7731,7 +7731,7 @@ ath_txq_update(struct ath_softc *sc, str
+ static int
+ ath_wme_update(struct ieee80211com *ic)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ if (sc->sc_uapsdq)
+ ath_txq_update(sc, sc->sc_uapsdq, WME_AC_VO);
+@@ -7750,7 +7750,7 @@ ath_uapsd_flush(struct ieee80211_node *n
+ {
+ struct ath_node *an = ATH_NODE(ni);
+ struct ath_buf *bf;
+- struct ath_softc *sc = ni->ni_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ni->ni_ic->ic_dev);
+ struct ath_txq *txq;
+
+ ATH_NODE_UAPSD_LOCK_IRQ(an);
+@@ -7941,7 +7941,7 @@ ath_tx_start(struct net_device *dev, str
+ struct ath_buf *bf, struct sk_buff *skb, int nextfraglen)
+ {
+ #define MIN(a,b) ((a) < (b) ? (a) : (b))
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ath_hal *ah = sc->sc_ah;
+@@ -8850,7 +8850,7 @@ static void
+ ath_tx_tasklet_q0(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ unsigned long flags;
+
+ process_tx_again:
+@@ -8881,7 +8881,7 @@ static void
+ ath_tx_tasklet_q0123(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ unsigned long flags;
+
+ process_tx_again:
+@@ -8926,7 +8926,7 @@ static void
+ ath_tx_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ unsigned int i;
+ unsigned long flags;
+
+@@ -8954,7 +8954,7 @@ process_tx_again:
+ static void
+ ath_tx_timeout(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (ath_chan_unavail(sc))
+ return;
+@@ -9362,7 +9362,7 @@ static void
+ ath_calibrate(unsigned long arg)
+ {
+ struct net_device *dev = (struct net_device *)arg;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211com *ic = &sc->sc_ic;
+ /* u_int32_t nchans; */
+@@ -9437,7 +9437,7 @@ static void
+ ath_scan_start(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int32_t rfilt;
+
+@@ -9457,7 +9457,7 @@ static void
+ ath_scan_end(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int32_t rfilt;
+
+@@ -9475,7 +9475,7 @@ static void
+ ath_set_channel(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ (void) ath_chan_set(sc, ic->ic_curchan);
+ ic->ic_channoise = ath_hal_get_channel_noise(sc->sc_ah, &(sc->sc_curchan));
+@@ -9492,7 +9492,7 @@ ath_set_channel(struct ieee80211com *ic)
+ static void
+ ath_set_coverageclass(struct ieee80211com *ic)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ sc->sc_coverage = ic->ic_coverageclass * 3;
+ ath_set_timing(sc);
+@@ -9503,7 +9503,7 @@ ath_set_coverageclass(struct ieee80211co
+ static u_int
+ ath_mhz2ieee(struct ieee80211com *ic, u_int freq, u_int flags)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ return (ath_hal_mhz2ieee(sc->sc_ah, freq, flags));
+ }
+@@ -9518,7 +9518,7 @@ ath_newstate(struct ieee80211vap *vap, e
+ struct ath_vap *avp = ATH_VAP(vap);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_node *ni, *wds_ni;
+ unsigned int i;
+@@ -9958,7 +9958,7 @@ ath_setup_comp(struct ieee80211_node *ni
+ {
+ #define IEEE80211_KEY_XR (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)
+ struct ieee80211vap *vap = ni->ni_vap;
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ struct ath_node *an = ATH_NODE(ni);
+ ieee80211_keyix_t keyix;
+
+@@ -10012,7 +10012,7 @@ static void
+ ath_setup_stationkey(struct ieee80211_node *ni)
+ {
+ struct ieee80211vap *vap = ni->ni_vap;
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ ieee80211_keyix_t keyix;
+
+ keyix = ath_key_alloc(vap, &ni->ni_ucastkey);
+@@ -10173,7 +10173,7 @@ ath_newassoc(struct ieee80211_node *ni,
+ {
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211vap *vap = ni->ni_vap;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+
+ sc->sc_rc->ops->newassoc(sc, ATH_NODE(ni), isnew);
+ ath_wprobe_node_join(ni->ni_vap, ni);
+@@ -10204,7 +10204,7 @@ ath_newassoc(struct ieee80211_node *ni,
+ static int
+ ath_getchannels(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ HAL_CHANNEL *chans;
+@@ -10479,7 +10479,7 @@ ath_update_txpow(struct ath_softc *sc)
+ static int
+ ath_xr_rate_setup(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211com *ic = &sc->sc_ic;
+ const HAL_RATE_TABLE *rt;
+@@ -10510,7 +10510,7 @@ ath_xr_rate_setup(struct net_device *dev
+ static int
+ ath_rate_setup(struct net_device *dev, u_int mode)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211com *ic = &sc->sc_ic;
+ const HAL_RATE_TABLE *rt;
+@@ -10757,7 +10757,7 @@ ath_printtxbuf(const struct ath_buf *bf,
+ {
+ const struct ath_tx_status *ts = &bf->bf_dsstatus.ds_txstat;
+ const struct ath_desc *ds = bf->bf_desc;
+- struct ath_softc *sc = bf->bf_node->ni_ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(bf->bf_node->ni_ic->ic_dev);
+ u_int8_t status = done ? ts->ts_status : 0;
+
+ DPRINTF(sc, ATH_DEBUG_ANY,
+@@ -10784,7 +10784,7 @@ ath_printtxbuf(const struct ath_buf *bf,
+ static struct net_device_stats *
+ ath_getstats(struct net_device *dev)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct net_device_stats *stats = &sc->sc_devstats;
+
+ /* update according to private statistics */
+@@ -10807,7 +10807,7 @@ ath_getstats(struct net_device *dev)
+ static int
+ ath_set_mac_address(struct net_device *dev, void *addr)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_hal *ah = sc->sc_ah;
+ struct sockaddr *mac = addr;
+@@ -10836,7 +10836,7 @@ ath_set_mac_address(struct net_device *d
+ static int
+ ath_change_mtu(struct net_device *dev, int mtu)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ int error = 0;
+
+ if (!(ATH_MIN_MTU < mtu && mtu <= ATH_MAX_MTU)) {
+@@ -10923,7 +10923,7 @@ bad:
+ static int
+ ath_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
+ int error;
+
+@@ -11804,7 +11804,7 @@ static void
+ ath_announce(struct net_device *dev)
+ {
+ #define HAL_MODE_DUALBAND (HAL_MODE_11A|HAL_MODE_11B)
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ u_int modes, cc;
+ static const int MLEN = 1024;
+@@ -11991,7 +11991,7 @@ static void
+ txcont_configure_radio(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ieee80211_wme_state *wme = &ic->ic_wme;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+@@ -12265,7 +12265,7 @@ static void
+ txcont_queue_packet(struct ieee80211com *ic, struct ath_txq* txq)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct ath_hal *ah = sc->sc_ah;
+ struct ath_buf *bf = NULL;
+ struct sk_buff *skb = NULL;
+@@ -12398,7 +12398,7 @@ static void
+ txcont_on(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (IFF_RUNNING != (ic->ic_dev->flags & IFF_RUNNING)) {
+ EPRINTF(sc, "Cannot enable txcont when"
+@@ -12419,7 +12419,7 @@ static void
+ txcont_off(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (TAILQ_FIRST(&ic->ic_vaps)->iv_opmode != IEEE80211_M_WDS)
+ sc->sc_beacons = 1;
+@@ -12433,7 +12433,7 @@ static int
+ ath_get_dfs_testmode(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_dfs_testmode;
+ }
+
+@@ -12460,7 +12460,7 @@ static void
+ ath_set_dfs_testmode(struct ieee80211com *ic, int value)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ sc->sc_dfs_testmode = !!value;
+ }
+
+@@ -12470,7 +12470,7 @@ static int
+ ath_get_txcont(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_txcont;
+ }
+
+@@ -12488,7 +12488,7 @@ static void
+ ath_set_txcont_power(struct ieee80211com *ic, unsigned int txpower)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ int new_txcont_power = txpower > IEEE80211_TXPOWER_MAX ?
+ IEEE80211_TXPOWER_MAX : txpower;
+ if (sc->sc_txcont_power != new_txcont_power) {
+@@ -12506,7 +12506,7 @@ static int
+ ath_get_txcont_power(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ /* VERY conservative default */
+ return sc->sc_txcont_power ? sc->sc_txcont_power : 0;
+ }
+@@ -12516,7 +12516,7 @@ ath_get_txcont_power(struct ieee80211com
+ ath_set_txcont_rate(struct ieee80211com *ic, unsigned int new_rate)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ if (sc->sc_txcont_rate != new_rate) {
+ /* NOTE: This value is sanity checked and dropped down to
+ * closest rate in txcont_on. */
+@@ -12533,7 +12533,7 @@ ath_set_txcont_rate(struct ieee80211com
+ ath_get_txcont_rate(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_txcont_rate ? sc->sc_txcont_rate : 0;
+ }
+
+@@ -12543,7 +12543,7 @@ static void
+ ath_set_dfs_cac_time(struct ieee80211com *ic, unsigned int time_s)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ sc->sc_dfs_cac_period = time_s;
+ }
+
+@@ -12553,7 +12553,7 @@ static unsigned int
+ ath_get_dfs_cac_time(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_dfs_cac_period;
+ }
+
+@@ -12573,7 +12573,7 @@ static void
+ ath_set_dfs_excl_period(struct ieee80211com *ic, unsigned int time_s)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ sc->sc_dfs_excl_period = time_s;
+ }
+
+@@ -12582,7 +12582,7 @@ static unsigned int
+ ath_get_dfs_excl_period(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ return sc->sc_dfs_excl_period;
+ }
+
+@@ -12594,7 +12594,7 @@ static unsigned int
+ ath_test_radar(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ if ((ic->ic_flags & IEEE80211_F_DOTH) && (sc->sc_curchan.privFlags & CHANNEL_DFS))
+ ath_radar_detected(sc, "ath_test_radar from user space");
+ else
+@@ -12610,7 +12610,7 @@ static unsigned int
+ ath_dump_hal_map(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ ath_hal_dump_map(sc->sc_ah);
+ return 0;
+ }
+@@ -12718,7 +12718,7 @@ ath_rcv_dev_event(struct notifier_block
+ void *ptr)
+ {
+ struct net_device *dev = (struct net_device *)ptr;
+- struct ath_softc *sc = (struct ath_softc *)dev->priv;
++ struct ath_softc *sc = (struct ath_softc *)netdev_priv(dev);
+
+ if (!dev || !sc || dev->open != &ath_init)
+ return 0;
+@@ -13453,7 +13453,7 @@ static unsigned int
+ ath_read_register(struct ieee80211com *ic, unsigned int address,
+ unsigned int* value)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ if (address >= MAX_REGISTER_ADDRESS) {
+ IPRINTF(sc, "Illegal Atheros register access "
+ "attempted: 0x%04x >= 0x%04x\n",
+@@ -13483,7 +13483,7 @@ static unsigned int
+ ath_write_register(struct ieee80211com *ic, unsigned int address,
+ unsigned int value)
+ {
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ if (address >= MAX_REGISTER_ADDRESS) {
+ IPRINTF(sc, "Illegal Atheros register access "
+ "attempted: 0x%04x >= 0x%04x\n",
+@@ -13511,7 +13511,7 @@ static void
+ ath_registers_dump(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ ath_ar5212_registers_dump(sc);
+ }
+ #endif /* #ifdef ATH_REVERSE_ENGINEERING */
+@@ -13523,7 +13523,7 @@ static void
+ ath_registers_mark(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ ath_ar5212_registers_mark(sc);
+ }
+ #endif /* #ifdef ATH_REVERSE_ENGINEERING */
+@@ -13535,7 +13535,7 @@ static void
+ ath_registers_dump_delta(struct ieee80211com *ic)
+ {
+ struct net_device *dev = ic->ic_dev;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ ath_ar5212_registers_dump_delta(sc);
+ }
+ #endif /* #ifdef ATH_REVERSE_ENGINEERING */
+--- a/ath/if_ath_pci.c
++++ b/ath/if_ath_pci.c
+@@ -199,7 +199,7 @@ ath_pci_probe(struct pci_dev *pdev, cons
+ printk(KERN_ERR "%s: no memory for device state\n", dev_info);
+ goto bad2;
+ }
+- sc = dev->priv;
++ sc = netdev_priv(dev);
+ sc->aps_sc.sc_dev = dev;
+ sc->aps_sc.sc_iobase = mem;
+
+@@ -278,7 +278,7 @@ static void
+ ath_pci_remove(struct pci_dev *pdev)
+ {
+ struct net_device *dev = pci_get_drvdata(pdev);
+- struct ath_pci_softc *sc = dev->priv;
++ struct ath_pci_softc *sc = netdev_priv(dev);
+
+ ath_detach(dev);
+ if (dev->irq)
+@@ -296,7 +296,7 @@ ath_pci_suspend(struct pci_dev *pdev, pm
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ ath_suspend(dev);
+- PCI_SAVE_STATE(pdev, ((struct ath_pci_softc *)dev->priv)->aps_pmstate);
++ PCI_SAVE_STATE(pdev, ((struct ath_pci_softc *)netdev_priv(dev))->aps_pmstate);
+ pci_disable_device(pdev);
+ return pci_set_power_state(pdev, PCI_D3hot);
+ }
+@@ -313,7 +313,7 @@ ath_pci_resume(struct pci_dev *pdev)
+ return err;
+
+ /* XXX - Should this return nonzero on fail? */
+- PCI_RESTORE_STATE(pdev, ((struct ath_pci_softc *)dev->priv)->aps_pmstate);
++ PCI_RESTORE_STATE(pdev, ((struct ath_pci_softc *)netdev_priv(dev))->aps_pmstate);
+
+ err = pci_enable_device(pdev);
+ if (err)
+--- a/ath/if_ath_radar.c
++++ b/ath/if_ath_radar.c
+@@ -1533,7 +1533,7 @@ static void ath_rp_clear(struct ath_soft
+ static void ath_rp_tasklet(TQUEUE_ARG data)
+ {
+ struct net_device *dev = (struct net_device *) data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+
+ if (sc->sc_rp_analyse != NULL)
+ sc->sc_rp_analyse(sc);
+--- a/ath_rate/amrr/amrr.c
++++ b/ath_rate/amrr/amrr.c
+@@ -298,7 +298,7 @@ ath_rate_ctl_start(struct ath_softc *sc,
+ static void
+ ath_rate_cb(void *arg, struct ieee80211_node *ni)
+ {
+- ath_rate_update(ni->ni_ic->ic_dev->priv, ni, (long) arg);
++ ath_rate_update(netdev_priv(ni->ni_ic->ic_dev), ni, (long) arg);
+ }
+
+ /*
+@@ -308,7 +308,7 @@ static void
+ ath_rate_newstate(struct ieee80211vap *vap, enum ieee80211_state state)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct amrr_softc *asc = (struct amrr_softc *) sc->sc_rc;
+ struct ieee80211_node *ni;
+
+@@ -420,7 +420,7 @@ static void
+ ath_ratectl(unsigned long data)
+ {
+ struct net_device *dev = (struct net_device *)data;
+- struct ath_softc *sc = dev->priv;
++ struct ath_softc *sc = netdev_priv(dev);
+ struct amrr_softc *asc = (struct amrr_softc *)sc->sc_rc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ int interval;
+--- a/ath_rate/minstrel/minstrel.c
++++ b/ath_rate/minstrel/minstrel.c
+@@ -622,7 +622,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ static void
+ ath_rate_cb(void *arg, struct ieee80211_node *ni)
+ {
+- ath_rate_ctl_reset(ni->ni_ic->ic_dev->priv, ni);
++ ath_rate_ctl_reset(netdev_priv(ni->ni_ic->ic_dev), ni);
+ }
+
+ /* Reset the rate control state for each 802.11 state transition. */
+@@ -636,7 +636,7 @@ ath_rate_newstate(struct ieee80211vap *v
+ /* Sync rates for associated stations and neighbors. */
+ ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, NULL);
+ }
+- ath_rate_newassoc(ic->ic_dev->priv, ATH_NODE(vap->iv_bss), 1);
++ ath_rate_newassoc(netdev_priv(ic->ic_dev), ATH_NODE(vap->iv_bss), 1);
+ }
+ }
+
+@@ -822,7 +822,7 @@ ath_proc_read_nodes(struct ieee80211vap
+ unsigned int x = 0;
+ unsigned int this_tp, this_prob, this_eprob;
+ #ifdef AR_DEBUG
+- struct ath_softc *sc = vap->iv_ic->ic_dev->priv;;
++ struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
+ #endif
+
+ IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+--- a/ath_rate/onoe/onoe.c
++++ b/ath_rate/onoe/onoe.c
+@@ -281,7 +281,7 @@ ath_rate_ctl_start(struct ath_softc *sc,
+ static void
+ ath_rate_cb(void *arg, struct ieee80211_node *ni)
+ {
+- ath_rate_update(ni->ni_ic->ic_dev->priv, ni, (long) arg);
++ ath_rate_update(netdev_priv(ni->ni_ic->ic_dev), ni, (long) arg);
+ }
+
+ /*
+@@ -291,7 +291,7 @@ static void
+ ath_rate_newstate(struct ieee80211vap *vap, enum ieee80211_state state)
+ {
+ struct ieee80211com *ic = vap->iv_ic;
+- struct ath_softc *sc = ic->ic_dev->priv;
++ struct ath_softc *sc = netdev_priv(ic->ic_dev);
+ struct ieee80211_node *ni;
+
+ if (state == IEEE80211_S_INIT)
+--- a/ath_rate/sample/sample.c
++++ b/ath_rate/sample/sample.c
+@@ -803,7 +803,7 @@ ath_rate_ctl_reset(struct ath_softc *sc,
+ static void
+ ath_rate_cb(void *arg, struct ieee80211_node *ni)
+ {
+- ath_rate_ctl_reset(ni->ni_ic->ic_dev->priv, ni);
++ ath_rate_ctl_reset(netdev_priv(ni->ni_ic->ic_dev), ni);
+ }
+
+ /*
+@@ -821,7 +821,7 @@ ath_rate_newstate(struct ieee80211vap *v
+ */
+ ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, NULL);
+ }
+- ath_rate_newassoc(ic->ic_dev->priv, ATH_NODE(vap->iv_bss), 1);
++ ath_rate_newassoc(netdev_priv(ic->ic_dev), ATH_NODE(vap->iv_bss), 1);
+ }
+ }
+
+--- a/include/compat.h
++++ b/include/compat.h
+@@ -162,6 +162,10 @@ static inline int timeval_compare(struct
+ #define IRQF_SHARED SA_SHIRQ
+ #endif
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27)
++#define netdev_priv(_netdev) ((_netdev)->priv)
++#endif
++
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ #define skb_end_pointer(_skb) ((_skb)->end)
+ #define skb_tail_pointer(_skb) ((_skb)->tail)
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -457,7 +457,7 @@ ieee80211_vap_setup(struct ieee80211com
+ #define IEEE80211_C_OPMODE \
+ (IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | IEEE80211_C_AHDEMO | \
+ IEEE80211_C_MONITOR)
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct net_device *parent = ic->ic_dev;
+ int err;
+
+@@ -1354,7 +1354,7 @@ media_status(enum ieee80211_opmode opmod
+ static void
+ ieee80211com_media_status(struct net_device *dev, struct ifmediareq *imr)
+ {
+- struct ieee80211com *ic = dev->priv; /* XXX */
++ struct ieee80211com *ic = netdev_priv(dev); /* XXX */
+
+ imr->ifm_status = IFM_AVALID;
+ if (!TAILQ_EMPTY(&ic->ic_vaps))
+@@ -1406,7 +1406,7 @@ media2mode(const struct ifmedia_entry *i
+ static int
+ ieee80211com_media_change(struct net_device *dev)
+ {
+- struct ieee80211com *ic = dev->priv; /* XXX */
++ struct ieee80211com *ic = netdev_priv(dev); /* XXX */
+ struct ieee80211vap *vap;
+ struct ifmedia_entry *ime = ic->ic_media.ifm_cur;
+ enum ieee80211_phymode newphymode;
+@@ -1510,7 +1510,7 @@ checkrate(struct ieee80211com *ic, enum
+ int
+ ieee80211_media_change(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifmedia_entry *ime = vap->iv_media.ifm_cur;
+ enum ieee80211_phymode newmode;
+@@ -1544,7 +1544,7 @@ EXPORT_SYMBOL(ieee80211_media_change);
+ void
+ ieee80211_media_status(struct net_device *dev, struct ifmediareq *imr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ enum ieee80211_phymode mode;
+ struct ieee80211_rateset *rs;
+@@ -1750,7 +1750,7 @@ EXPORT_SYMBOL(ieee80211_media2rate);
+ static struct net_device_stats *
+ ieee80211_getstats(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct net_device_stats *stats = &vap->iv_devstats;
+
+ /* XXX: Total guess as to what to count where */
+@@ -1789,7 +1789,7 @@ ieee80211_change_mtu(struct net_device *
+ static void
+ ieee80211_set_multicast_list(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *parent = ic->ic_dev;
+
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -183,7 +183,7 @@ EXPORT_SYMBOL(ieee80211_getmgtframe);
+ static void
+ ieee80211_vlan_register(struct net_device *dev, struct vlan_group *grp)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ vap->iv_vlgrp = grp;
+ }
+@@ -194,7 +194,7 @@ ieee80211_vlan_register(struct net_devic
+ static void
+ ieee80211_vlan_add_vid(struct net_device *dev, unsigned short vid)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_vlgrp != NULL)
+ vap->iv_bss->ni_vlan = vid;
+@@ -206,7 +206,7 @@ ieee80211_vlan_add_vid(struct net_device
+ static void
+ ieee80211_vlan_kill_vid(struct net_device *dev, unsigned short vid)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_vlgrp != NULL)
+ vlan_group_set_device(vap->iv_vlgrp, vid, NULL);
+@@ -989,8 +989,8 @@ ieee80211_rcv_dev_event(struct notifier_
+
+ switch (event) {
+ case NETDEV_CHANGENAME:
+- ieee80211_virtfs_vdetach(dev->priv);
+- ieee80211_virtfs_latevattach(dev->priv);
++ ieee80211_virtfs_vdetach(netdev_priv(dev));
++ ieee80211_virtfs_latevattach(netdev_priv(dev));
+ return NOTIFY_DONE;
+ default:
+ break;
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -201,7 +201,7 @@ ieee80211_classify(struct ieee80211_node
+ int
+ ieee80211_hardstart(struct sk_buff *skb, struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *parent = ic->ic_dev;
+ struct ieee80211_node *ni = NULL;
+@@ -317,7 +317,7 @@ bad:
+ */
+
+ void ieee80211_parent_queue_xmit(struct sk_buff *skb) {
+- struct ieee80211vap *vap = skb->dev->priv;
++ struct ieee80211vap *vap = netdev_priv(skb->dev);
+
+ vap->iv_devstats.tx_packets++;
+ vap->iv_devstats.tx_bytes += skb->len;
+--- a/net80211/ieee80211_proto.c
++++ b/net80211/ieee80211_proto.c
+@@ -970,7 +970,7 @@ ieee80211_init(struct net_device *dev, i
+ {
+ #define IS_RUNNING(_dev) \
+ ((_dev->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *parent = ic->ic_dev;
+
+@@ -1081,7 +1081,7 @@ ieee80211_init(struct net_device *dev, i
+ int
+ ieee80211_open(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ return ieee80211_init(dev, 0);
+ }
+@@ -1125,7 +1125,7 @@ EXPORT_SYMBOL(ieee80211_start_running);
+ int
+ ieee80211_stop(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct net_device *parent = ic->ic_dev;
+ struct ieee80211_node *tni, *ni;
+--- a/net80211/ieee80211_wireless.c
++++ b/net80211/ieee80211_wireless.c
+@@ -87,7 +87,7 @@ pre_announced_chanswitch(struct net_devi
+ static int
+ preempt_scan(struct net_device *dev, int max_grace, int max_wait)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ int total_delay = 0;
+ int canceled = 0, ready = 0;
+@@ -122,7 +122,7 @@ preempt_scan(struct net_device *dev, int
+ static struct iw_statistics *
+ ieee80211_iw_getstats(struct net_device *dev)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct iw_statistics *is = &vap->iv_iwstats;
+ struct ieee80211com *ic = vap->iv_ic;
+
+@@ -146,7 +146,7 @@ static int
+ ieee80211_ioctl_giwname(struct net_device *dev, struct iw_request_info *info,
+ char *name, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211_channel *c = vap->iv_ic->ic_curchan;
+
+ if (IEEE80211_IS_CHAN_108G(c))
+@@ -198,7 +198,7 @@ static int
+ ieee80211_ioctl_siwencode(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *erq, char *keybuf)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ int error;
+ int wepchange = 0;
+ ieee80211_keyix_t kix;
+@@ -306,7 +306,7 @@ static int
+ ieee80211_ioctl_giwencode(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *erq, char *key)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211_key *k;
+ int error;
+ ieee80211_keyix_t kix;
+@@ -351,7 +351,7 @@ ieee80211_ioctl_siwrate(struct net_devic
+ IFM_IEEE80211_11A | IFM_IEEE80211_TURBO,
+ IFM_IEEE80211_11G | IFM_IEEE80211_TURBO,
+ };
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifreq ifr;
+ int rate, retv;
+@@ -386,7 +386,7 @@ static int
+ ieee80211_ioctl_giwrate(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ifmediareq imr;
+ int rate;
+
+@@ -424,7 +424,7 @@ static int
+ ieee80211_ioctl_siwrts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ u16 val;
+
+@@ -447,7 +447,7 @@ static int
+ ieee80211_ioctl_giwrts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ rts->value = vap->iv_rtsthreshold;
+ rts->disabled = (rts->value == IEEE80211_RTS_MAX);
+@@ -460,7 +460,7 @@ static int
+ ieee80211_ioctl_siwfrag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ u16 val;
+
+@@ -483,7 +483,7 @@ static int
+ ieee80211_ioctl_giwfrag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ rts->value = vap->iv_fragthreshold;
+ rts->disabled = (rts->value == 2346);
+@@ -496,7 +496,7 @@ static int
+ ieee80211_ioctl_siwap(struct net_device *dev, struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ /* NB: should not be set when in AP mode */
+ if (vap->iv_opmode == IEEE80211_M_HOSTAP)
+@@ -532,7 +532,7 @@ static int
+ ieee80211_ioctl_giwap(struct net_device *dev, struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_flags & IEEE80211_F_DESBSSID)
+ IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_des_bssid);
+@@ -553,7 +553,7 @@ static int
+ ieee80211_ioctl_siwnickn(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (data->length > IEEE80211_NWID_LEN)
+ return -E2BIG;
+@@ -569,7 +569,7 @@ static int
+ ieee80211_ioctl_giwnickn(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (data->length > vap->iv_nicknamelen + 1)
+ data->length = vap->iv_nicknamelen + 1;
+@@ -678,7 +678,7 @@ static int
+ ieee80211_ioctl_siwfreq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_channel *c, *c2;
+ int i;
+@@ -767,7 +767,7 @@ static int
+ ieee80211_ioctl_giwfreq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+
+ if (vap->iv_state == IEEE80211_S_RUN &&
+@@ -808,7 +808,7 @@ static int
+ ieee80211_ioctl_siwessid(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *ssid)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_opmode == IEEE80211_M_WDS)
+ return -EOPNOTSUPP;
+@@ -853,7 +853,7 @@ static int
+ ieee80211_ioctl_giwessid(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *essid)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_opmode == IEEE80211_M_WDS)
+ return -EOPNOTSUPP;
+@@ -884,7 +884,7 @@ static int
+ ieee80211_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_point *data, char *extra)
+ {
+ /* save the list of node addresses */
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr address[IW_MAX_SPY];
+ unsigned int number = data->length;
+ int i;
+@@ -1072,7 +1072,7 @@ ieee80211_ioctl_getspy(struct net_device
+ * locate nodes by mac (ieee80211_find_node()),
+ * copy out rssi, set updated flag appropriately
+ */
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ ieee80211_ioctl_setthrspy(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct iw_thrspy threshold;
+
+ if (data->length != 1)
+@@ -1157,7 +1157,7 @@ static int
+ ieee80211_ioctl_getthrspy(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct iw_thrspy *threshold;
+
+@@ -1178,7 +1178,7 @@ static int
+ ieee80211_ioctl_siwmode(struct net_device *dev, struct iw_request_info *info,
+ __u32 *mode, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ifmediareq imr;
+ int valid = 0;
+
+@@ -1203,7 +1203,7 @@ static int
+ ieee80211_ioctl_giwmode(struct net_device *dev, struct iw_request_info *info,
+ __u32 *mode, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ifmediareq imr;
+
+ memset(&imr, 0, sizeof(imr));
+@@ -1226,7 +1226,7 @@ static int
+ ieee80211_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *wrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ ieee80211_ioctl_giwpower(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+
+ rrq->disabled = (ic->ic_flags & IEEE80211_F_PMGTON) == 0;
+@@ -1289,7 +1289,7 @@ static int
+ ieee80211_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+
+ if (rrq->disabled) {
+@@ -1321,7 +1321,7 @@ static int
+ ieee80211_ioctl_giwretry(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ rrq->disabled = (vap->iv_flags & IEEE80211_F_SWRETRY) == 0;
+ if (!rrq->disabled) {
+@@ -1352,7 +1352,7 @@ static int
+ ieee80211_ioctl_siwtxpow(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ int fixed, disabled;
+
+@@ -1389,7 +1389,7 @@ ieee80211_get_txcont(struct net_device *
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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 *
+ void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ struct iw_request_info *info, void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ void *w, char *extra)
+ {
+ int *params = (int*) extra;
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ if (!(ic->ic_flags & IEEE80211_F_DOTH))
+ return 0;
+@@ -1544,7 +1544,7 @@ static int
+ ieee80211_ioctl_giwtxpow(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ unsigned int power = ic->ic_txpowlimit;
+ struct ieee80211_channel *c;
+@@ -1572,7 +1572,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 ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ switch (params[1]) {
+ case 2:
+@@ -1595,7 +1595,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 ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ return ic->ic_write_register(ic, params[0], params[1]);
+ }
+@@ -1606,7 +1606,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 ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ return ic->ic_read_register(ic, params[0], ¶ms[0]);
+ }
+@@ -1642,7 +1642,7 @@ static int
+ ieee80211_ioctl_iwaplist(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct waplistreq req; /* XXX off stack */
+
+@@ -1664,7 +1664,7 @@ static int
+ ieee80211_ioctl_siwscan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ /*
+ * XXX don't permit a scan to be started unless we
+@@ -1988,7 +1988,7 @@ static int
+ ieee80211_ioctl_giwscan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct iwscanreq req;
+ int res = 0;
+@@ -2089,7 +2089,7 @@ static int
+ ieee80211_ioctl_setmode(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *wri, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifreq ifr;
+ char s[6]; /* big enough for ``11adt'' */
+@@ -2213,10 +2213,10 @@ ieee80211_setathcap(struct ieee80211vap
+ static int
+ ieee80211_set_turbo(struct net_device *dev, int flag)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifreq ifr;
+- struct ieee80211vap *tmpvap = dev->priv;
++ struct ieee80211vap *tmpvap = netdev_priv(dev);
+ int nvap = 0;
+
+ TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next)
+@@ -2237,7 +2237,7 @@ static int
+ ieee80211_ioctl_setparam(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ ieee80211_ioctl_getmode(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *wri, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifmediareq imr;
+
+@@ -2955,7 +2955,7 @@ static int
+ ieee80211_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ ieee80211_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *wri, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ void *ie;
+
+ /*
+@@ -3334,7 +3334,7 @@ static int
+ ieee80211_ioctl_getoptie(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *wri, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (vap->iv_opt_ie == NULL) {
+ wri->length = 0;
+@@ -3398,7 +3398,7 @@ ieee80211_ioctl_setappiebuf(struct net_d
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211req_getset_appiebuf *iebuf =
+ (struct ieee80211req_getset_appiebuf *)extra;
+ enum ieee80211_opmode chk_opmode;
+@@ -3440,7 +3440,7 @@ static int
+ ieee80211_ioctl_getappiebuf(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211req_getset_appiebuf *iebuf =
+ (struct ieee80211req_getset_appiebuf *)extra;
+ int max_iebuf_len;
+@@ -3481,7 +3481,7 @@ static int
+ ieee80211_ioctl_setfilter(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ ieee80211_ioctl_setkey(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ static int
+ ieee80211_ioctl_getkey(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
+ struct ieee80211req_key ik;
+@@ -3640,7 +3640,7 @@ static int
+ ieee80211_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ ieee80211_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra;
+ struct ieee80211_node *ni;
+@@ -3817,7 +3817,7 @@ static int
+ ieee80211_ioctl_wdsaddmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr *sa = (struct sockaddr *)extra;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211vap *avp;
+@@ -3846,7 +3846,7 @@ static int
+ ieee80211_ioctl_wdssetmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr *sa = (struct sockaddr *)extra;
+
+ if (vap->iv_opmode != IEEE80211_M_WDS)
+@@ -3913,7 +3913,7 @@ ieee80211_ioctl_setscanlist(struct net_d
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ char *s, *next;
+ int val = 1;
+@@ -3988,7 +3988,7 @@ static int
+ ieee80211_ioctl_addmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr *sa = (struct sockaddr *)extra;
+ const struct ieee80211_aclator *acl = vap->iv_acl;
+
+@@ -4006,7 +4006,7 @@ static int
+ ieee80211_ioctl_delmac(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct sockaddr *sa = (struct sockaddr *)extra;
+ const struct ieee80211_aclator *acl = vap->iv_acl;
+
+@@ -4024,7 +4024,7 @@ static int
+ ieee80211_ioctl_setchanlist(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211req_chanlist *list =
+ (struct ieee80211req_chanlist *)extra;
+@@ -4075,7 +4075,7 @@ static int
+ ieee80211_ioctl_getchanlist(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+
+ memcpy(extra, ic->ic_chan_active, sizeof(ic->ic_chan_active));
+@@ -4096,7 +4096,7 @@ static int
+ ieee80211_ioctl_getchaninfo(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211req_chaninfo *chans =
+ (struct ieee80211req_chaninfo *)extra;
+@@ -4143,7 +4143,7 @@ static int
+ ieee80211_ioctl_setwmmparams(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ ieee80211_ioctl_getwmmparams(struct net_device *dev,
+ struct iw_request_info *info, void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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_
+ static int
+ ieee80211_ioctl_getwpaie(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
+ struct ieee80211req_wpaie wpaie;
+@@ -4300,7 +4300,7 @@ ieee80211_ioctl_getwpaie(struct net_devi
+ static int
+ ieee80211_ioctl_getstastats(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ static int
+ ieee80211_ioctl_getscanresults(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct scanreq req;
+ int error;
+@@ -4582,7 +4582,7 @@ get_sta_info(void *arg, struct ieee80211
+ static int
+ ieee80211_ioctl_getstainfo(struct net_device *dev, struct iwreq *iwr)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct stainforeq req;
+ int error;
+@@ -4616,7 +4616,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 ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211vap *avp;
+
+@@ -4634,7 +4634,7 @@ static int
+ ieee80211_ioctl_chanswitch(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ unsigned int *param = (unsigned int *) extra;
+
+@@ -4679,7 +4679,7 @@ static int
+ ieee80211_ioctl_giwgenie(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *out, char *buf)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+
+ if (out->length < vap->iv_opt_ie_len)
+ return -E2BIG;
+@@ -5212,7 +5212,7 @@ static int
+ ieee80211_ioctl_giwencodeext(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *erq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct iw_encode_ext *ext;
+ struct ieee80211_key *wk;
+ ieee80211_keyix_t kix;
+@@ -5272,7 +5272,7 @@ static int
+ ieee80211_ioctl_siwencodeext(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *erq, char *extra)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ 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
+ static int
+ ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+- struct ieee80211vap *vap = dev->priv;
++ struct ieee80211vap *vap = netdev_priv(dev);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
+
--- /dev/null
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -2387,7 +2387,9 @@ ath_intr(int irq, void *dev_id, struct p
+ if (status & (HAL_INT_RX | HAL_INT_RXPHY)) {
+ ath_uapsd_processtriggers(sc, hw_tsf);
+ sc->sc_isr &= ~HAL_INT_RX;
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++ if (napi_schedule_prep(&sc->sc_napi))
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ if (netif_rx_schedule_prep(dev, &sc->sc_napi))
+ #else
+ if (netif_rx_schedule_prep(dev))
+@@ -2395,7 +2397,9 @@ ath_intr(int irq, void *dev_id, struct p
+ {
+ sc->sc_imask &= ~HAL_INT_RX;
+ ath_hal_intrset(ah, sc->sc_imask);
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++ __napi_schedule(&sc->sc_napi);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ __netif_rx_schedule(dev, &sc->sc_napi);
+ #else
+ __netif_rx_schedule(dev);
+@@ -7131,7 +7135,9 @@ rx_next:
+ local_irq_restore(flags);
+ }
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++ napi_complete(napi);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ netif_rx_complete(dev, napi);
+ #else
+ netif_rx_complete(dev);
--- /dev/null
+Convert to net_device_ops for Linux 2.6.29+
+http://madwifi-project.org/changeset/4005
+--- a/ath/if_ath.c
++++ b/ath/if_ath.c
+@@ -566,6 +566,20 @@ static inline int rate_factor(int mode)
+
+ /* Initialize ath_softc structure */
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++static const struct net_device_ops ath_netdev_ops = {
++ .ndo_open = ath_init,
++ .ndo_stop = ath_stop,
++ .ndo_start_xmit = ath_hardstart,
++ .ndo_tx_timeout = ath_tx_timeout,
++ .ndo_set_multicast_list = ath_mode_init,
++ .ndo_do_ioctl = ath_ioctl,
++ .ndo_get_stats = ath_getstats,
++ .ndo_set_mac_address = ath_set_mac_address,
++ .ndo_change_mtu = ath_change_mtu,
++};
++#endif
++
+ int
+ ath_attach(u_int16_t devid, struct net_device *dev, HAL_BUS_TAG tag)
+ {
+@@ -865,16 +879,20 @@ ath_attach(u_int16_t devid, struct net_d
+ }
+
+ /* NB: ether_setup is done by bus-specific code */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ dev->open = ath_init;
+ dev->stop = ath_stop;
+ dev->hard_start_xmit = ath_hardstart;
+ dev->tx_timeout = ath_tx_timeout;
+- dev->watchdog_timeo = 5 * HZ;
+ dev->set_multicast_list = ath_mode_init;
+ dev->do_ioctl = ath_ioctl;
+ dev->get_stats = ath_getstats;
+ dev->set_mac_address = ath_set_mac_address;
+ dev->change_mtu = ath_change_mtu;
++#else
++ dev->netdev_ops = &ath_netdev_ops;
++#endif
++ dev->watchdog_timeo = 5 * HZ;
+ dev->tx_queue_len = ATH_TXBUF - ATH_TXBUF_MGT_RESERVED;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ netif_napi_add(dev, &sc->sc_napi, ath_rx_poll, 64);
+@@ -12726,8 +12744,13 @@ ath_rcv_dev_event(struct notifier_block
+ struct net_device *dev = (struct net_device *)ptr;
+ struct ath_softc *sc = (struct ath_softc *)netdev_priv(dev);
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ if (!dev || !sc || dev->open != &ath_init)
+ return 0;
++#else
++ if (!dev || !sc || dev->netdev_ops->ndo_open != &ath_init)
++ return 0;
++#endif
+
+ switch (event) {
+ case NETDEV_CHANGENAME:
+--- a/net80211/ieee80211.c
++++ b/net80211/ieee80211.c
+@@ -450,6 +450,17 @@ ieee80211_ifdetach(struct ieee80211com *
+ }
+ EXPORT_SYMBOL(ieee80211_ifdetach);
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++static const struct net_device_ops ieee80211_netdev_ops = {
++ .ndo_get_stats = ieee80211_getstats,
++ .ndo_open = ieee80211_open,
++ .ndo_stop = ieee80211_stop,
++ .ndo_start_xmit = ieee80211_hardstart,
++ .ndo_set_multicast_list = ieee80211_set_multicast_list,
++ .ndo_change_mtu = ieee80211_change_mtu,
++};
++#endif
++
+ int
+ ieee80211_vap_setup(struct ieee80211com *ic, struct net_device *dev,
+ const char *name, int opmode, int flags, struct ieee80211vap *master)
+@@ -470,12 +481,16 @@ ieee80211_vap_setup(struct ieee80211com
+ } else
+ strncpy(dev->name, name, sizeof(dev->name));
+ }
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+
+ dev->get_stats = ieee80211_getstats;
+ dev->open = ieee80211_open;
+ dev->stop = ieee80211_stop;
+ dev->hard_start_xmit = ieee80211_hardstart;
+ dev->set_multicast_list = ieee80211_set_multicast_list;
++#else
++ dev->netdev_ops = &ieee80211_netdev_ops;
++#endif
+ #if 0
+ dev->set_mac_address = ieee80211_set_mac_address;
+ #endif
+@@ -1823,7 +1838,11 @@ ieee80211_set_multicast_list(struct net_
+ IEEE80211_UNLOCK_IRQ(ic);
+
+ /* XXX: Merge multicast list into parent device */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ parent->set_multicast_list(ic->ic_dev);
++#else
++ parent->netdev_ops->ndo_set_multicast_list(ic->ic_dev);
++#endif
+ }
+
+ void
+--- a/net80211/ieee80211_linux.c
++++ b/net80211/ieee80211_linux.c
+@@ -984,8 +984,14 @@ ieee80211_rcv_dev_event(struct notifier_
+ void *ptr)
+ {
+ struct net_device *dev = (struct net_device *) ptr;
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ if (!dev || dev->open != &ieee80211_open)
+ return 0;
++#else
++ if (!dev || dev->netdev_ops->ndo_open != &ieee80211_open)
++ return 0;
++#endif
+
+ switch (event) {
+ case NETDEV_CHANGENAME:
--- /dev/null
+Fix Linux 2.6.30 compatibility
+
+Linux 2.6.30 doesn't define IRQ_NONE as a macro. Assume irqreturn_t,
+IRQ_NONE and IRQ_HANDLED to be present on Linux 2.6.29 and newer.
+http://madwifi-project.org/changeset/3986
+--- a/ath/if_athvar.h
++++ b/ath/if_athvar.h
+@@ -83,11 +83,13 @@ typedef void *TQUEUE_ARG;
+ /*
+ * Guess how the interrupt handler should work.
+ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+ #if !defined(IRQ_NONE)
+ typedef void irqreturn_t;
+ #define IRQ_NONE
+ #define IRQ_HANDLED
+ #endif /* !defined(IRQ_NONE) */
++#endif /* Linux < 2.6.29 */
+
+ #ifndef SET_MODULE_OWNER
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
--- /dev/null
+diff -ur madwifi-trunk-r3314/ath/if_ath_ahb.c madwifi-trunk-r3314.patched/ath/if_ath_ahb.c
+--- madwifi-trunk-r3314/ath/if_ath_ahb.c 2009-05-17 22:16:05.000000000 +0300
++++ madwifi-trunk-r3314.patched/ath/if_ath_ahb.c 2009-05-17 22:15:47.000000000 +0300
+@@ -376,6 +376,11 @@
+ SET_MODULE_OWNER(dev);
+ sclist[wlanNum] = sc;
+
++ if (dev_alloc_name(dev, dev->name) < 0) {
++ printk(KERN_ERR "%s: cannot allocate name\n", dev_info);
++ goto bad3;
++ }
++
+ switch (wlanNum) {
+ case AR531X_WLAN0_NUM:
+ if (((devid & AR5315_REV_MAJ_M) == AR5315_REV_MAJ) ||
+diff -ur madwifi-trunk-r3314/ath/if_ath_pci.c madwifi-trunk-r3314.patched/ath/if_ath_pci.c
+--- madwifi-trunk-r3314/ath/if_ath_pci.c 2009-05-17 22:16:05.000000000 +0300
++++ madwifi-trunk-r3314.patched/ath/if_ath_pci.c 2009-05-17 22:15:47.000000000 +0300
+@@ -209,6 +209,11 @@
+ */
+ sc->aps_sc.sc_invalid = 1;
+
++ if (dev_alloc_name(dev, dev->name) < 0) {
++ printk(KERN_ERR "%s: cannot allocate name\n", dev_info);
++ goto bad3;
++ }
++
+ dev->irq = pdev->irq;
+
+ SET_MODULE_OWNER(dev);
--- /dev/null
+--- a/net80211/ieee80211_input.c
++++ b/net80211/ieee80211_input.c
+@@ -313,7 +313,7 @@ ieee80211_input(struct ieee80211vap * va
+ if (type == IEEE80211_FC0_TYPE_DATA && ni == vap->iv_bss &&
+ !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2)) {
+ /* Try to find sender in local node table. */
+- ni = ieee80211_find_node(vap->iv_bss->ni_table, wh->i_addr2);
++ ni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
+ if (ni == NULL) {
+ /*
+ * Fake up a node for this newly discovered