Search Linux Wireless

[PATCH 1/2] ath9k: Code scrub

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Merge core.c and base.c
Remove Antenna Diversity (unused now).
Remove unused chainmask handling code.
Comment, indentation scrub.

Signed-off-by: Sujith <Sujith.Manoharan@xxxxxxxxxxx>
---
 drivers/net/wireless/ath9k/Makefile |    3 +-
 drivers/net/wireless/ath9k/beacon.c |   80 +--
 drivers/net/wireless/ath9k/core.c   | 1610 -----------------------------------
 drivers/net/wireless/ath9k/core.h   |  155 +----
 drivers/net/wireless/ath9k/main.c   | 1195 +++++++++++++++++++++++++-
 drivers/net/wireless/ath9k/rc.c     |    9 +-
 drivers/net/wireless/ath9k/recv.c   |   22 +
 drivers/net/wireless/ath9k/xmit.c   |   22 +-
 8 files changed, 1231 insertions(+), 1865 deletions(-)

diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath9k/Makefile
index c58cfde..c741e8d 100644
--- a/drivers/net/wireless/ath9k/Makefile
+++ b/drivers/net/wireless/ath9k/Makefile
@@ -9,7 +9,6 @@ ath9k-y +=	hw.o \
 		main.o \
 		recv.o \
 		xmit.o \
-		rc.o \
-		core.o
+		rc.o
 
 obj-$(CONFIG_ATH9K) += ath9k.o
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index 8b94635..e80d9b9 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -14,13 +14,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
- /* Implementation of beacon processing. */
-
 #include "core.h"
 
 /*
- *  Configure parameters for the beacon queue
- *
  *  This function will modify certain transmit queue properties depending on
  *  the operating mode of the station (AP or AdHoc).  Parameters are AIFS
  *  settings and channel width min/max
@@ -54,9 +50,15 @@ static int ath_beaconq_config(struct ath_softc *sc)
 	}
 }
 
+static void ath_bstuck_process(struct ath_softc *sc)
+{
+	DPRINTF(sc, ATH_DBG_BEACON,
+		"%s: stuck beacon; resetting (bmiss count %u)\n",
+		__func__, sc->sc_bmisscount);
+	ath_reset(sc, false);
+}
+
 /*
- *  Setup the beacon frame for transmit.
- *
  *  Associates the beacon frame buffer with a transmit descriptor.  Will set
  *  up all required antenna switch parameters, rate codes, and channel flags.
  *  Beacons are always sent out at the lowest rate, and are not retried.
@@ -138,14 +140,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
 		ctsrate, ctsduration, series, 4, 0);
 }
 
-/*
- *  Generate beacon frame and queue cab data for a vap.
- *
- *  Updates the contents of the beacon frame.  It is assumed that the buffer for
- *  the beacon frame has been allocated in the ATH object, and simply needs to
- *  be filled for this cycle.  Also, any CAB (crap after beacon?) traffic will
- *  be added to the beacon frame at this point.
-*/
+/* Generate beacon frame and queue cab data for a vap */
 static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
 {
 	struct ath_buf *bf;
@@ -275,14 +270,6 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
 		sc->sc_bhalq, ito64(bf->bf_daddr), bf->bf_desc);
 }
 
-/*
- *  Setup a h/w transmit queue for beacons.
- *
- *  This function allocates an information structure (struct ath9k_txq_info)
- *  on the stack, sets some specific parameters (zero out channel width
- *  min/max, and enable aifs). The info structure does not need to be
- *  persistant.
-*/
 int ath_beaconq_setup(struct ath_hal *ah)
 {
 	struct ath9k_tx_queue_info qi;
@@ -295,14 +282,6 @@ int ath_beaconq_setup(struct ath_hal *ah)
 	return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
 }
 
-
-/*
- *  Allocate and setup an initial beacon frame.
- *
- *  Allocate a beacon state variable for a specific VAP instance created on
- *  the ATH interface.  This routine also calculates the beacon "slot" for
- *  staggared beacons in the mBSSID case.
-*/
 int ath_beacon_alloc(struct ath_softc *sc, int if_id)
 {
 	struct ieee80211_vif *vif;
@@ -321,7 +300,6 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
 	if (!avp->av_bcbuf) {
 		/* Allocate beacon state for hostap/ibss.  We know
 		 * a buffer is available. */
-
 		avp->av_bcbuf = list_first_entry(&sc->sc_bbuf,
 						 struct ath_buf, list);
 		list_del(&avp->av_bcbuf->list);
@@ -427,12 +405,6 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
 	return 0;
 }
 
-/*
- *  Reclaim beacon resources and return buffer to the pool.
- *
- *  Checks the VAP to put the beacon frame buffer back to the ATH object
- *  queue, and de-allocates any skbs that were sent as CAB traffic.
-*/
 void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
 {
 	if (avp->av_bcbuf != NULL) {
@@ -458,13 +430,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
 	}
 }
 
-/*
- * Tasklet for Sending Beacons
- *
- * Transmit one or more beacon frames at SWBA.  Dynamic updates to the frame
- * contents are done as needed and the slot time is also adjusted based on
- * current state.
-*/
 void ath9k_beacon_tasklet(unsigned long data)
 {
 	struct ath_softc *sc = (struct ath_softc *)data;
@@ -481,9 +446,7 @@ void ath9k_beacon_tasklet(unsigned long data)
 
 	if (sc->sc_flags & SC_OP_NO_RESET) {
 		show_cycles = ath9k_hw_GetMibCycleCountsPct(ah,
-							    &rx_clear,
-							    &rx_frame,
-							    &tx_frame);
+					    &rx_clear, &rx_frame, &tx_frame);
 	}
 
 	/*
@@ -605,9 +568,10 @@ void ath9k_beacon_tasklet(unsigned long data)
 	if (sc->sc_updateslot == UPDATE) {
 		sc->sc_updateslot = COMMIT; /* commit next beacon */
 		sc->sc_slotupdate = slot;
-	} else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot)
-		ath_setslottime(sc);        /* commit change to hardware */
-
+	} else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot) {
+		ath9k_hw_setslottime(sc->sc_ah, sc->sc_slottime);
+		sc->sc_updateslot = OK;
+	}
 	if (bfaddr != 0) {
 		/*
 		 * Stop any current dma and put the new frame(s) on the queue.
@@ -630,20 +594,6 @@ void ath9k_beacon_tasklet(unsigned long data)
 }
 
 /*
- *  Tasklet for Beacon Stuck processing
- *
- *  Processing for Beacon Stuck.
- *  Basically resets the chip.
-*/
-void ath_bstuck_process(struct ath_softc *sc)
-{
-	DPRINTF(sc, ATH_DBG_BEACON,
-		"%s: stuck beacon; resetting (bmiss count %u)\n",
-		__func__, sc->sc_bmisscount);
-	ath_reset(sc, false);
-}
-
-/*
  * Configure the beacon and sleep timers.
  *
  * When operating as an AP this resets the TSF and sets
@@ -886,8 +836,6 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
 	}
 }
 
-/* Function to collect beacon rssi data and resync beacon if necessary */
-
 void ath_beacon_sync(struct ath_softc *sc, int if_id)
 {
 	/*
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c
index fb6a013..e69de29 100644
--- a/drivers/net/wireless/ath9k/core.c
+++ b/drivers/net/wireless/ath9k/core.c
@@ -1,1610 +0,0 @@
-/*
- * Copyright (c) 2008, Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "core.h"
-#include "regd.h"
-
-static u32 ath_chainmask_sel_up_rssi_thres =
-	ATH_CHAINMASK_SEL_UP_RSSI_THRES;
-static u32 ath_chainmask_sel_down_rssi_thres =
-	ATH_CHAINMASK_SEL_DOWN_RSSI_THRES;
-static u32 ath_chainmask_sel_period =
-	ATH_CHAINMASK_SEL_TIMEOUT;
-
-/* return bus cachesize in 4B word units */
-
-static void bus_read_cachesize(struct ath_softc *sc, int *csz)
-{
-	u8 u8tmp;
-
-	pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, (u8 *)&u8tmp);
-	*csz = (int)u8tmp;
-
-	/*
-	 * This check was put in to avoid "unplesant" consequences if
-	 * the bootrom has not fully initialized all PCI devices.
-	 * Sometimes the cache line size register is not set
-	 */
-
-	if (*csz == 0)
-		*csz = DEFAULT_CACHELINE >> 2;   /* Use the default size */
-}
-
-static u8 parse_mpdudensity(u8 mpdudensity)
-{
-	/*
-	 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
-	 *   0 for no restriction
-	 *   1 for 1/4 us
-	 *   2 for 1/2 us
-	 *   3 for 1 us
-	 *   4 for 2 us
-	 *   5 for 4 us
-	 *   6 for 8 us
-	 *   7 for 16 us
-	 */
-	switch (mpdudensity) {
-	case 0:
-		return 0;
-	case 1:
-	case 2:
-	case 3:
-		/* Our lower layer calculations limit our precision to
-		   1 microsecond */
-		return 1;
-	case 4:
-		return 2;
-	case 5:
-		return 4;
-	case 6:
-		return 8;
-	case 7:
-		return 16;
-	default:
-		return 0;
-	}
-}
-
-/*
- *  Set current operating mode
-*/
-static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
-{
-	sc->sc_curmode = mode;
-	/*
-	 * All protection frames are transmited at 2Mb/s for
-	 * 11g, otherwise at 1Mb/s.
-	 * XXX select protection rate index from rate table.
-	 */
-	sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0);
-}
-
-/*
- * Set up rate table (legacy rates)
- */
-static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
-{
-	struct ath_rate_table *rate_table = NULL;
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_rate *rate;
-	int i, maxrates;
-
-	switch (band) {
-	case IEEE80211_BAND_2GHZ:
-		rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
-		break;
-	case IEEE80211_BAND_5GHZ:
-		rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
-		break;
-	default:
-		break;
-	}
-
-	if (rate_table == NULL)
-		return;
-
-	sband = &sc->sbands[band];
-	rate = sc->rates[band];
-
-	if (rate_table->rate_cnt > ATH_RATE_MAX)
-		maxrates = ATH_RATE_MAX;
-	else
-		maxrates = rate_table->rate_cnt;
-
-	for (i = 0; i < maxrates; i++) {
-		rate[i].bitrate = rate_table->info[i].ratekbps / 100;
-		rate[i].hw_value = rate_table->info[i].ratecode;
-		sband->n_bitrates++;
-		DPRINTF(sc, ATH_DBG_CONFIG,
-			"%s: Rate: %2dMbps, ratecode: %2d\n",
-			__func__,
-			rate[i].bitrate / 10,
-			rate[i].hw_value);
-	}
-}
-
-/*
- *  Set up channel list
- */
-static int ath_setup_channels(struct ath_softc *sc)
-{
-	struct ath_hal *ah = sc->sc_ah;
-	int nchan, i, a = 0, b = 0;
-	u8 regclassids[ATH_REGCLASSIDS_MAX];
-	u32 nregclass = 0;
-	struct ieee80211_supported_band *band_2ghz;
-	struct ieee80211_supported_band *band_5ghz;
-	struct ieee80211_channel *chan_2ghz;
-	struct ieee80211_channel *chan_5ghz;
-	struct ath9k_channel *c;
-
-	/* Fill in ah->ah_channels */
-	if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan,
-				      regclassids, ATH_REGCLASSIDS_MAX,
-				      &nregclass, CTRY_DEFAULT, false, 1)) {
-		u32 rd = ah->ah_currentRD;
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to collect channel list; "
-			"regdomain likely %u country code %u\n",
-			__func__, rd, CTRY_DEFAULT);
-		return -EINVAL;
-	}
-
-	band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ];
-	band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ];
-	chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ];
-	chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ];
-
-	for (i = 0; i < nchan; i++) {
-		c = &ah->ah_channels[i];
-		if (IS_CHAN_2GHZ(c)) {
-			chan_2ghz[a].band = IEEE80211_BAND_2GHZ;
-			chan_2ghz[a].center_freq = c->channel;
-			chan_2ghz[a].max_power = c->maxTxPower;
-
-			if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
-				chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS;
-			if (c->channelFlags & CHANNEL_PASSIVE)
-				chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
-
-			band_2ghz->n_channels = ++a;
-
-			DPRINTF(sc, ATH_DBG_CONFIG,
-				"%s: 2MHz channel: %d, "
-				"channelFlags: 0x%x\n",
-				__func__, c->channel, c->channelFlags);
-		} else if (IS_CHAN_5GHZ(c)) {
-			chan_5ghz[b].band = IEEE80211_BAND_5GHZ;
-			chan_5ghz[b].center_freq = c->channel;
-			chan_5ghz[b].max_power = c->maxTxPower;
-
-			if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
-				chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS;
-			if (c->channelFlags & CHANNEL_PASSIVE)
-				chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
-
-			band_5ghz->n_channels = ++b;
-
-			DPRINTF(sc, ATH_DBG_CONFIG,
-				"%s: 5MHz channel: %d, "
-				"channelFlags: 0x%x\n",
-				__func__, c->channel, c->channelFlags);
-		}
-	}
-
-	return 0;
-}
-
-/*
- *  Determine mode from channel flags
- *
- *  This routine will provide the enumerated WIRELESSS_MODE value based
- *  on the settings of the channel flags.  If no valid set of flags
- *  exist, the lowest mode (11b) is selected.
-*/
-
-static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan)
-{
-	if (chan->chanmode == CHANNEL_A)
-		return ATH9K_MODE_11A;
-	else if (chan->chanmode == CHANNEL_G)
-		return ATH9K_MODE_11G;
-	else if (chan->chanmode == CHANNEL_B)
-		return ATH9K_MODE_11B;
-	else if (chan->chanmode == CHANNEL_A_HT20)
-		return ATH9K_MODE_11NA_HT20;
-	else if (chan->chanmode == CHANNEL_G_HT20)
-		return ATH9K_MODE_11NG_HT20;
-	else if (chan->chanmode == CHANNEL_A_HT40PLUS)
-		return ATH9K_MODE_11NA_HT40PLUS;
-	else if (chan->chanmode == CHANNEL_A_HT40MINUS)
-		return ATH9K_MODE_11NA_HT40MINUS;
-	else if (chan->chanmode == CHANNEL_G_HT40PLUS)
-		return ATH9K_MODE_11NG_HT40PLUS;
-	else if (chan->chanmode == CHANNEL_G_HT40MINUS)
-		return ATH9K_MODE_11NG_HT40MINUS;
-
-	WARN_ON(1); /* should not get here */
-
-	return ATH9K_MODE_11B;
-}
-
-/*
- * Set the current channel
- *
- * Set/change channels.  If the channel is really being changed, it's done
- * by reseting the chip.  To accomplish this we must first cleanup any pending
- * DMA, then restart stuff after a la ath_init.
-*/
-int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
-{
-	struct ath_hal *ah = sc->sc_ah;
-	bool fastcc = true, stopped;
-
-	if (sc->sc_flags & SC_OP_INVALID) /* the device is invalid or removed */
-		return -EIO;
-
-	DPRINTF(sc, ATH_DBG_CONFIG,
-		"%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n",
-		__func__,
-		ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel,
-				  sc->sc_ah->ah_curchan->channelFlags),
-		sc->sc_ah->ah_curchan->channel,
-		ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags),
-		hchan->channel, hchan->channelFlags);
-
-	if (hchan->channel != sc->sc_ah->ah_curchan->channel ||
-	    hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags ||
-	    (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) ||
-	    (sc->sc_flags & SC_OP_FULL_RESET)) {
-		int status;
-		/*
-		 * This is only performed if the channel settings have
-		 * actually changed.
-		 *
-		 * To switch channels clear any pending DMA operations;
-		 * wait long enough for the RX fifo to drain, reset the
-		 * hardware at the new frequency, and then re-enable
-		 * the relevant bits of the h/w.
-		 */
-		ath9k_hw_set_interrupts(ah, 0);	/* disable interrupts */
-		ath_draintxq(sc, false);	/* clear pending tx frames */
-		stopped = ath_stoprecv(sc);	/* turn off frame recv */
-
-		/* XXX: do not flush receive queue here. We don't want
-		 * to flush data frames already in queue because of
-		 * changing channel. */
-
-		if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
-			fastcc = false;
-
-		spin_lock_bh(&sc->sc_resetlock);
-		if (!ath9k_hw_reset(ah, hchan,
-				    sc->sc_ht_info.tx_chan_width,
-				    sc->sc_tx_chainmask,
-				    sc->sc_rx_chainmask,
-				    sc->sc_ht_extprotspacing,
-				    fastcc, &status)) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"%s: unable to reset channel %u (%uMhz) "
-				"flags 0x%x hal status %u\n", __func__,
-				ath9k_hw_mhz2ieee(ah, hchan->channel,
-						  hchan->channelFlags),
-				hchan->channel, hchan->channelFlags, status);
-			spin_unlock_bh(&sc->sc_resetlock);
-			return -EIO;
-		}
-		spin_unlock_bh(&sc->sc_resetlock);
-
-		sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
-		sc->sc_flags &= ~SC_OP_FULL_RESET;
-
-		/* Re-enable rx framework */
-		if (ath_startrecv(sc) != 0) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"%s: unable to restart recv logic\n", __func__);
-			return -EIO;
-		}
-		/*
-		 * Change channels and update the h/w rate map
-		 * if we're switching; e.g. 11a to 11b/g.
-		 */
-		ath_setcurmode(sc, ath_chan2mode(hchan));
-
-		ath_update_txpow(sc);	/* update tx power state */
-		/*
-		 * Re-enable interrupts.
-		 */
-		ath9k_hw_set_interrupts(ah, sc->sc_imask);
-	}
-	return 0;
-}
-
-/**********************/
-/* Chainmask Handling */
-/**********************/
-
-static void ath_chainmask_sel_timertimeout(unsigned long data)
-{
-	struct ath_chainmask_sel *cm = (struct ath_chainmask_sel *)data;
-	cm->switch_allowed = 1;
-}
-
-/* Start chainmask select timer */
-static void ath_chainmask_sel_timerstart(struct ath_chainmask_sel *cm)
-{
-	cm->switch_allowed = 0;
-	mod_timer(&cm->timer, ath_chainmask_sel_period);
-}
-
-/* Stop chainmask select timer */
-static void ath_chainmask_sel_timerstop(struct ath_chainmask_sel *cm)
-{
-	cm->switch_allowed = 0;
-	del_timer_sync(&cm->timer);
-}
-
-static void ath_chainmask_sel_init(struct ath_softc *sc, struct ath_node *an)
-{
-	struct ath_chainmask_sel *cm = &an->an_chainmask_sel;
-
-	memset(cm, 0, sizeof(struct ath_chainmask_sel));
-
-	cm->cur_tx_mask = sc->sc_tx_chainmask;
-	cm->cur_rx_mask = sc->sc_rx_chainmask;
-	cm->tx_avgrssi = ATH_RSSI_DUMMY_MARKER;
-	setup_timer(&cm->timer,
-		ath_chainmask_sel_timertimeout, (unsigned long) cm);
-}
-
-int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an)
-{
-	struct ath_chainmask_sel *cm = &an->an_chainmask_sel;
-
-	/*
-	 * Disable auto-swtiching in one of the following if conditions.
-	 * sc_chainmask_auto_sel is used for internal global auto-switching
-	 * enabled/disabled setting
-	 */
-	if (sc->sc_ah->ah_caps.tx_chainmask != ATH_CHAINMASK_SEL_3X3) {
-		cm->cur_tx_mask = sc->sc_tx_chainmask;
-		return cm->cur_tx_mask;
-	}
-
-	if (cm->tx_avgrssi == ATH_RSSI_DUMMY_MARKER)
-		return cm->cur_tx_mask;
-
-	if (cm->switch_allowed) {
-		/* Switch down from tx 3 to tx 2. */
-		if (cm->cur_tx_mask == ATH_CHAINMASK_SEL_3X3 &&
-		    ATH_RSSI_OUT(cm->tx_avgrssi) >=
-		    ath_chainmask_sel_down_rssi_thres) {
-			cm->cur_tx_mask = sc->sc_tx_chainmask;
-
-			/* Don't let another switch happen until
-			 * this timer expires */
-			ath_chainmask_sel_timerstart(cm);
-		}
-		/* Switch up from tx 2 to 3. */
-		else if (cm->cur_tx_mask == sc->sc_tx_chainmask &&
-			 ATH_RSSI_OUT(cm->tx_avgrssi) <=
-			 ath_chainmask_sel_up_rssi_thres) {
-			cm->cur_tx_mask = ATH_CHAINMASK_SEL_3X3;
-
-			/* Don't let another switch happen
-			 * until this timer expires */
-			ath_chainmask_sel_timerstart(cm);
-		}
-	}
-
-	return cm->cur_tx_mask;
-}
-
-/*
- * Update tx/rx chainmask. For legacy association,
- * hard code chainmask to 1x1, for 11n association, use
- * the chainmask configuration.
- */
-
-void ath_update_chainmask(struct ath_softc *sc, int is_ht)
-{
-	sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
-	if (is_ht) {
-		sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask;
-		sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask;
-	} else {
-		sc->sc_tx_chainmask = 1;
-		sc->sc_rx_chainmask = 1;
-	}
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s: tx chmask: %d, rx chmask: %d\n",
-		__func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask);
-}
-
-/*******/
-/* ANI */
-/*******/
-
-/*
- *  This routine performs the periodic noise floor calibration function
- *  that is used to adjust and optimize the chip performance.  This
- *  takes environmental changes (location, temperature) into account.
- *  When the task is complete, it reschedules itself depending on the
- *  appropriate interval that was calculated.
- */
-
-static void ath_ani_calibrate(unsigned long data)
-{
-	struct ath_softc *sc;
-	struct ath_hal *ah;
-	bool longcal = false;
-	bool shortcal = false;
-	bool aniflag = false;
-	unsigned int timestamp = jiffies_to_msecs(jiffies);
-	u32 cal_interval;
-
-	sc = (struct ath_softc *)data;
-	ah = sc->sc_ah;
-
-	/*
-	* don't calibrate when we're scanning.
-	* we are most likely not on our home channel.
-	*/
-	if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)
-		return;
-
-	/* Long calibration runs independently of short calibration. */
-	if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) {
-		longcal = true;
-		DPRINTF(sc, ATH_DBG_ANI, "%s: longcal @%lu\n",
-			__func__, jiffies);
-		sc->sc_ani.sc_longcal_timer = timestamp;
-	}
-
-	/* Short calibration applies only while sc_caldone is false */
-	if (!sc->sc_ani.sc_caldone) {
-		if ((timestamp - sc->sc_ani.sc_shortcal_timer) >=
-		    ATH_SHORT_CALINTERVAL) {
-			shortcal = true;
-			DPRINTF(sc, ATH_DBG_ANI, "%s: shortcal @%lu\n",
-			       __func__, jiffies);
-			sc->sc_ani.sc_shortcal_timer = timestamp;
-			sc->sc_ani.sc_resetcal_timer = timestamp;
-		}
-	} else {
-		if ((timestamp - sc->sc_ani.sc_resetcal_timer) >=
-		    ATH_RESTART_CALINTERVAL) {
-			ath9k_hw_reset_calvalid(ah, ah->ah_curchan,
-						&sc->sc_ani.sc_caldone);
-			if (sc->sc_ani.sc_caldone)
-				sc->sc_ani.sc_resetcal_timer = timestamp;
-		}
-	}
-
-	/* Verify whether we must check ANI */
-	if ((timestamp - sc->sc_ani.sc_checkani_timer) >=
-	   ATH_ANI_POLLINTERVAL) {
-		aniflag = true;
-		sc->sc_ani.sc_checkani_timer = timestamp;
-	}
-
-	/* Skip all processing if there's nothing to do. */
-	if (longcal || shortcal || aniflag) {
-		/* Call ANI routine if necessary */
-		if (aniflag)
-			ath9k_hw_ani_monitor(ah, &sc->sc_halstats,
-					     ah->ah_curchan);
-
-		/* Perform calibration if necessary */
-		if (longcal || shortcal) {
-			bool iscaldone = false;
-
-			if (ath9k_hw_calibrate(ah, ah->ah_curchan,
-					       sc->sc_rx_chainmask, longcal,
-					       &iscaldone)) {
-				if (longcal)
-					sc->sc_ani.sc_noise_floor =
-						ath9k_hw_getchan_noise(ah,
-							       ah->ah_curchan);
-
-				DPRINTF(sc, ATH_DBG_ANI,
-					"%s: calibrate chan %u/%x nf: %d\n",
-					 __func__,
-					ah->ah_curchan->channel,
-					ah->ah_curchan->channelFlags,
-					sc->sc_ani.sc_noise_floor);
-			} else {
-				DPRINTF(sc, ATH_DBG_ANY,
-					"%s: calibrate chan %u/%x failed\n",
-					 __func__,
-					ah->ah_curchan->channel,
-					ah->ah_curchan->channelFlags);
-			}
-			sc->sc_ani.sc_caldone = iscaldone;
-		}
-	}
-
-	/*
-	* Set timer interval based on previous results.
-	* The interval must be the shortest necessary to satisfy ANI,
-	* short calibration and long calibration.
-	*/
-
-	cal_interval = ATH_ANI_POLLINTERVAL;
-	if (!sc->sc_ani.sc_caldone)
-		cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL);
-
-	mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
-}
-
-/********/
-/* Core */
-/********/
-
-int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
-{
-	struct ath_hal *ah = sc->sc_ah;
-	int status;
-	int error = 0;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n",
-		__func__, sc->sc_ah->ah_opmode);
-
-	/* Reset SERDES registers */
-	ath9k_hw_configpcipowersave(ah, 0);
-
-	/*
-	 * The basic interface to setting the hardware in a good
-	 * state is ``reset''.  On return the hardware is known to
-	 * be powered up and with interrupts disabled.  This must
-	 * be followed by initialization of the appropriate bits
-	 * and then setup of the interrupt mask.
-	 */
-
-	spin_lock_bh(&sc->sc_resetlock);
-	if (!ath9k_hw_reset(ah, initial_chan,
-			    sc->sc_ht_info.tx_chan_width,
-			    sc->sc_tx_chainmask, sc->sc_rx_chainmask,
-			    sc->sc_ht_extprotspacing, false, &status)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to reset hardware; hal status %u "
-			"(freq %u flags 0x%x)\n", __func__, status,
-			initial_chan->channel, initial_chan->channelFlags);
-		error = -EIO;
-		spin_unlock_bh(&sc->sc_resetlock);
-		goto done;
-	}
-	spin_unlock_bh(&sc->sc_resetlock);
-
-	/*
-	 * This is needed only to setup initial state
-	 * but it's best done after a reset.
-	 */
-	ath_update_txpow(sc);
-
-	/*
-	 * Setup the hardware after reset:
-	 * The receive engine is set going.
-	 * Frame transmit is handled entirely
-	 * in the frame output path; there's nothing to do
-	 * here except setup the interrupt mask.
-	 */
-	if (ath_startrecv(sc) != 0) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to start recv logic\n", __func__);
-		error = -EIO;
-		goto done;
-	}
-
-	/* Setup our intr mask. */
-	sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX
-		| ATH9K_INT_RXEOL | ATH9K_INT_RXORN
-		| ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
-
-	if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_GTT)
-		sc->sc_imask |= ATH9K_INT_GTT;
-
-	if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
-		sc->sc_imask |= ATH9K_INT_CST;
-
-	/*
-	 * Enable MIB interrupts when there are hardware phy counters.
-	 * Note we only do this (at the moment) for station mode.
-	 */
-	if (ath9k_hw_phycounters(ah) &&
-	    ((sc->sc_ah->ah_opmode == ATH9K_M_STA) ||
-	     (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)))
-		sc->sc_imask |= ATH9K_INT_MIB;
-	/*
-	 * Some hardware processes the TIM IE and fires an
-	 * interrupt when the TIM bit is set.  For hardware
-	 * that does, if not overridden by configuration,
-	 * enable the TIM interrupt when operating as station.
-	 */
-	if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
-	    (sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
-	    !sc->sc_config.swBeaconProcess)
-		sc->sc_imask |= ATH9K_INT_TIM;
-
-	ath_setcurmode(sc, ath_chan2mode(initial_chan));
-
-	sc->sc_flags &= ~SC_OP_INVALID;
-
-	/* Disable BMISS interrupt when we're not associated */
-	sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
-	ath9k_hw_set_interrupts(sc->sc_ah,sc->sc_imask);
-
-	ieee80211_wake_queues(sc->hw);
-done:
-	return error;
-}
-
-void ath_stop(struct ath_softc *sc)
-{
-	struct ath_hal *ah = sc->sc_ah;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Cleaning up\n", __func__);
-
-	ieee80211_stop_queues(sc->hw);
-
-	/* make sure h/w will not generate any interrupt
-	 * before setting the invalid flag. */
-	ath9k_hw_set_interrupts(ah, 0);
-
-	if (!(sc->sc_flags & SC_OP_INVALID)) {
-		ath_draintxq(sc, false);
-		ath_stoprecv(sc);
-		ath9k_hw_phy_disable(ah);
-	} else
-		sc->sc_rxlink = NULL;
-
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
-	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
-#endif
-	/* disable HAL and put h/w to sleep */
-	ath9k_hw_disable(sc->sc_ah);
-	ath9k_hw_configpcipowersave(sc->sc_ah, 1);
-
-	sc->sc_flags |= SC_OP_INVALID;
-}
-
-int ath_reset(struct ath_softc *sc, bool retry_tx)
-{
-	struct ath_hal *ah = sc->sc_ah;
-	int status;
-	int error = 0;
-
-	ath9k_hw_set_interrupts(ah, 0);
-	ath_draintxq(sc, retry_tx);
-	ath_stoprecv(sc);
-	ath_flushrecv(sc);
-
-	/* Reset chip */
-	spin_lock_bh(&sc->sc_resetlock);
-	if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan,
-			    sc->sc_ht_info.tx_chan_width,
-			    sc->sc_tx_chainmask, sc->sc_rx_chainmask,
-			    sc->sc_ht_extprotspacing, false, &status)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to reset hardware; hal status %u\n",
-			__func__, status);
-		error = -EIO;
-	}
-	spin_unlock_bh(&sc->sc_resetlock);
-
-	if (ath_startrecv(sc) != 0)
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to start recv logic\n", __func__);
-
-	/*
-	 * We may be doing a reset in response to a request
-	 * that changes the channel so update any state that
-	 * might change as a result.
-	 */
-	ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan));
-
-	ath_update_txpow(sc);
-
-	if (sc->sc_flags & SC_OP_BEACONS)
-		ath_beacon_config(sc, ATH_IF_ID_ANY);	/* restart beacons */
-
-	ath9k_hw_set_interrupts(ah, sc->sc_imask);
-
-	/* Restart the txq */
-	if (retry_tx) {
-		int i;
-		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-			if (ATH_TXQ_SETUP(sc, i)) {
-				spin_lock_bh(&sc->sc_txq[i].axq_lock);
-				ath_txq_schedule(sc, &sc->sc_txq[i]);
-				spin_unlock_bh(&sc->sc_txq[i].axq_lock);
-			}
-		}
-	}
-
-	return error;
-}
-
-/* Interrupt handler.  Most of the actual processing is deferred.
- * It's the caller's responsibility to ensure the chip is awake. */
-
-irqreturn_t ath_isr(int irq, void *dev)
-{
-	struct ath_softc *sc = dev;
-	struct ath_hal *ah = sc->sc_ah;
-	enum ath9k_int status;
-	bool sched = false;
-
-	do {
-		if (sc->sc_flags & SC_OP_INVALID) {
-			/*
-			 * The hardware is not ready/present, don't
-			 * touch anything. Note this can happen early
-			 * on if the IRQ is shared.
-			 */
-			return IRQ_NONE;
-		}
-		if (!ath9k_hw_intrpend(ah)) {	/* shared irq, not for us */
-			return IRQ_NONE;
-		}
-
-		/*
-		 * Figure out the reason(s) for the interrupt.  Note
-		 * that the hal returns a pseudo-ISR that may include
-		 * bits we haven't explicitly enabled so we mask the
-		 * value to insure we only process bits we requested.
-		 */
-		ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */
-
-		status &= sc->sc_imask;	/* discard unasked-for bits */
-
-		/*
-		 * If there are no status bits set, then this interrupt was not
-		 * for me (should have been caught above).
-		 */
-
-		if (!status)
-			return IRQ_NONE;
-
-		sc->sc_intrstatus = status;
-
-		if (status & ATH9K_INT_FATAL) {
-			/* need a chip reset */
-			sched = true;
-		} else if (status & ATH9K_INT_RXORN) {
-			/* need a chip reset */
-			sched = true;
-		} else {
-			if (status & ATH9K_INT_SWBA) {
-				/* schedule a tasklet for beacon handling */
-				tasklet_schedule(&sc->bcon_tasklet);
-			}
-			if (status & ATH9K_INT_RXEOL) {
-				/*
-				 * NB: the hardware should re-read the link when
-				 *     RXE bit is written, but it doesn't work
-				 *     at least on older hardware revs.
-				 */
-				sched = true;
-			}
-
-			if (status & ATH9K_INT_TXURN)
-				/* bump tx trigger level */
-				ath9k_hw_updatetxtriglevel(ah, true);
-			/* XXX: optimize this */
-			if (status & ATH9K_INT_RX)
-				sched = true;
-			if (status & ATH9K_INT_TX)
-				sched = true;
-			if (status & ATH9K_INT_BMISS)
-				sched = true;
-			/* carrier sense timeout */
-			if (status & ATH9K_INT_CST)
-				sched = true;
-			if (status & ATH9K_INT_MIB) {
-				/*
-				 * Disable interrupts until we service the MIB
-				 * interrupt; otherwise it will continue to
-				 * fire.
-				 */
-				ath9k_hw_set_interrupts(ah, 0);
-				/*
-				 * Let the hal handle the event. We assume
-				 * it will clear whatever condition caused
-				 * the interrupt.
-				 */
-				ath9k_hw_procmibevent(ah, &sc->sc_halstats);
-				ath9k_hw_set_interrupts(ah, sc->sc_imask);
-			}
-			if (status & ATH9K_INT_TIM_TIMER) {
-				if (!(ah->ah_caps.hw_caps &
-				      ATH9K_HW_CAP_AUTOSLEEP)) {
-					/* Clear RxAbort bit so that we can
-					 * receive frames */
-					ath9k_hw_setrxabort(ah, 0);
-					sched = true;
-				}
-			}
-		}
-	} while (0);
-
-	if (sched) {
-		/* turn off every interrupt except SWBA */
-		ath9k_hw_set_interrupts(ah, (sc->sc_imask & ATH9K_INT_SWBA));
-		tasklet_schedule(&sc->intr_tq);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/* Deferred interrupt processing  */
-
-static void ath9k_tasklet(unsigned long data)
-{
-	struct ath_softc *sc = (struct ath_softc *)data;
-	u32 status = sc->sc_intrstatus;
-
-	if (status & ATH9K_INT_FATAL) {
-		/* need a chip reset */
-		ath_reset(sc, false);
-		return;
-	} else {
-
-		if (status &
-		    (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
-			/* XXX: fill me in */
-			/*
-			if (status & ATH9K_INT_RXORN) {
-			}
-			if (status & ATH9K_INT_RXEOL) {
-			}
-			*/
-			spin_lock_bh(&sc->sc_rxflushlock);
-			ath_rx_tasklet(sc, 0);
-			spin_unlock_bh(&sc->sc_rxflushlock);
-		}
-		/* XXX: optimize this */
-		if (status & ATH9K_INT_TX)
-			ath_tx_tasklet(sc);
-		/* XXX: fill me in */
-		/*
-		if (status & ATH9K_INT_BMISS) {
-		}
-		if (status & (ATH9K_INT_TIM | ATH9K_INT_DTIMSYNC)) {
-			if (status & ATH9K_INT_TIM) {
-			}
-			if (status & ATH9K_INT_DTIMSYNC) {
-			}
-		}
-		*/
-	}
-
-	/* re-enable hardware interrupt */
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask);
-}
-
-int ath_init(u16 devid, struct ath_softc *sc)
-{
-	struct ath_hal *ah = NULL;
-	int status;
-	int error = 0, i;
-	int csz = 0;
-
-	/* XXX: hardware will not be ready until ath_open() being called */
-	sc->sc_flags |= SC_OP_INVALID;
-	sc->sc_debug = DBG_DEFAULT;
-
-	spin_lock_init(&sc->sc_resetlock);
-	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
-	tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
-		     (unsigned long)sc);
-
-	/*
-	 * Cache line size is used to size and align various
-	 * structures used to communicate with the hardware.
-	 */
-	bus_read_cachesize(sc, &csz);
-	/* XXX assert csz is non-zero */
-	sc->sc_cachelsz = csz << 2;	/* convert to bytes */
-
-	ah = ath9k_hw_attach(devid, sc, sc->mem, &status);
-	if (ah == NULL) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to attach hardware; HAL status %u\n",
-			__func__, status);
-		error = -ENXIO;
-		goto bad;
-	}
-	sc->sc_ah = ah;
-
-	/* Get the hardware key cache size. */
-	sc->sc_keymax = ah->ah_caps.keycache_size;
-	if (sc->sc_keymax > ATH_KEYMAX) {
-		DPRINTF(sc, ATH_DBG_KEYCACHE,
-			"%s: Warning, using only %u entries in %u key cache\n",
-			__func__, ATH_KEYMAX, sc->sc_keymax);
-		sc->sc_keymax = ATH_KEYMAX;
-	}
-
-	/*
-	 * Reset the key cache since some parts do not
-	 * reset the contents on initial power up.
-	 */
-	for (i = 0; i < sc->sc_keymax; i++)
-		ath9k_hw_keyreset(ah, (u16) i);
-	/*
-	 * Mark key cache slots associated with global keys
-	 * as in use.  If we knew TKIP was not to be used we
-	 * could leave the +32, +64, and +32+64 slots free.
-	 * XXX only for splitmic.
-	 */
-	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
-		set_bit(i, sc->sc_keymap);
-		set_bit(i + 32, sc->sc_keymap);
-		set_bit(i + 64, sc->sc_keymap);
-		set_bit(i + 32 + 64, sc->sc_keymap);
-	}
-
-	/* Collect the channel list using the default country code */
-
-	error = ath_setup_channels(sc);
-	if (error)
-		goto bad;
-
-	/* default to MONITOR mode */
-	sc->sc_ah->ah_opmode = ATH9K_M_MONITOR;
-
-	/* Setup rate tables */
-
-	ath_rate_attach(sc);
-	ath_setup_rates(sc, IEEE80211_BAND_2GHZ);
-	ath_setup_rates(sc, IEEE80211_BAND_5GHZ);
-
-	/*
-	 * Allocate hardware transmit queues: one queue for
-	 * beacon frames and one data queue for each QoS
-	 * priority.  Note that the hal handles reseting
-	 * these queues at the needed time.
-	 */
-	sc->sc_bhalq = ath_beaconq_setup(ah);
-	if (sc->sc_bhalq == -1) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to setup a beacon xmit queue\n", __func__);
-		error = -EIO;
-		goto bad2;
-	}
-	sc->sc_cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
-	if (sc->sc_cabq == NULL) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to setup CAB xmit queue\n", __func__);
-		error = -EIO;
-		goto bad2;
-	}
-
-	sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME;
-	ath_cabq_update(sc);
-
-	for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++)
-		sc->sc_haltype2q[i] = -1;
-
-	/* Setup data queues */
-	/* NB: ensure BK queue is the lowest priority h/w queue */
-	if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to setup xmit queue for BK traffic\n",
-			__func__);
-		error = -EIO;
-		goto bad2;
-	}
-
-	if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to setup xmit queue for BE traffic\n",
-			__func__);
-		error = -EIO;
-		goto bad2;
-	}
-	if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to setup xmit queue for VI traffic\n",
-			__func__);
-		error = -EIO;
-		goto bad2;
-	}
-	if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: unable to setup xmit queue for VO traffic\n",
-			__func__);
-		error = -EIO;
-		goto bad2;
-	}
-
-	/* Initializes the noise floor to a reasonable default value.
-	 * Later on this will be updated during ANI processing. */
-
-	sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
-	setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc);
-
-	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
-				   ATH9K_CIPHER_TKIP, NULL)) {
-		/*
-		 * Whether we should enable h/w TKIP MIC.
-		 * XXX: if we don't support WME TKIP MIC, then we wouldn't
-		 * report WMM capable, so it's always safe to turn on
-		 * TKIP MIC in this case.
-		 */
-		ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC,
-				       0, 1, NULL);
-	}
-
-	/*
-	 * Check whether the separate key cache entries
-	 * are required to handle both tx+rx MIC keys.
-	 * With split mic keys the number of stations is limited
-	 * to 27 otherwise 59.
-	 */
-	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
-				   ATH9K_CIPHER_TKIP, NULL)
-	    && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
-				      ATH9K_CIPHER_MIC, NULL)
-	    && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
-				      0, NULL))
-		sc->sc_splitmic = 1;
-
-	/* turn on mcast key search if possible */
-	if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
-		(void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1,
-					     1, NULL);
-
-	sc->sc_config.txpowlimit = ATH_TXPOWER_MAX;
-	sc->sc_config.txpowlimit_override = 0;
-
-	/* 11n Capabilities */
-	if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
-		sc->sc_flags |= SC_OP_TXAGGR;
-		sc->sc_flags |= SC_OP_RXAGGR;
-	}
-
-	sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
-	sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
-
-	ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
-	sc->sc_defant = ath9k_hw_getdefantenna(ah);
-
-	ath9k_hw_getmac(ah, sc->sc_myaddr);
-	if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) {
-		ath9k_hw_getbssidmask(ah, sc->sc_bssidmask);
-		ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask);
-		ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
-	}
-
-	sc->sc_slottime = ATH9K_SLOT_TIME_9;	/* default to short slot time */
-
-	/* initialize beacon slots */
-	for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++)
-		sc->sc_bslot[i] = ATH_IF_ID_ANY;
-
-	/* save MISC configurations */
-	sc->sc_config.swBeaconProcess = 1;
-
-#ifdef CONFIG_SLOW_ANT_DIV
-	/* range is 40 - 255, we use something in the middle */
-	ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127);
-#endif
-
-	/* setup channels and rates */
-
-	sc->sbands[IEEE80211_BAND_2GHZ].channels =
-		sc->channels[IEEE80211_BAND_2GHZ];
-	sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
-		sc->rates[IEEE80211_BAND_2GHZ];
-	sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
-
-	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
-		sc->sbands[IEEE80211_BAND_5GHZ].channels =
-			sc->channels[IEEE80211_BAND_5GHZ];
-		sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
-			sc->rates[IEEE80211_BAND_5GHZ];
-		sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
-	}
-
-	return 0;
-bad2:
-	/* cleanup tx queues */
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_tx_cleanupq(sc, &sc->sc_txq[i]);
-bad:
-	if (ah)
-		ath9k_hw_detach(ah);
-
-	return error;
-}
-
-/*******************/
-/* Node Management */
-/*******************/
-
-void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
-{
-	struct ath_node *an;
-
-	an = (struct ath_node *)sta->drv_priv;
-
-	if (sc->sc_flags & SC_OP_TXAGGR)
-		ath_tx_node_init(sc, an);
-
-	an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
-			     sta->ht_cap.ampdu_factor);
-	an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
-
-	ath_chainmask_sel_init(sc, an);
-	ath_chainmask_sel_timerstart(&an->an_chainmask_sel);
-}
-
-void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
-{
-	struct ath_node *an = (struct ath_node *)sta->drv_priv;
-
-	ath_chainmask_sel_timerstop(&an->an_chainmask_sel);
-
-	if (sc->sc_flags & SC_OP_TXAGGR)
-		ath_tx_node_cleanup(sc, an);
-}
-
-/*
- * Set up New Node
- *
- * Setup driver-specific state for a newly associated node.  This routine
- * really only applies if compression or XR are enabled, there is no code
- * covering any other cases.
-*/
-
-void ath_newassoc(struct ath_softc *sc,
-	struct ath_node *an, int isnew, int isuapsd)
-{
-	int tidno;
-
-	/* if station reassociates, tear down the aggregation state. */
-	if (!isnew) {
-		for (tidno = 0; tidno < WME_NUM_TID; tidno++) {
-			if (sc->sc_flags & SC_OP_TXAGGR)
-				ath_tx_aggr_teardown(sc, an, tidno);
-		}
-	}
-}
-
-/**************/
-/* Encryption */
-/**************/
-
-void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot)
-{
-	ath9k_hw_keyreset(sc->sc_ah, keyix);
-	if (freeslot)
-		clear_bit(keyix, sc->sc_keymap);
-}
-
-int ath_keyset(struct ath_softc *sc,
-	       u16 keyix,
-	       struct ath9k_keyval *hk,
-	       const u8 mac[ETH_ALEN])
-{
-	bool status;
-
-	status = ath9k_hw_set_keycache_entry(sc->sc_ah,
-		keyix, hk, mac, false);
-
-	return status != false;
-}
-
-/***********************/
-/* TX Power/Regulatory */
-/***********************/
-
-/*
- *  Set Transmit power in HAL
- *
- *  This routine makes the actual HAL calls to set the new transmit power
- *  limit.
-*/
-
-void ath_update_txpow(struct ath_softc *sc)
-{
-	struct ath_hal *ah = sc->sc_ah;
-	u32 txpow;
-
-	if (sc->sc_curtxpow != sc->sc_config.txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit);
-		/* read back in case value is clamped */
-		ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
-		sc->sc_curtxpow = txpow;
-	}
-}
-
-/**************************/
-/* Slow Antenna Diversity */
-/**************************/
-
-void ath_slow_ant_div_init(struct ath_antdiv *antdiv,
-			   struct ath_softc *sc,
-			   int32_t rssitrig)
-{
-	int trig;
-
-	/* antdivf_rssitrig can range from 40 - 0xff */
-	trig = (rssitrig > 0xff) ? 0xff : rssitrig;
-	trig = (rssitrig < 40) ? 40 : rssitrig;
-
-	antdiv->antdiv_sc = sc;
-	antdiv->antdivf_rssitrig = trig;
-}
-
-void ath_slow_ant_div_start(struct ath_antdiv *antdiv,
-			    u8 num_antcfg,
-			    const u8 *bssid)
-{
-	antdiv->antdiv_num_antcfg =
-		num_antcfg < ATH_ANT_DIV_MAX_CFG ?
-		num_antcfg : ATH_ANT_DIV_MAX_CFG;
-	antdiv->antdiv_state = ATH_ANT_DIV_IDLE;
-	antdiv->antdiv_curcfg = 0;
-	antdiv->antdiv_bestcfg = 0;
-	antdiv->antdiv_laststatetsf = 0;
-
-	memcpy(antdiv->antdiv_bssid, bssid, sizeof(antdiv->antdiv_bssid));
-
-	antdiv->antdiv_start = 1;
-}
-
-void ath_slow_ant_div_stop(struct ath_antdiv *antdiv)
-{
-	antdiv->antdiv_start = 0;
-}
-
-static int32_t ath_find_max_val(int32_t *val,
-	u8 num_val, u8 *max_index)
-{
-	u32 MaxVal = *val++;
-	u32 cur_index = 0;
-
-	*max_index = 0;
-	while (++cur_index < num_val) {
-		if (*val > MaxVal) {
-			MaxVal = *val;
-			*max_index = cur_index;
-		}
-
-		val++;
-	}
-
-	return MaxVal;
-}
-
-void ath_slow_ant_div(struct ath_antdiv *antdiv,
-		      struct ieee80211_hdr *hdr,
-		      struct ath_rx_status *rx_stats)
-{
-	struct ath_softc *sc = antdiv->antdiv_sc;
-	struct ath_hal *ah = sc->sc_ah;
-	u64 curtsf = 0;
-	u8 bestcfg, curcfg = antdiv->antdiv_curcfg;
-	__le16 fc = hdr->frame_control;
-
-	if (antdiv->antdiv_start && ieee80211_is_beacon(fc)
-	    && !compare_ether_addr(hdr->addr3, antdiv->antdiv_bssid)) {
-		antdiv->antdiv_lastbrssi[curcfg] = rx_stats->rs_rssi;
-		antdiv->antdiv_lastbtsf[curcfg] = ath9k_hw_gettsf64(sc->sc_ah);
-		curtsf = antdiv->antdiv_lastbtsf[curcfg];
-	} else {
-		return;
-	}
-
-	switch (antdiv->antdiv_state) {
-	case ATH_ANT_DIV_IDLE:
-		if ((antdiv->antdiv_lastbrssi[curcfg] <
-		     antdiv->antdivf_rssitrig)
-		    && ((curtsf - antdiv->antdiv_laststatetsf) >
-			ATH_ANT_DIV_MIN_IDLE_US)) {
-
-			curcfg++;
-			if (curcfg == antdiv->antdiv_num_antcfg)
-				curcfg = 0;
-
-			if (!ath9k_hw_select_antconfig(ah, curcfg)) {
-				antdiv->antdiv_bestcfg = antdiv->antdiv_curcfg;
-				antdiv->antdiv_curcfg = curcfg;
-				antdiv->antdiv_laststatetsf = curtsf;
-				antdiv->antdiv_state = ATH_ANT_DIV_SCAN;
-			}
-		}
-		break;
-
-	case ATH_ANT_DIV_SCAN:
-		if ((curtsf - antdiv->antdiv_laststatetsf) <
-		    ATH_ANT_DIV_MIN_SCAN_US)
-			break;
-
-		curcfg++;
-		if (curcfg == antdiv->antdiv_num_antcfg)
-			curcfg = 0;
-
-		if (curcfg == antdiv->antdiv_bestcfg) {
-			ath_find_max_val(antdiv->antdiv_lastbrssi,
-				   antdiv->antdiv_num_antcfg, &bestcfg);
-			if (!ath9k_hw_select_antconfig(ah, bestcfg)) {
-				antdiv->antdiv_bestcfg = bestcfg;
-				antdiv->antdiv_curcfg = bestcfg;
-				antdiv->antdiv_laststatetsf = curtsf;
-				antdiv->antdiv_state = ATH_ANT_DIV_IDLE;
-			}
-		} else {
-			if (!ath9k_hw_select_antconfig(ah, curcfg)) {
-				antdiv->antdiv_curcfg = curcfg;
-				antdiv->antdiv_laststatetsf = curtsf;
-				antdiv->antdiv_state = ATH_ANT_DIV_SCAN;
-			}
-		}
-
-		break;
-	}
-}
-
-/***********************/
-/* Descriptor Handling */
-/***********************/
-
-/*
- *  Set up DMA descriptors
- *
- *  This function will allocate both the DMA descriptor structure, and the
- *  buffers it contains.  These are used to contain the descriptors used
- *  by the system.
-*/
-
-int ath_descdma_setup(struct ath_softc *sc,
-		      struct ath_descdma *dd,
-		      struct list_head *head,
-		      const char *name,
-		      int nbuf,
-		      int ndesc)
-{
-#define	DS2PHYS(_dd, _ds)						\
-	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
-#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
-#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
-
-	struct ath_desc *ds;
-	struct ath_buf *bf;
-	int i, bsize, error;
-
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA: %u buffers %u desc/buf\n",
-		__func__, name, nbuf, ndesc);
-
-	/* ath_desc must be a multiple of DWORDs */
-	if ((sizeof(struct ath_desc) % 4) != 0) {
-		DPRINTF(sc, ATH_DBG_FATAL, "%s: ath_desc not DWORD aligned\n",
-			__func__);
-		ASSERT((sizeof(struct ath_desc) % 4) == 0);
-		error = -ENOMEM;
-		goto fail;
-	}
-
-	dd->dd_name = name;
-	dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
-
-	/*
-	 * Need additional DMA memory because we can't use
-	 * descriptors that cross the 4K page boundary. Assume
-	 * one skipped descriptor per 4K page.
-	 */
-	if (!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
-		u32 ndesc_skipped =
-			ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
-		u32 dma_len;
-
-		while (ndesc_skipped) {
-			dma_len = ndesc_skipped * sizeof(struct ath_desc);
-			dd->dd_desc_len += dma_len;
-
-			ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
-		};
-	}
-
-	/* allocate descriptors */
-	dd->dd_desc = pci_alloc_consistent(sc->pdev,
-			      dd->dd_desc_len,
-			      &dd->dd_desc_paddr);
-	if (dd->dd_desc == NULL) {
-		error = -ENOMEM;
-		goto fail;
-	}
-	ds = dd->dd_desc;
-	DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA map: %p (%u) -> %llx (%u)\n",
-		__func__, dd->dd_name, ds, (u32) dd->dd_desc_len,
-		ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
-
-	/* allocate buffers */
-	bsize = sizeof(struct ath_buf) * nbuf;
-	bf = kmalloc(bsize, GFP_KERNEL);
-	if (bf == NULL) {
-		error = -ENOMEM;
-		goto fail2;
-	}
-	memset(bf, 0, bsize);
-	dd->dd_bufptr = bf;
-
-	INIT_LIST_HEAD(head);
-	for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
-		bf->bf_desc = ds;
-		bf->bf_daddr = DS2PHYS(dd, ds);
-
-		if (!(sc->sc_ah->ah_caps.hw_caps &
-		      ATH9K_HW_CAP_4KB_SPLITTRANS)) {
-			/*
-			 * Skip descriptor addresses which can cause 4KB
-			 * boundary crossing (addr + length) with a 32 dword
-			 * descriptor fetch.
-			 */
-			while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
-				ASSERT((caddr_t) bf->bf_desc <
-				       ((caddr_t) dd->dd_desc +
-					dd->dd_desc_len));
-
-				ds += ndesc;
-				bf->bf_desc = ds;
-				bf->bf_daddr = DS2PHYS(dd, ds);
-			}
-		}
-		list_add_tail(&bf->list, head);
-	}
-	return 0;
-fail2:
-	pci_free_consistent(sc->pdev,
-		dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
-fail:
-	memset(dd, 0, sizeof(*dd));
-	return error;
-#undef ATH_DESC_4KB_BOUND_CHECK
-#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
-#undef DS2PHYS
-}
-
-/*
- *  Cleanup DMA descriptors
- *
- *  This function will free the DMA block that was allocated for the descriptor
- *  pool.  Since this was allocated as one "chunk", it is freed in the same
- *  manner.
-*/
-
-void ath_descdma_cleanup(struct ath_softc *sc,
-			 struct ath_descdma *dd,
-			 struct list_head *head)
-{
-	/* Free memory associated with descriptors */
-	pci_free_consistent(sc->pdev,
-		dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
-
-	INIT_LIST_HEAD(head);
-	kfree(dd->dd_bufptr);
-	memset(dd, 0, sizeof(*dd));
-}
-
-/*************/
-/* Utilities */
-/*************/
-
-int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
-{
-	int qnum;
-
-	switch (queue) {
-	case 0:
-		qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO];
-		break;
-	case 1:
-		qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI];
-		break;
-	case 2:
-		qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
-		break;
-	case 3:
-		qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK];
-		break;
-	default:
-		qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
-		break;
-	}
-
-	return qnum;
-}
-
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
-{
-	int qnum;
-
-	switch (queue) {
-	case ATH9K_WME_AC_VO:
-		qnum = 0;
-		break;
-	case ATH9K_WME_AC_VI:
-		qnum = 1;
-		break;
-	case ATH9K_WME_AC_BE:
-		qnum = 2;
-		break;
-	case ATH9K_WME_AC_BK:
-		qnum = 3;
-		break;
-	default:
-		qnum = -1;
-		break;
-	}
-
-	return qnum;
-}
-
-
-/*
- *  Expand time stamp to TSF
- *
- *  Extend 15-bit time stamp from rx descriptor to
- *  a full 64-bit TSF using the current h/w TSF.
-*/
-
-u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
-{
-	u64 tsf;
-
-	tsf = ath9k_hw_gettsf64(sc->sc_ah);
-	if ((tsf & 0x7fff) < rstamp)
-		tsf -= 0x8000;
-	return (tsf & ~0x7fff) | rstamp;
-}
-
-/*
- *  Set Default Antenna
- *
- *  Call into the HAL to set the default antenna to use.  Not really valid for
- *  MIMO technology.
-*/
-
-void ath_setdefantenna(void *context, u32 antenna)
-{
-	struct ath_softc *sc = (struct ath_softc *)context;
-	struct ath_hal *ah = sc->sc_ah;
-
-	/* XXX block beacon interrupts */
-	ath9k_hw_setantenna(ah, antenna);
-	sc->sc_defant = antenna;
-	sc->sc_rxotherant = 0;
-}
-
-/*
- * Set Slot Time
- *
- * This will wake up the chip if required, and set the slot time for the
- * frame (maximum transmit time).  Slot time is assumed to be already set
- * in the ATH object member sc_slottime
-*/
-
-void ath_setslottime(struct ath_softc *sc)
-{
-	ath9k_hw_setslottime(sc->sc_ah, sc->sc_slottime);
-	sc->sc_updateslot = OK;
-}
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index e672556..21ee0c2 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -47,10 +47,6 @@
 
 struct ath_node;
 
-/******************/
-/* Utility macros */
-/******************/
-
 /* Macro to expand scalars to 64-bit objects */
 
 #define	ito64(x) (sizeof(x) == 8) ?			\
@@ -86,11 +82,6 @@ struct ath_node;
 
 #define	ATH_TXQ_SETUP(sc, i)        ((sc)->sc_txqsetup & (1<<i))
 
-static inline unsigned long get_timestamp(void)
-{
-	return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ);
-}
-
 static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 /*************/
@@ -141,34 +132,6 @@ struct ath_config {
 	u8 swBeaconProcess; /* Process received beacons in SW (vs HW) */
 };
 
-/***********************/
-/* Chainmask Selection */
-/***********************/
-
-#define ATH_CHAINMASK_SEL_TIMEOUT	   6000
-/* Default - Number of last RSSI values that is used for
- * chainmask selection */
-#define ATH_CHAINMASK_SEL_RSSI_CNT	   10
-/* Means use 3x3 chainmask instead of configured chainmask */
-#define ATH_CHAINMASK_SEL_3X3		   7
-/* Default - Rssi threshold below which we have to switch to 3x3 */
-#define ATH_CHAINMASK_SEL_UP_RSSI_THRES	   20
-/* Default - Rssi threshold above which we have to switch to
- * user configured values */
-#define ATH_CHAINMASK_SEL_DOWN_RSSI_THRES  35
-/* Struct to store the chainmask select related info */
-struct ath_chainmask_sel {
-	struct timer_list timer;
-	int cur_tx_mask; 	/* user configured or 3x3 */
-	int cur_rx_mask; 	/* user configured or 3x3 */
-	int tx_avgrssi;
-	u8 switch_allowed:1, 	/* timer will set this */
-	   cm_sel_enabled : 1;
-};
-
-int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an);
-void ath_update_chainmask(struct ath_softc *sc, int is_ht);
-
 /*************************/
 /* Descriptor Management */
 /*************************/
@@ -240,7 +203,6 @@ struct ath_buf {
 					   an aggregate) */
 	struct ath_buf *bf_lastfrm;	/* last buf of this frame */
 	struct ath_buf *bf_next;	/* next subframe in the aggregate */
-	struct ath_buf *bf_rifslast;	/* last buf for RIFS burst */
 	void *bf_mpdu;			/* enclosing frame structure */
 	struct ath_desc *bf_desc;	/* virtual addr of desc */
 	dma_addr_t bf_daddr;		/* physical addr of desc */
@@ -278,16 +240,10 @@ struct ath_descdma {
 	dma_addr_t dd_dmacontext;
 };
 
-int ath_descdma_setup(struct ath_softc *sc,
-		      struct ath_descdma *dd,
-		      struct list_head *head,
-		      const char *name,
-		      int nbuf,
-		      int ndesc);
-int ath_desc_alloc(struct ath_softc *sc);
-void ath_desc_free(struct ath_softc *sc);
-void ath_descdma_cleanup(struct ath_softc *sc,
-			 struct ath_descdma *dd,
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+		      struct list_head *head, const char *name,
+		      int nbuf, int ndesc);
+void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
 			 struct list_head *head);
 
 /***********/
@@ -452,7 +408,6 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
 void ath_tx_tasklet(struct ath_softc *sc);
 u32 ath_txq_depth(struct ath_softc *sc, int qnum);
 u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
-void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth);
 void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
 
 /**********************/
@@ -517,25 +472,18 @@ struct ath_node_aggr {
 /* driver-specific node state */
 struct ath_node {
 	struct ath_softc *an_sc;
-	struct ath_chainmask_sel an_chainmask_sel;
 	struct ath_node_aggr an_aggr;
 	u16 maxampdu;
 	u8 mpdudensity;
 };
 
-void ath_tx_resume_tid(struct ath_softc *sc,
-	struct ath_atx_tid *tid);
+void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
 bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
-void ath_tx_aggr_teardown(struct ath_softc *sc,
-	struct ath_node *an, u8 tidno);
+void ath_tx_aggr_teardown(struct ath_softc *sc,	struct ath_node *an, u8 tidno);
 int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
 		      u16 tid, u16 *ssn);
 int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
 void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-void ath_newassoc(struct ath_softc *sc,
-	struct ath_node *node, int isnew, int isuapsd);
-void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta);
-void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta);
 
 /********/
 /* VAPs */
@@ -593,49 +541,8 @@ void ath9k_beacon_tasklet(unsigned long data);
 void ath_beacon_config(struct ath_softc *sc, int if_id);
 int ath_beaconq_setup(struct ath_hal *ah);
 int ath_beacon_alloc(struct ath_softc *sc, int if_id);
-void ath_bstuck_process(struct ath_softc *sc);
 void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp);
 void ath_beacon_sync(struct ath_softc *sc, int if_id);
-void ath_get_beaconconfig(struct ath_softc *sc,
-			  int if_id,
-			  struct ath_beacon_config *conf);
-/*********************/
-/* Antenna diversity */
-/*********************/
-
-#define ATH_ANT_DIV_MAX_CFG      2
-#define ATH_ANT_DIV_MIN_IDLE_US  1000000  /* us */
-#define ATH_ANT_DIV_MIN_SCAN_US  50000	  /* us */
-
-enum ATH_ANT_DIV_STATE{
-	ATH_ANT_DIV_IDLE,
-	ATH_ANT_DIV_SCAN,	/* evaluating antenna */
-};
-
-struct ath_antdiv {
-	struct ath_softc *antdiv_sc;
-	u8 antdiv_start;
-	enum ATH_ANT_DIV_STATE antdiv_state;
-	u8 antdiv_num_antcfg;
-	u8 antdiv_curcfg;
-	u8 antdiv_bestcfg;
-	int32_t antdivf_rssitrig;
-	int32_t antdiv_lastbrssi[ATH_ANT_DIV_MAX_CFG];
-	u64 antdiv_lastbtsf[ATH_ANT_DIV_MAX_CFG];
-	u64 antdiv_laststatetsf;
-	u8 antdiv_bssid[ETH_ALEN];
-};
-
-void ath_slow_ant_div_init(struct ath_antdiv *antdiv,
-	struct ath_softc *sc, int32_t rssitrig);
-void ath_slow_ant_div_start(struct ath_antdiv *antdiv,
-			    u8 num_antcfg,
-			    const u8 *bssid);
-void ath_slow_ant_div_stop(struct ath_antdiv *antdiv);
-void ath_slow_ant_div(struct ath_antdiv *antdiv,
-		      struct ieee80211_hdr *wh,
-		      struct ath_rx_status *rx_stats);
-void ath_setdefantenna(void *sc, u32 antenna);
 
 /*******/
 /* ANI */
@@ -717,30 +624,8 @@ struct ath_rfkill {
 
 #define ATH_IF_ID_ANY   	0xff
 #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
-
-#define RSSI_LPF_THRESHOLD         -20
-#define ATH_RSSI_EP_MULTIPLIER     (1<<7)  /* pow2 to optimize out * and / */
-#define ATH_RATE_DUMMY_MARKER      0
-#define ATH_RSSI_LPF_LEN           10
-#define ATH_RSSI_DUMMY_MARKER      0x127
-
-#define ATH_EP_MUL(x, mul)         ((x) * (mul))
-#define ATH_EP_RND(x, mul)						\
-	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
-#define ATH_RSSI_OUT(x)							\
-	(((x) != ATH_RSSI_DUMMY_MARKER) ?				\
-	 (ATH_EP_RND((x), ATH_RSSI_EP_MULTIPLIER)) : ATH_RSSI_DUMMY_MARKER)
-#define ATH_RSSI_IN(x)					\
-	(ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
-#define ATH_LPF_RSSI(x, y, len)						\
-	((x != ATH_RSSI_DUMMY_MARKER) ? \
-		(((x) * ((len) - 1) + (y)) / (len)) : (y))
-#define ATH_RSSI_LPF(x, y) do {						\
-		if ((y) >= RSSI_LPF_THRESHOLD)				\
-			x = ATH_LPF_RSSI((x), \
-				ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \
-	} while (0)
-
+#define ATH_RSSI_DUMMY_MARKER   0x127
+#define ATH_RATE_DUMMY_MARKER   0
 
 enum PROT_MODE {
 	PROT_M_NONE = 0,
@@ -748,12 +633,6 @@ enum PROT_MODE {
 	PROT_M_CTSONLY
 };
 
-enum RATE_TYPE {
-	NORMAL_RATE = 0,
-	HALF_RATE,
-	QUARTER_RATE
-};
-
 struct ath_ht_info {
 	enum ath9k_ht_macmode tx_chan_width;
 	u8 ext_chan_offset;
@@ -881,27 +760,9 @@ struct ath_softc {
 	struct ath_ani sc_ani;
 };
 
-int ath_init(u16 devid, struct ath_softc *sc);
-int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan);
-void ath_stop(struct ath_softc *sc);
-irqreturn_t ath_isr(int irq, void *dev);
 int ath_reset(struct ath_softc *sc, bool retry_tx);
-int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan);
-
-/*********************/
-/* Utility Functions */
-/*********************/
-
-void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot);
-int ath_keyset(struct ath_softc *sc,
-	       u16 keyix,
-	       struct ath9k_keyval *hk,
-	       const u8 mac[ETH_ALEN]);
 int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
 int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
-void ath_setslottime(struct ath_softc *sc);
-void ath_update_txpow(struct ath_softc *sc);
 int ath_cabq_update(struct ath_softc *);
-u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp);
 
 #endif /* CORE_H */
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 27be0d9..8eccc20 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -14,8 +14,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* mac80211 and PCI callbacks */
-
 #include <linux/nl80211.h>
 #include "core.h"
 #include "reg.h"
@@ -40,6 +38,580 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = {
 
 static void ath_detach(struct ath_softc *sc);
 
+/* return bus cachesize in 4B word units */
+
+static void bus_read_cachesize(struct ath_softc *sc, int *csz)
+{
+	u8 u8tmp;
+
+	pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, (u8 *)&u8tmp);
+	*csz = (int)u8tmp;
+
+	/*
+	 * This check was put in to avoid "unplesant" consequences if
+	 * the bootrom has not fully initialized all PCI devices.
+	 * Sometimes the cache line size register is not set
+	 */
+
+	if (*csz == 0)
+		*csz = DEFAULT_CACHELINE >> 2;   /* Use the default size */
+}
+
+static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
+{
+	sc->sc_curmode = mode;
+	/*
+	 * All protection frames are transmited at 2Mb/s for
+	 * 11g, otherwise at 1Mb/s.
+	 * XXX select protection rate index from rate table.
+	 */
+	sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0);
+}
+
+static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan)
+{
+	if (chan->chanmode == CHANNEL_A)
+		return ATH9K_MODE_11A;
+	else if (chan->chanmode == CHANNEL_G)
+		return ATH9K_MODE_11G;
+	else if (chan->chanmode == CHANNEL_B)
+		return ATH9K_MODE_11B;
+	else if (chan->chanmode == CHANNEL_A_HT20)
+		return ATH9K_MODE_11NA_HT20;
+	else if (chan->chanmode == CHANNEL_G_HT20)
+		return ATH9K_MODE_11NG_HT20;
+	else if (chan->chanmode == CHANNEL_A_HT40PLUS)
+		return ATH9K_MODE_11NA_HT40PLUS;
+	else if (chan->chanmode == CHANNEL_A_HT40MINUS)
+		return ATH9K_MODE_11NA_HT40MINUS;
+	else if (chan->chanmode == CHANNEL_G_HT40PLUS)
+		return ATH9K_MODE_11NG_HT40PLUS;
+	else if (chan->chanmode == CHANNEL_G_HT40MINUS)
+		return ATH9K_MODE_11NG_HT40MINUS;
+
+	WARN_ON(1); /* should not get here */
+
+	return ATH9K_MODE_11B;
+}
+
+static void ath_update_txpow(struct ath_softc *sc)
+{
+	struct ath_hal *ah = sc->sc_ah;
+	u32 txpow;
+
+	if (sc->sc_curtxpow != sc->sc_config.txpowlimit) {
+		ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit);
+		/* read back in case value is clamped */
+		ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
+		sc->sc_curtxpow = txpow;
+	}
+}
+
+static u8 parse_mpdudensity(u8 mpdudensity)
+{
+	/*
+	 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
+	 *   0 for no restriction
+	 *   1 for 1/4 us
+	 *   2 for 1/2 us
+	 *   3 for 1 us
+	 *   4 for 2 us
+	 *   5 for 4 us
+	 *   6 for 8 us
+	 *   7 for 16 us
+	 */
+	switch (mpdudensity) {
+	case 0:
+		return 0;
+	case 1:
+	case 2:
+	case 3:
+		/* Our lower layer calculations limit our precision to
+		   1 microsecond */
+		return 1;
+	case 4:
+		return 2;
+	case 5:
+		return 4;
+	case 6:
+		return 8;
+	case 7:
+		return 16;
+	default:
+		return 0;
+	}
+}
+
+static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
+{
+	struct ath_rate_table *rate_table = NULL;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_rate *rate;
+	int i, maxrates;
+
+	switch (band) {
+	case IEEE80211_BAND_2GHZ:
+		rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
+		break;
+	case IEEE80211_BAND_5GHZ:
+		rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
+		break;
+	default:
+		break;
+	}
+
+	if (rate_table == NULL)
+		return;
+
+	sband = &sc->sbands[band];
+	rate = sc->rates[band];
+
+	if (rate_table->rate_cnt > ATH_RATE_MAX)
+		maxrates = ATH_RATE_MAX;
+	else
+		maxrates = rate_table->rate_cnt;
+
+	for (i = 0; i < maxrates; i++) {
+		rate[i].bitrate = rate_table->info[i].ratekbps / 100;
+		rate[i].hw_value = rate_table->info[i].ratecode;
+		sband->n_bitrates++;
+		DPRINTF(sc, ATH_DBG_CONFIG, "%s: Rate: %2dMbps, ratecode: %2d\n",
+			__func__, rate[i].bitrate / 10,	rate[i].hw_value);
+	}
+}
+
+static int ath_setup_channels(struct ath_softc *sc)
+{
+	struct ath_hal *ah = sc->sc_ah;
+	int nchan, i, a = 0, b = 0;
+	u8 regclassids[ATH_REGCLASSIDS_MAX];
+	u32 nregclass = 0;
+	struct ieee80211_supported_band *band_2ghz;
+	struct ieee80211_supported_band *band_5ghz;
+	struct ieee80211_channel *chan_2ghz;
+	struct ieee80211_channel *chan_5ghz;
+	struct ath9k_channel *c;
+
+	/* Fill in ah->ah_channels */
+	if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan,
+				      regclassids, ATH_REGCLASSIDS_MAX,
+				      &nregclass, CTRY_DEFAULT, false, 1)) {
+		u32 rd = ah->ah_currentRD;
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to collect channel list; "
+			"regdomain likely %u country code %u\n",
+			__func__, rd, CTRY_DEFAULT);
+		return -EINVAL;
+	}
+
+	band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ];
+	band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ];
+	chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ];
+	chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ];
+
+	for (i = 0; i < nchan; i++) {
+		c = &ah->ah_channels[i];
+		if (IS_CHAN_2GHZ(c)) {
+			chan_2ghz[a].band = IEEE80211_BAND_2GHZ;
+			chan_2ghz[a].center_freq = c->channel;
+			chan_2ghz[a].max_power = c->maxTxPower;
+
+			if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
+				chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS;
+			if (c->channelFlags & CHANNEL_PASSIVE)
+				chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+			band_2ghz->n_channels = ++a;
+
+			DPRINTF(sc, ATH_DBG_CONFIG, "%s: 2MHz channel: %d, "
+				"channelFlags: 0x%x\n",
+				__func__, c->channel, c->channelFlags);
+		} else if (IS_CHAN_5GHZ(c)) {
+			chan_5ghz[b].band = IEEE80211_BAND_5GHZ;
+			chan_5ghz[b].center_freq = c->channel;
+			chan_5ghz[b].max_power = c->maxTxPower;
+
+			if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
+				chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS;
+			if (c->channelFlags & CHANNEL_PASSIVE)
+				chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+			band_5ghz->n_channels = ++b;
+
+			DPRINTF(sc, ATH_DBG_CONFIG, "%s: 5MHz channel: %d, "
+				"channelFlags: 0x%x\n",
+				__func__, c->channel, c->channelFlags);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Set/change channels.  If the channel is really being changed, it's done
+ * by reseting the chip.  To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+*/
+static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
+{
+	struct ath_hal *ah = sc->sc_ah;
+	bool fastcc = true, stopped;
+
+	if (sc->sc_flags & SC_OP_INVALID)
+		return -EIO;
+
+	DPRINTF(sc, ATH_DBG_CONFIG,
+		"%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n",
+		__func__,
+		ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel,
+				  sc->sc_ah->ah_curchan->channelFlags),
+		sc->sc_ah->ah_curchan->channel,
+		ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags),
+		hchan->channel, hchan->channelFlags);
+
+	if (hchan->channel != sc->sc_ah->ah_curchan->channel ||
+	    hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags ||
+	    (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) ||
+	    (sc->sc_flags & SC_OP_FULL_RESET)) {
+		int status;
+		/*
+		 * This is only performed if the channel settings have
+		 * actually changed.
+		 *
+		 * To switch channels clear any pending DMA operations;
+		 * wait long enough for the RX fifo to drain, reset the
+		 * hardware at the new frequency, and then re-enable
+		 * the relevant bits of the h/w.
+		 */
+		ath9k_hw_set_interrupts(ah, 0);	/* disable interrupts */
+		ath_draintxq(sc, false);	/* clear pending tx frames */
+		stopped = ath_stoprecv(sc);	/* turn off frame recv */
+
+		/* XXX: do not flush receive queue here. We don't want
+		 * to flush data frames already in queue because of
+		 * changing channel. */
+
+		if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
+			fastcc = false;
+
+		spin_lock_bh(&sc->sc_resetlock);
+		if (!ath9k_hw_reset(ah, hchan, sc->sc_ht_info.tx_chan_width,
+				    sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+				    sc->sc_ht_extprotspacing, fastcc, &status)) {
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"%s: unable to reset channel %u (%uMhz) "
+				"flags 0x%x hal status %u\n", __func__,
+				ath9k_hw_mhz2ieee(ah, hchan->channel,
+						  hchan->channelFlags),
+				hchan->channel, hchan->channelFlags, status);
+			spin_unlock_bh(&sc->sc_resetlock);
+			return -EIO;
+		}
+		spin_unlock_bh(&sc->sc_resetlock);
+
+		sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
+		sc->sc_flags &= ~SC_OP_FULL_RESET;
+
+		if (ath_startrecv(sc) != 0) {
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"%s: unable to restart recv logic\n", __func__);
+			return -EIO;
+		}
+
+		ath_setcurmode(sc, ath_chan2mode(hchan));
+		ath_update_txpow(sc);
+		ath9k_hw_set_interrupts(ah, sc->sc_imask);
+	}
+	return 0;
+}
+
+/*
+ *  This routine performs the periodic noise floor calibration function
+ *  that is used to adjust and optimize the chip performance.  This
+ *  takes environmental changes (location, temperature) into account.
+ *  When the task is complete, it reschedules itself depending on the
+ *  appropriate interval that was calculated.
+ */
+static void ath_ani_calibrate(unsigned long data)
+{
+	struct ath_softc *sc;
+	struct ath_hal *ah;
+	bool longcal = false;
+	bool shortcal = false;
+	bool aniflag = false;
+	unsigned int timestamp = jiffies_to_msecs(jiffies);
+	u32 cal_interval;
+
+	sc = (struct ath_softc *)data;
+	ah = sc->sc_ah;
+
+	/*
+	* don't calibrate when we're scanning.
+	* we are most likely not on our home channel.
+	*/
+	if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)
+		return;
+
+	/* Long calibration runs independently of short calibration. */
+	if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) {
+		longcal = true;
+		DPRINTF(sc, ATH_DBG_ANI, "%s: longcal @%lu\n",
+			__func__, jiffies);
+		sc->sc_ani.sc_longcal_timer = timestamp;
+	}
+
+	/* Short calibration applies only while sc_caldone is false */
+	if (!sc->sc_ani.sc_caldone) {
+		if ((timestamp - sc->sc_ani.sc_shortcal_timer) >=
+		    ATH_SHORT_CALINTERVAL) {
+			shortcal = true;
+			DPRINTF(sc, ATH_DBG_ANI, "%s: shortcal @%lu\n",
+			       __func__, jiffies);
+			sc->sc_ani.sc_shortcal_timer = timestamp;
+			sc->sc_ani.sc_resetcal_timer = timestamp;
+		}
+	} else {
+		if ((timestamp - sc->sc_ani.sc_resetcal_timer) >=
+		    ATH_RESTART_CALINTERVAL) {
+			ath9k_hw_reset_calvalid(ah, ah->ah_curchan,
+						&sc->sc_ani.sc_caldone);
+			if (sc->sc_ani.sc_caldone)
+				sc->sc_ani.sc_resetcal_timer = timestamp;
+		}
+	}
+
+	/* Verify whether we must check ANI */
+	if ((timestamp - sc->sc_ani.sc_checkani_timer) >=
+	   ATH_ANI_POLLINTERVAL) {
+		aniflag = true;
+		sc->sc_ani.sc_checkani_timer = timestamp;
+	}
+
+	/* Skip all processing if there's nothing to do. */
+	if (longcal || shortcal || aniflag) {
+		/* Call ANI routine if necessary */
+		if (aniflag)
+			ath9k_hw_ani_monitor(ah, &sc->sc_halstats,
+					     ah->ah_curchan);
+
+		/* Perform calibration if necessary */
+		if (longcal || shortcal) {
+			bool iscaldone = false;
+
+			if (ath9k_hw_calibrate(ah, ah->ah_curchan,
+					       sc->sc_rx_chainmask, longcal,
+					       &iscaldone)) {
+				if (longcal)
+					sc->sc_ani.sc_noise_floor =
+						ath9k_hw_getchan_noise(ah,
+							       ah->ah_curchan);
+
+				DPRINTF(sc, ATH_DBG_ANI,
+					"%s: calibrate chan %u/%x nf: %d\n",
+					 __func__,
+					ah->ah_curchan->channel,
+					ah->ah_curchan->channelFlags,
+					sc->sc_ani.sc_noise_floor);
+			} else {
+				DPRINTF(sc, ATH_DBG_ANY,
+					"%s: calibrate chan %u/%x failed\n",
+					 __func__,
+					ah->ah_curchan->channel,
+					ah->ah_curchan->channelFlags);
+			}
+			sc->sc_ani.sc_caldone = iscaldone;
+		}
+	}
+
+	/*
+	* Set timer interval based on previous results.
+	* The interval must be the shortest necessary to satisfy ANI,
+	* short calibration and long calibration.
+	*/
+
+	cal_interval = ATH_ANI_POLLINTERVAL;
+	if (!sc->sc_ani.sc_caldone)
+		cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL);
+
+	mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
+}
+
+/*
+ * Update tx/rx chainmask. For legacy association,
+ * hard code chainmask to 1x1, for 11n association, use
+ * the chainmask configuration.
+ */
+static void ath_update_chainmask(struct ath_softc *sc, int is_ht)
+{
+	sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
+	if (is_ht) {
+		sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask;
+		sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask;
+	} else {
+		sc->sc_tx_chainmask = 1;
+		sc->sc_rx_chainmask = 1;
+	}
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "%s: tx chmask: %d, rx chmask: %d\n",
+		__func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask);
+}
+
+static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
+{
+	struct ath_node *an;
+
+	an = (struct ath_node *)sta->drv_priv;
+
+	if (sc->sc_flags & SC_OP_TXAGGR)
+		ath_tx_node_init(sc, an);
+
+	an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
+			     sta->ht_cap.ampdu_factor);
+	an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
+}
+
+static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
+{
+	struct ath_node *an = (struct ath_node *)sta->drv_priv;
+
+	if (sc->sc_flags & SC_OP_TXAGGR)
+		ath_tx_node_cleanup(sc, an);
+}
+
+static void ath9k_tasklet(unsigned long data)
+{
+	struct ath_softc *sc = (struct ath_softc *)data;
+	u32 status = sc->sc_intrstatus;
+
+	if (status & ATH9K_INT_FATAL) {
+		/* need a chip reset */
+		ath_reset(sc, false);
+		return;
+	} else {
+
+		if (status &
+		    (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
+			spin_lock_bh(&sc->sc_rxflushlock);
+			ath_rx_tasklet(sc, 0);
+			spin_unlock_bh(&sc->sc_rxflushlock);
+		}
+		/* XXX: optimize this */
+		if (status & ATH9K_INT_TX)
+			ath_tx_tasklet(sc);
+	}
+
+	/* re-enable hardware interrupt */
+	ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask);
+}
+
+static irqreturn_t ath_isr(int irq, void *dev)
+{
+	struct ath_softc *sc = dev;
+	struct ath_hal *ah = sc->sc_ah;
+	enum ath9k_int status;
+	bool sched = false;
+
+	do {
+		if (sc->sc_flags & SC_OP_INVALID) {
+			/*
+			 * The hardware is not ready/present, don't
+			 * touch anything. Note this can happen early
+			 * on if the IRQ is shared.
+			 */
+			return IRQ_NONE;
+		}
+		if (!ath9k_hw_intrpend(ah)) {	/* shared irq, not for us */
+			return IRQ_NONE;
+		}
+
+		/*
+		 * Figure out the reason(s) for the interrupt.  Note
+		 * that the hal returns a pseudo-ISR that may include
+		 * bits we haven't explicitly enabled so we mask the
+		 * value to insure we only process bits we requested.
+		 */
+		ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */
+
+		status &= sc->sc_imask;	/* discard unasked-for bits */
+
+		/*
+		 * If there are no status bits set, then this interrupt was not
+		 * for me (should have been caught above).
+		 */
+		if (!status)
+			return IRQ_NONE;
+
+		sc->sc_intrstatus = status;
+
+		if (status & ATH9K_INT_FATAL) {
+			/* need a chip reset */
+			sched = true;
+		} else if (status & ATH9K_INT_RXORN) {
+			/* need a chip reset */
+			sched = true;
+		} else {
+			if (status & ATH9K_INT_SWBA) {
+				/* schedule a tasklet for beacon handling */
+				tasklet_schedule(&sc->bcon_tasklet);
+			}
+			if (status & ATH9K_INT_RXEOL) {
+				/*
+				 * NB: the hardware should re-read the link when
+				 *     RXE bit is written, but it doesn't work
+				 *     at least on older hardware revs.
+				 */
+				sched = true;
+			}
+
+			if (status & ATH9K_INT_TXURN)
+				/* bump tx trigger level */
+				ath9k_hw_updatetxtriglevel(ah, true);
+			/* XXX: optimize this */
+			if (status & ATH9K_INT_RX)
+				sched = true;
+			if (status & ATH9K_INT_TX)
+				sched = true;
+			if (status & ATH9K_INT_BMISS)
+				sched = true;
+			/* carrier sense timeout */
+			if (status & ATH9K_INT_CST)
+				sched = true;
+			if (status & ATH9K_INT_MIB) {
+				/*
+				 * Disable interrupts until we service the MIB
+				 * interrupt; otherwise it will continue to
+				 * fire.
+				 */
+				ath9k_hw_set_interrupts(ah, 0);
+				/*
+				 * Let the hal handle the event. We assume
+				 * it will clear whatever condition caused
+				 * the interrupt.
+				 */
+				ath9k_hw_procmibevent(ah, &sc->sc_halstats);
+				ath9k_hw_set_interrupts(ah, sc->sc_imask);
+			}
+			if (status & ATH9K_INT_TIM_TIMER) {
+				if (!(ah->ah_caps.hw_caps &
+				      ATH9K_HW_CAP_AUTOSLEEP)) {
+					/* Clear RxAbort bit so that we can
+					 * receive frames */
+					ath9k_hw_setrxabort(ah, 0);
+					sched = true;
+				}
+			}
+		}
+	} while (0);
+
+	if (sched) {
+		/* turn off every interrupt except SWBA */
+		ath9k_hw_set_interrupts(ah, (sc->sc_imask & ATH9K_INT_SWBA));
+		tasklet_schedule(&sc->intr_tq);
+	}
+
+	return IRQ_HANDLED;
+}
+
 static int ath_get_channel(struct ath_softc *sc,
 			   struct ieee80211_channel *chan)
 {
@@ -90,6 +662,23 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
 	return chanmode;
 }
 
+static void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot)
+{
+	ath9k_hw_keyreset(sc->sc_ah, keyix);
+	if (freeslot)
+		clear_bit(keyix, sc->sc_keymap);
+}
+
+static int ath_keyset(struct ath_softc *sc, u16 keyix,
+	       struct ath9k_keyval *hk, const u8 mac[ETH_ALEN])
+{
+	bool status;
+
+	status = ath9k_hw_set_keycache_entry(sc->sc_ah,
+		keyix, hk, mac, false);
+
+	return status != false;
+}
 
 static int ath_setkey_tkip(struct ath_softc *sc,
 			   struct ieee80211_key_conf *key,
@@ -328,20 +917,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
 	}
 }
 
-void ath_get_beaconconfig(struct ath_softc *sc,
-			  int if_id,
-			  struct ath_beacon_config *conf)
-{
-	struct ieee80211_hw *hw = sc->hw;
-
-	/* fill in beacon config data */
-
-	conf->beacon_interval = hw->conf.beacon_int;
-	conf->listen_interval = 100;
-	conf->dtim_count = 1;
-	conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
-}
-
 /********************************/
 /*	 LED functions		*/
 /********************************/
@@ -723,6 +1298,244 @@ static void ath_detach(struct ath_softc *sc)
 	ath9k_hw_detach(sc->sc_ah);
 }
 
+static int ath_init(u16 devid, struct ath_softc *sc)
+{
+	struct ath_hal *ah = NULL;
+	int status;
+	int error = 0, i;
+	int csz = 0;
+
+	/* XXX: hardware will not be ready until ath_open() being called */
+	sc->sc_flags |= SC_OP_INVALID;
+	sc->sc_debug = DBG_DEFAULT;
+
+	spin_lock_init(&sc->sc_resetlock);
+	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
+	tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
+		     (unsigned long)sc);
+
+	/*
+	 * Cache line size is used to size and align various
+	 * structures used to communicate with the hardware.
+	 */
+	bus_read_cachesize(sc, &csz);
+	/* XXX assert csz is non-zero */
+	sc->sc_cachelsz = csz << 2;	/* convert to bytes */
+
+	ah = ath9k_hw_attach(devid, sc, sc->mem, &status);
+	if (ah == NULL) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to attach hardware; HAL status %u\n",
+			__func__, status);
+		error = -ENXIO;
+		goto bad;
+	}
+	sc->sc_ah = ah;
+
+	/* Get the hardware key cache size. */
+	sc->sc_keymax = ah->ah_caps.keycache_size;
+	if (sc->sc_keymax > ATH_KEYMAX) {
+		DPRINTF(sc, ATH_DBG_KEYCACHE,
+			"%s: Warning, using only %u entries in %u key cache\n",
+			__func__, ATH_KEYMAX, sc->sc_keymax);
+		sc->sc_keymax = ATH_KEYMAX;
+	}
+
+	/*
+	 * Reset the key cache since some parts do not
+	 * reset the contents on initial power up.
+	 */
+	for (i = 0; i < sc->sc_keymax; i++)
+		ath9k_hw_keyreset(ah, (u16) i);
+	/*
+	 * Mark key cache slots associated with global keys
+	 * as in use.  If we knew TKIP was not to be used we
+	 * could leave the +32, +64, and +32+64 slots free.
+	 * XXX only for splitmic.
+	 */
+	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+		set_bit(i, sc->sc_keymap);
+		set_bit(i + 32, sc->sc_keymap);
+		set_bit(i + 64, sc->sc_keymap);
+		set_bit(i + 32 + 64, sc->sc_keymap);
+	}
+
+	/* Collect the channel list using the default country code */
+
+	error = ath_setup_channels(sc);
+	if (error)
+		goto bad;
+
+	/* default to MONITOR mode */
+	sc->sc_ah->ah_opmode = ATH9K_M_MONITOR;
+
+	/* Setup rate tables */
+
+	ath_rate_attach(sc);
+	ath_setup_rates(sc, IEEE80211_BAND_2GHZ);
+	ath_setup_rates(sc, IEEE80211_BAND_5GHZ);
+
+	/*
+	 * Allocate hardware transmit queues: one queue for
+	 * beacon frames and one data queue for each QoS
+	 * priority.  Note that the hal handles reseting
+	 * these queues at the needed time.
+	 */
+	sc->sc_bhalq = ath_beaconq_setup(ah);
+	if (sc->sc_bhalq == -1) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to setup a beacon xmit queue\n", __func__);
+		error = -EIO;
+		goto bad2;
+	}
+	sc->sc_cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
+	if (sc->sc_cabq == NULL) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to setup CAB xmit queue\n", __func__);
+		error = -EIO;
+		goto bad2;
+	}
+
+	sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME;
+	ath_cabq_update(sc);
+
+	for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++)
+		sc->sc_haltype2q[i] = -1;
+
+	/* Setup data queues */
+	/* NB: ensure BK queue is the lowest priority h/w queue */
+	if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to setup xmit queue for BK traffic\n",
+			__func__);
+		error = -EIO;
+		goto bad2;
+	}
+
+	if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to setup xmit queue for BE traffic\n",
+			__func__);
+		error = -EIO;
+		goto bad2;
+	}
+	if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to setup xmit queue for VI traffic\n",
+			__func__);
+		error = -EIO;
+		goto bad2;
+	}
+	if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to setup xmit queue for VO traffic\n",
+			__func__);
+		error = -EIO;
+		goto bad2;
+	}
+
+	/* Initializes the noise floor to a reasonable default value.
+	 * Later on this will be updated during ANI processing. */
+
+	sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
+	setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc);
+
+	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+				   ATH9K_CIPHER_TKIP, NULL)) {
+		/*
+		 * Whether we should enable h/w TKIP MIC.
+		 * XXX: if we don't support WME TKIP MIC, then we wouldn't
+		 * report WMM capable, so it's always safe to turn on
+		 * TKIP MIC in this case.
+		 */
+		ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC,
+				       0, 1, NULL);
+	}
+
+	/*
+	 * Check whether the separate key cache entries
+	 * are required to handle both tx+rx MIC keys.
+	 * With split mic keys the number of stations is limited
+	 * to 27 otherwise 59.
+	 */
+	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+				   ATH9K_CIPHER_TKIP, NULL)
+	    && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+				      ATH9K_CIPHER_MIC, NULL)
+	    && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
+				      0, NULL))
+		sc->sc_splitmic = 1;
+
+	/* turn on mcast key search if possible */
+	if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
+		(void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1,
+					     1, NULL);
+
+	sc->sc_config.txpowlimit = ATH_TXPOWER_MAX;
+	sc->sc_config.txpowlimit_override = 0;
+
+	/* 11n Capabilities */
+	if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
+		sc->sc_flags |= SC_OP_TXAGGR;
+		sc->sc_flags |= SC_OP_RXAGGR;
+	}
+
+	sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
+	sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
+
+	ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
+	sc->sc_defant = ath9k_hw_getdefantenna(ah);
+
+	ath9k_hw_getmac(ah, sc->sc_myaddr);
+	if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) {
+		ath9k_hw_getbssidmask(ah, sc->sc_bssidmask);
+		ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask);
+		ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
+	}
+
+	sc->sc_slottime = ATH9K_SLOT_TIME_9;	/* default to short slot time */
+
+	/* initialize beacon slots */
+	for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++)
+		sc->sc_bslot[i] = ATH_IF_ID_ANY;
+
+	/* save MISC configurations */
+	sc->sc_config.swBeaconProcess = 1;
+
+#ifdef CONFIG_SLOW_ANT_DIV
+	/* range is 40 - 255, we use something in the middle */
+	ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127);
+#endif
+
+	/* setup channels and rates */
+
+	sc->sbands[IEEE80211_BAND_2GHZ].channels =
+		sc->channels[IEEE80211_BAND_2GHZ];
+	sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
+		sc->rates[IEEE80211_BAND_2GHZ];
+	sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+
+	if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
+		sc->sbands[IEEE80211_BAND_5GHZ].channels =
+			sc->channels[IEEE80211_BAND_5GHZ];
+		sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
+			sc->rates[IEEE80211_BAND_5GHZ];
+		sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
+	}
+
+	return 0;
+bad2:
+	/* cleanup tx queues */
+	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+		if (ATH_TXQ_SETUP(sc, i))
+			ath_tx_cleanupq(sc, &sc->sc_txq[i]);
+bad:
+	if (ah)
+		ath9k_hw_detach(ah);
+
+	return error;
+}
+
 static int ath_attach(u16 devid, struct ath_softc *sc)
 {
 	struct ieee80211_hw *hw = sc->hw;
@@ -811,11 +1624,243 @@ bad:
 	return error;
 }
 
+int ath_reset(struct ath_softc *sc, bool retry_tx)
+{
+	struct ath_hal *ah = sc->sc_ah;
+	int status;
+	int error = 0;
+
+	ath9k_hw_set_interrupts(ah, 0);
+	ath_draintxq(sc, retry_tx);
+	ath_stoprecv(sc);
+	ath_flushrecv(sc);
+
+	spin_lock_bh(&sc->sc_resetlock);
+	if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan,
+			    sc->sc_ht_info.tx_chan_width,
+			    sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+			    sc->sc_ht_extprotspacing, false, &status)) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to reset hardware; hal status %u\n",
+			__func__, status);
+		error = -EIO;
+	}
+	spin_unlock_bh(&sc->sc_resetlock);
+
+	if (ath_startrecv(sc) != 0)
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to start recv logic\n", __func__);
+
+	/*
+	 * We may be doing a reset in response to a request
+	 * that changes the channel so update any state that
+	 * might change as a result.
+	 */
+	ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan));
+
+	ath_update_txpow(sc);
+
+	if (sc->sc_flags & SC_OP_BEACONS)
+		ath_beacon_config(sc, ATH_IF_ID_ANY);	/* restart beacons */
+
+	ath9k_hw_set_interrupts(ah, sc->sc_imask);
+
+	if (retry_tx) {
+		int i;
+		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+			if (ATH_TXQ_SETUP(sc, i)) {
+				spin_lock_bh(&sc->sc_txq[i].axq_lock);
+				ath_txq_schedule(sc, &sc->sc_txq[i]);
+				spin_unlock_bh(&sc->sc_txq[i].axq_lock);
+			}
+		}
+	}
+
+	return error;
+}
+
+/*
+ *  This function will allocate both the DMA descriptor structure, and the
+ *  buffers it contains.  These are used to contain the descriptors used
+ *  by the system.
+*/
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+		      struct list_head *head, const char *name,
+		      int nbuf, int ndesc)
+{
+#define	DS2PHYS(_dd, _ds)						\
+	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
+
+	struct ath_desc *ds;
+	struct ath_buf *bf;
+	int i, bsize, error;
+
+	DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA: %u buffers %u desc/buf\n",
+		__func__, name, nbuf, ndesc);
+
+	/* ath_desc must be a multiple of DWORDs */
+	if ((sizeof(struct ath_desc) % 4) != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL, "%s: ath_desc not DWORD aligned\n",
+			__func__);
+		ASSERT((sizeof(struct ath_desc) % 4) == 0);
+		error = -ENOMEM;
+		goto fail;
+	}
+
+	dd->dd_name = name;
+	dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
+
+	/*
+	 * Need additional DMA memory because we can't use
+	 * descriptors that cross the 4K page boundary. Assume
+	 * one skipped descriptor per 4K page.
+	 */
+	if (!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+		u32 ndesc_skipped =
+			ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
+		u32 dma_len;
+
+		while (ndesc_skipped) {
+			dma_len = ndesc_skipped * sizeof(struct ath_desc);
+			dd->dd_desc_len += dma_len;
+
+			ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
+		};
+	}
+
+	/* allocate descriptors */
+	dd->dd_desc = pci_alloc_consistent(sc->pdev,
+			      dd->dd_desc_len,
+			      &dd->dd_desc_paddr);
+	if (dd->dd_desc == NULL) {
+		error = -ENOMEM;
+		goto fail;
+	}
+	ds = dd->dd_desc;
+	DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA map: %p (%u) -> %llx (%u)\n",
+		__func__, dd->dd_name, ds, (u32) dd->dd_desc_len,
+		ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
+
+	/* allocate buffers */
+	bsize = sizeof(struct ath_buf) * nbuf;
+	bf = kmalloc(bsize, GFP_KERNEL);
+	if (bf == NULL) {
+		error = -ENOMEM;
+		goto fail2;
+	}
+	memset(bf, 0, bsize);
+	dd->dd_bufptr = bf;
+
+	INIT_LIST_HEAD(head);
+	for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
+		bf->bf_desc = ds;
+		bf->bf_daddr = DS2PHYS(dd, ds);
+
+		if (!(sc->sc_ah->ah_caps.hw_caps &
+		      ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+			/*
+			 * Skip descriptor addresses which can cause 4KB
+			 * boundary crossing (addr + length) with a 32 dword
+			 * descriptor fetch.
+			 */
+			while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
+				ASSERT((caddr_t) bf->bf_desc <
+				       ((caddr_t) dd->dd_desc +
+					dd->dd_desc_len));
+
+				ds += ndesc;
+				bf->bf_desc = ds;
+				bf->bf_daddr = DS2PHYS(dd, ds);
+			}
+		}
+		list_add_tail(&bf->list, head);
+	}
+	return 0;
+fail2:
+	pci_free_consistent(sc->pdev,
+		dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
+fail:
+	memset(dd, 0, sizeof(*dd));
+	return error;
+#undef ATH_DESC_4KB_BOUND_CHECK
+#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
+#undef DS2PHYS
+}
+
+void ath_descdma_cleanup(struct ath_softc *sc,
+			 struct ath_descdma *dd,
+			 struct list_head *head)
+{
+	pci_free_consistent(sc->pdev,
+		dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
+
+	INIT_LIST_HEAD(head);
+	kfree(dd->dd_bufptr);
+	memset(dd, 0, sizeof(*dd));
+}
+
+int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
+{
+	int qnum;
+
+	switch (queue) {
+	case 0:
+		qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO];
+		break;
+	case 1:
+		qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI];
+		break;
+	case 2:
+		qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
+		break;
+	case 3:
+		qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK];
+		break;
+	default:
+		qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
+		break;
+	}
+
+	return qnum;
+}
+
+int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
+{
+	int qnum;
+
+	switch (queue) {
+	case ATH9K_WME_AC_VO:
+		qnum = 0;
+		break;
+	case ATH9K_WME_AC_VI:
+		qnum = 1;
+		break;
+	case ATH9K_WME_AC_BE:
+		qnum = 2;
+		break;
+	case ATH9K_WME_AC_BK:
+		qnum = 3;
+		break;
+	default:
+		qnum = -1;
+		break;
+	}
+
+	return qnum;
+}
+
+/**********************/
+/* mac80211 callbacks */
+/**********************/
+
 static int ath9k_start(struct ieee80211_hw *hw)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ieee80211_channel *curchan = hw->conf.channel;
-	int error = 0, pos;
+	struct ath9k_channel *init_channel;
+	int error = 0, pos, status;
 
 	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with "
 		"initial channel: %d MHz\n", __func__, curchan->center_freq);
@@ -828,24 +1873,103 @@ static int ath9k_start(struct ieee80211_hw *hw)
 	if (pos == -1) {
 		DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
 		error = -EINVAL;
-		goto exit;
+		goto error;
 	}
 
 	sc->sc_ah->ah_channels[pos].chanmode =
 		(curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A;
+	init_channel = &sc->sc_ah->ah_channels[pos];
 
-	error = ath_open(sc, &sc->sc_ah->ah_channels[pos]);
-	if (error) {
+	/* Reset SERDES registers */
+	ath9k_hw_configpcipowersave(sc->sc_ah, 0);
+
+	/*
+	 * The basic interface to setting the hardware in a good
+	 * state is ``reset''.  On return the hardware is known to
+	 * be powered up and with interrupts disabled.  This must
+	 * be followed by initialization of the appropriate bits
+	 * and then setup of the interrupt mask.
+	 */
+	spin_lock_bh(&sc->sc_resetlock);
+	if (!ath9k_hw_reset(sc->sc_ah, init_channel,
+			    sc->sc_ht_info.tx_chan_width,
+			    sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+			    sc->sc_ht_extprotspacing, false, &status)) {
 		DPRINTF(sc, ATH_DBG_FATAL,
-			"%s: Unable to complete ath_open\n", __func__);
-		goto exit;
+			"%s: unable to reset hardware; hal status %u "
+			"(freq %u flags 0x%x)\n", __func__, status,
+			init_channel->channel, init_channel->channelFlags);
+		error = -EIO;
+		spin_unlock_bh(&sc->sc_resetlock);
+		goto error;
 	}
+	spin_unlock_bh(&sc->sc_resetlock);
+
+	/*
+	 * This is needed only to setup initial state
+	 * but it's best done after a reset.
+	 */
+	ath_update_txpow(sc);
+
+	/*
+	 * Setup the hardware after reset:
+	 * The receive engine is set going.
+	 * Frame transmit is handled entirely
+	 * in the frame output path; there's nothing to do
+	 * here except setup the interrupt mask.
+	 */
+	if (ath_startrecv(sc) != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"%s: unable to start recv logic\n", __func__);
+		error = -EIO;
+		goto error;
+	}
+
+	/* Setup our intr mask. */
+	sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX
+		| ATH9K_INT_RXEOL | ATH9K_INT_RXORN
+		| ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
+
+	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_GTT)
+		sc->sc_imask |= ATH9K_INT_GTT;
+
+	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
+		sc->sc_imask |= ATH9K_INT_CST;
+
+	/*
+	 * Enable MIB interrupts when there are hardware phy counters.
+	 * Note we only do this (at the moment) for station mode.
+	 */
+	if (ath9k_hw_phycounters(sc->sc_ah) &&
+	    ((sc->sc_ah->ah_opmode == ATH9K_M_STA) ||
+	     (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)))
+		sc->sc_imask |= ATH9K_INT_MIB;
+	/*
+	 * Some hardware processes the TIM IE and fires an
+	 * interrupt when the TIM bit is set.  For hardware
+	 * that does, if not overridden by configuration,
+	 * enable the TIM interrupt when operating as station.
+	 */
+	if ((sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
+	    (sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
+	    !sc->sc_config.swBeaconProcess)
+		sc->sc_imask |= ATH9K_INT_TIM;
+
+	ath_setcurmode(sc, ath_chan2mode(init_channel));
+
+	sc->sc_flags &= ~SC_OP_INVALID;
+
+	/* Disable BMISS interrupt when we're not associated */
+	sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+	ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask);
+
+	ieee80211_wake_queues(sc->hw);
 
 #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
 	error = ath_start_rfkill_poll(sc);
 #endif
 
-exit:
+error:
 	return error;
 }
 
@@ -912,7 +2036,30 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 		return;
 	}
 
-	ath_stop(sc);
+	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Cleaning up\n", __func__);
+
+	ieee80211_stop_queues(sc->hw);
+
+	/* make sure h/w will not generate any interrupt
+	 * before setting the invalid flag. */
+	ath9k_hw_set_interrupts(sc->sc_ah, 0);
+
+	if (!(sc->sc_flags & SC_OP_INVALID)) {
+		ath_draintxq(sc, false);
+		ath_stoprecv(sc);
+		ath9k_hw_phy_disable(sc->sc_ah);
+	} else
+		sc->sc_rxlink = NULL;
+
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+	if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+		cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
+#endif
+	/* disable HAL and put h/w to sleep */
+	ath9k_hw_disable(sc->sc_ah);
+	ath9k_hw_configpcipowersave(sc->sc_ah, 1);
+
+	sc->sc_flags |= SC_OP_INVALID;
 
 	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__);
 }
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index 7d1913d..93dfea8 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -1401,7 +1401,6 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
 	struct ath_softc *sc = priv;
 	struct ath_rate_priv *ath_rc_priv = priv_sta;
 	struct ath_tx_info_priv *tx_info_priv = NULL;
-	struct ath_node *an;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr;
 	int final_ts_idx, tx_status = 0, is_underrun = 0;
@@ -1410,21 +1409,15 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
 	hdr = (struct ieee80211_hdr *)skb->data;
 	fc = hdr->frame_control;
 	tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
-	an = (struct ath_node *)sta->drv_priv;
 	final_ts_idx = tx_info_priv->tx.ts_rateindex;
 
-	if (!an || !priv_sta || !ieee80211_is_data(fc) ||
+	if (!priv_sta || !ieee80211_is_data(fc) ||
 	    !tx_info_priv->update_rc)
 		goto exit;
 
 	if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT)
 		goto exit;
 
-	if (tx_info_priv->tx.ts_rssi > 0) {
-		ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi,
-			     tx_info_priv->tx.ts_rssi);
-	}
-
 	/*
 	 * If underrun error is seen assume it as an excessive retry only
 	 * if prefetch trigger level have reached the max (0x3f for 5416)
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c
index 0cd2a91..e0e345e 100644
--- a/drivers/net/wireless/ath9k/recv.c
+++ b/drivers/net/wireless/ath9k/recv.c
@@ -57,6 +57,28 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
 	ath9k_hw_rxena(ah);
 }
 
+static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
+{
+	/* XXX block beacon interrupts */
+	ath9k_hw_setantenna(sc->sc_ah, antenna);
+	sc->sc_defant = antenna;
+	sc->sc_rxotherant = 0;
+}
+
+/*
+ *  Extend 15-bit time stamp from rx descriptor to
+ *  a full 64-bit TSF using the current h/w TSF.
+*/
+static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
+{
+	u64 tsf;
+
+	tsf = ath9k_hw_gettsf64(sc->sc_ah);
+	if ((tsf & 0x7fff) < rstamp)
+		tsf -= 0x8000;
+	return (tsf & ~0x7fff) | rstamp;
+}
+
 static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len)
 {
 	struct sk_buff *skb;
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index dad81a9..3de60c5 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -147,6 +147,19 @@ static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno)
 		return 0;
 }
 
+static void ath_get_beaconconfig(struct ath_softc *sc, int if_id,
+				 struct ath_beacon_config *conf)
+{
+	struct ieee80211_hw *hw = sc->hw;
+
+	/* fill in beacon config data */
+
+	conf->beacon_interval = hw->conf.beacon_int;
+	conf->listen_interval = 100;
+	conf->dtim_count = 1;
+	conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
+}
+
 /* Calculate Atheros packet type from IEEE80211 packet header */
 
 static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
@@ -522,7 +535,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
 	struct ath_desc *ds = bf->bf_desc;
 	struct ath_desc *lastds = bf->bf_lastbf->bf_desc;
 	struct ath9k_11n_rate_series series[4];
-	struct ath_node *an = NULL;
 	struct sk_buff *skb;
 	struct ieee80211_tx_info *tx_info;
 	struct ieee80211_tx_rate *rates;
@@ -540,9 +552,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
 	tx_info = IEEE80211_SKB_CB(skb);
 	rates = tx_info->control.rates;
 
-	if (tx_info->control.sta)
-		an = (struct ath_node *)tx_info->control.sta->drv_priv;
-
 	if (ieee80211_has_morefrags(fc) ||
 	    (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
 		rates[1].count = rates[2].count = rates[3].count = 0;
@@ -632,10 +641,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
 			 (rates[i].flags & IEEE80211_TX_RC_SHORT_GI),
 			 bf_isshpreamble(bf));
 
-		if (bf_isht(bf) && an)
-			series[i].ChSel = ath_chainmask_sel_logic(sc, an);
-		else
-			series[i].ChSel = sc->sc_tx_chainmask;
+		series[i].ChSel = sc->sc_tx_chainmask;
 
 		if (rtsctsena)
 			series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-- 
1.6.0.3

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux