Skip to contentSkip to conversation

ath9k: pending patches

PATCH In review Luis R. Rodriguez 3 participants 8 messages Oct 4, 2008 – Oct 5, 2008 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

cover ath9k: pending patches

This is the list of pending patches for wireless-testing for ath9k. I hadn't ported over today's fix so its going in this series.

Luis

#1 lore raw

PATCH 1/3 ath9k: kill ath9k's memzero() and use memset() instead

Part of the cleanup on ath9k -- this was also causing some annoying compile time warnings.

---
 drivers/net/wireless/ath9k/beacon.c |    8 ++++----
 drivers/net/wireless/ath9k/core.c   |   14 +++++++-------
 drivers/net/wireless/ath9k/core.h   |    5 +----
 drivers/net/wireless/ath9k/recv.c   |    4 ++--
 drivers/net/wireless/ath9k/xmit.c   |   10 +++++-----
 5 files changed, 19 insertions(+), 22 deletions(-)
drivers/net/wireless/ath9k/beacon.c +4 -4
index eedb465..9e15c30 100644
@@ -129,7 +129,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
 			    ds                    /* first descriptor */
 		);
 
-	memzero(series, sizeof(struct ath9k_11n_rate_series) * 4);
+	memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
 	series[0].Tries = 1;
 	series[0].Rate = rate;
 	series[0].ChSel = sc->sc_tx_chainmask;
@@ -282,7 +282,7 @@ int ath_beaconq_setup(struct ath_hal *ah)
 {
 	struct ath9k_tx_queue_info qi;
 
-	memzero(&qi, sizeof(qi));
+	memset(&qi, 0, sizeof(qi));
 	qi.tqi_aifs = 1;
 	qi.tqi_cwmin = 0;
 	qi.tqi_cwmax = 0;
@@ -662,7 +662,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
 	else
 		av_opmode = sc->sc_ah->ah_opmode;
 
-	memzero(&conf, sizeof(struct ath_beacon_config));
+	memset(&conf, 0, sizeof(struct ath_beacon_config));
 
 	conf.beacon_interval = sc->hw->conf.beacon_int ?
 		sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
@@ -738,7 +738,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
 			}
 		} while (nexttbtt < tsftu);
 #undef FUDGE
-		memzero(&bs, sizeof(bs));
+		memset(&bs, 0, sizeof(bs));
 		bs.bs_intval = intval;
 		bs.bs_nexttbtt = nexttbtt;
 		bs.bs_dtimperiod = dtimperiod*intval;
drivers/net/wireless/ath9k/core.c +7 -7
index d7f5257..5af7dfb 100644
@@ -65,7 +65,7 @@ static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
 	for (i = 0; i < rt->rateCount; i++)
 		sc->sc_rixmap[rt->info[i].rateCode] = (u8) i;
 
-	memzero(sc->sc_hwmap, sizeof(sc->sc_hwmap));
+	memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap));
 	for (i = 0; i < 256; i++) {
 		u8 ix = rt->rateCodeToIndex[i];
 
@@ -417,7 +417,7 @@ static void ath_chainmask_sel_init(struct ath_softc *sc, struct ath_node *an)
 {
 	struct ath_chainmask_sel *cm = &an->an_chainmask_sel;
 
-	memzero(cm, sizeof(struct ath_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;
@@ -526,7 +526,7 @@ int ath_vap_attach(struct ath_softc *sc,
 	if (avp == NULL)
 		return -ENOMEM;
 
-	memzero(avp, sizeof(struct ath_vap));
+	memset(avp, 0, sizeof(struct ath_vap));
 	avp->av_if_data = if_data;
 	/* Set the VAP opmode */
 	avp->av_opmode = opmode;
@@ -1219,7 +1219,7 @@ struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id)
 	an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC);
 	if (an == NULL)
 		return NULL;
-	memzero(an, sizeof(*an));
+	memset(an, 0, sizeof(*an));
 
 	an->an_sc = sc;
 	memcpy(an->an_addr, addr, ETH_ALEN);
@@ -1606,7 +1606,7 @@ int ath_descdma_setup(struct ath_softc *sc,
 		error = -ENOMEM;
 		goto fail2;
 	}
-	memzero(bf, bsize);
+	memset(bf, 0, bsize);
 	dd->dd_bufptr = bf;
 
 	INIT_LIST_HEAD(head);
@@ -1638,7 +1638,7 @@ fail2:
 	pci_free_consistent(sc->pdev,
 		dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
 fail:
-	memzero(dd, sizeof(*dd));
+	memset(dd, 0, sizeof(*dd));
 	return error;
 #undef ATH_DESC_4KB_BOUND_CHECK
 #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
@@ -1663,7 +1663,7 @@ void ath_descdma_cleanup(struct ath_softc *sc,
 
 	INIT_LIST_HEAD(head);
 	kfree(dd->dd_bufptr);
-	memzero(dd, sizeof(*dd));
+	memset(dd, 0, sizeof(*dd));
 }
 
 /*************/
drivers/net/wireless/ath9k/core.h +1 -4
index 872f0c5..80814c9 100644
@@ -84,9 +84,6 @@ struct ath_node;
 #define TSF_TO_TU(_h,_l) \
 	((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
 
-/* XXX: remove */
-#define memzero(_buf, _len) memset(_buf, 0, _len)
-
 #define ATH9K_BH_STATUS_INTACT		0
 #define ATH9K_BH_STATUS_CHANGE		1
 
@@ -184,7 +181,7 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht);
 		(_bf)->bf_lastbf = NULL;			\
 		(_bf)->bf_lastfrm = NULL;			\
 		(_bf)->bf_next = NULL;				\
-		memzero(&((_bf)->bf_state),			\
+		memset(&((_bf)->bf_state), 0,			\
 			    sizeof(struct ath_buf_state));	\
 	} while (0)
 
drivers/net/wireless/ath9k/recv.c +2 -2
index 4982563..f4be5d1 100644
@@ -892,7 +892,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 
 		hdr = (struct ieee80211_hdr *)skb->data;
 		fc = hdr->frame_control;
-		memzero(&rx_status, sizeof(struct ath_recv_status));
+		memset(&rx_status, 0, sizeof(struct ath_recv_status));
 
 		if (ds->ds_rxstat.rs_more) {
 			/*
@@ -1166,7 +1166,7 @@ int ath_rx_aggr_start(struct ath_softc *sc,
 		} else {
 			/* Ensure the memory is zeroed out (all internal
 			 * pointers are null) */
-			memzero(rxtid->rxbuf, ATH_TID_MAX_BUFS *
+			memset(rxtid->rxbuf, 0, ATH_TID_MAX_BUFS *
 				sizeof(struct ath_rxbuf));
 			DPRINTF(sc, ATH_DBG_AGGR,
 				"%s: Allocated @%p\n", __func__, rxtid->rxbuf);
drivers/net/wireless/ath9k/xmit.c +5 -5
index 2592905..bdcb9e1 100644
@@ -729,7 +729,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
 	/*
 	 * Setup HAL rate series
 	 */
-	memzero(series, sizeof(struct ath9k_11n_rate_series) * 4);
+	memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
 
 	for (i = 0; i < 4; i++) {
 		if (!bf->bf_rcs[i].tries)
@@ -817,7 +817,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
 		 * Disable multi-rate retry when using RTS/CTS by clearing
 		 * series 1, 2 and 3.
 		 */
-		memzero(&series[1], sizeof(struct ath9k_11n_rate_series) * 3);
+		memset(&series[1], 0, sizeof(struct ath9k_11n_rate_series) * 3);
 	}
 
 	/*
@@ -930,7 +930,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
 					ATH_DS_BA_BITMAP(ds),
 					WME_BA_BMP_SIZE >> 3);
 			} else {
-				memzero(ba, WME_BA_BMP_SIZE >> 3);
+				memset(ba, 0, WME_BA_BMP_SIZE >> 3);
 
 				/*
 				 * AR5416 can become deaf/mute when BA
@@ -943,7 +943,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
 					needreset = 1;
 			}
 		} else {
-			memzero(ba, WME_BA_BMP_SIZE >> 3);
+			memset(ba, 0, WME_BA_BMP_SIZE >> 3);
 		}
 	}
 
@@ -2098,7 +2098,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
 	struct ath9k_tx_queue_info qi;
 	int qnum;
 
-	memzero(&qi, sizeof(qi));
+	memset(&qi, 0, sizeof(qi));
 	qi.tqi_subtype = subtype;
 	qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
 	qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
Signature · 1 line
1.5.6.rc2.15.g457bb.dirty
#2 lore raw

PATCH 2/3 ath9k: fix oops on trying to hold the wrong spinlock

We were trying to hold the wrong spinlock due to a typo on IEEE80211_BAR_CTL_TID_S's definition. We use this to compute the tid number and then hold this this tid number's spinlock.

---
 drivers/net/wireless/ath9k/core.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wireless/ath9k/core.h +1 -1
index 80814c9..5b4f1c4 100644
@@ -309,7 +309,7 @@ void ath_descdma_cleanup(struct ath_softc *sc,
 #define ATH_RX_TIMEOUT           40      /* 40 milliseconds */
 #define WME_NUM_TID              16
 #define IEEE80211_BAR_CTL_TID_M  0xF000  /* tid mask */
-#define IEEE80211_BAR_CTL_TID_S  2       /* tid shift */
+#define IEEE80211_BAR_CTL_TID_S  12      /* tid shift */
 
 enum ATH_RX_TYPE {
 	ATH_RX_NON_CONSUMED = 0,
Signature · 1 line
1.5.6.rc2.15.g457bb.dirty
#3 lore raw

PATCH 3/3 ath9k: enable ANI to help with noisy environments

This enables Adaptive Noise Immunity (ANI) on ath9k. ANI is as algorithm designed to minimize the detrimental effects of time-varying interferences. This should help with throughput in noisy environments. To use ANI we re-enable the MIB interrupt. Since ANI works on a timer and updates the noise floor we take advantage of this and also report a non-static noise floor now to mac80211.

---

I've tested this on x86 and x86_64

 drivers/net/wireless/ath9k/ath9k.h |    2 +-
 drivers/net/wireless/ath9k/core.c  |  129 ++++++++++++++++++++++++++++++++++--
 drivers/net/wireless/ath9k/core.h  |   25 +++++++
 drivers/net/wireless/ath9k/hw.c    |   35 ++++++++--
 drivers/net/wireless/ath9k/main.c  |   18 +++++-
 drivers/net/wireless/ath9k/recv.c  |   13 +---
 6 files changed, 197 insertions(+), 25 deletions(-)
drivers/net/wireless/ath9k/ath9k.h +1 -1
index 0e897c2..accace5 100644
@@ -854,7 +854,7 @@ bool ath9k_hw_calibrate(struct ath_hal *ah,
 			u8 rxchainmask,
 			bool longcal,
 			bool *isCalDone);
-int16_t ath9k_hw_getchan_noise(struct ath_hal *ah,
+s16 ath9k_hw_getchan_noise(struct ath_hal *ah,
 			       struct ath9k_channel *chan);
 void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
 			    u16 assocId);
drivers/net/wireless/ath9k/core.c +122 -7

159 lines not on this page · raw message

drivers/net/wireless/ath9k/core.h +25 -0
index 5b4f1c4..cb3e61e 100644
@@ -800,6 +800,28 @@ void ath_slow_ant_div(struct ath_antdiv *antdiv,
 		      struct ath_rx_status *rx_stats);
 void ath_setdefantenna(void *sc, u32 antenna);
 
+/*******/
+/* ANI */
+/*******/
+
+/* ANI values for STA only.
+   FIXME: Add appropriate values for AP later */
+
+#define ATH_ANI_POLLINTERVAL    100     /* 100 milliseconds between ANI poll */
+#define ATH_SHORT_CALINTERVAL   1000    /* 1 second between calibrations */
+#define ATH_LONG_CALINTERVAL    30000   /* 30 seconds between calibrations */
+#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes between calibrations */
+
+struct ath_ani {
+	bool sc_caldone;
+	int16_t sc_noise_floor;
+	unsigned int sc_longcal_timer;
+	unsigned int sc_shortcal_timer;
+	unsigned int sc_resetcal_timer;
+	unsigned int sc_checkani_timer;
+	struct timer_list timer;
+};
+
 /********************/
 /*   LED Control    */
 /********************/
@@ -1028,6 +1050,9 @@ struct ath_softc {
 
 	/* Rfkill */
 	struct ath_rfkill rf_kill;
+
+	/* ANI */
+	struct ath_ani sc_ani;
 };
 
 int ath_init(u16 devid, struct ath_softc *sc);
drivers/net/wireless/ath9k/hw.c +30 -5
index 272c758..62e44a0 100644
@@ -329,7 +329,7 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah)
 	ah->ah_config.ofdm_trig_high = 500;
 	ah->ah_config.cck_trig_high = 200;
 	ah->ah_config.cck_trig_low = 100;
-	ah->ah_config.enable_ani = 0;
+	ah->ah_config.enable_ani = 1;
 	ah->ah_config.noise_immunity_level = 4;
 	ah->ah_config.ofdm_weaksignal_det = 1;
 	ah->ah_config.cck_weaksignal_thr = 0;
@@ -8405,23 +8405,48 @@ u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags)
 	}
 }
 
-int16_t
+/* We can tune this as we go by monitoring really low values */
+#define ATH9K_NF_TOO_LOW	-60
+
+/* AR5416 may return very high value (like -31 dBm), in those cases the nf
+ * is incorrect and we should use the static NF value. Later we can try to
+ * find out why they are reporting these values */
+static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf)
+{
+	if (nf > ATH9K_NF_TOO_LOW) {
+		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
+			 "%s: noise floor value detected (%d) is "
+			"lower than what we think is a "
+			"reasonable value (%d)\n",
+			 __func__, nf, ATH9K_NF_TOO_LOW);
+		return false;
+	}
+	return true;
+}
+
+s16
 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
 {
 	struct ath9k_channel *ichan;
+	s16 nf;
 
 	ichan = ath9k_regd_check_channel(ah, chan);
 	if (ichan == NULL) {
 		DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
 			 "%s: invalid channel %u/0x%x; no mapping\n",
 			 __func__, chan->channel, chan->channelFlags);
-		return 0;
+		return ATH_DEFAULT_NOISE_FLOOR;
 	}
 	if (ichan->rawNoiseFloor == 0) {
 		enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
-		return NOISE_FLOOR[mode];
+		nf = NOISE_FLOOR[mode];
 	} else
-		return ichan->rawNoiseFloor;
+		nf = ichan->rawNoiseFloor;
+
+	if (!ath9k_hw_nf_in_range(ah, nf))
+		nf = ATH_DEFAULT_NOISE_FLOOR;
+
+	return nf;
 }
 
 bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting)
drivers/net/wireless/ath9k/main.c +17 -1
index 2caba44..7472699 100644
@@ -274,10 +274,12 @@ static void ath9k_rx_prepare(struct ath_softc *sc,
 	rx_status->mactime = status->tsf;
 	rx_status->band = curchan->band;
 	rx_status->freq =  curchan->center_freq;
-	rx_status->noise = ATH_DEFAULT_NOISE_FLOOR;
+	rx_status->noise = sc->sc_ani.sc_noise_floor;
 	rx_status->signal = rx_status->noise + status->rssi;
 	rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100));
 	rx_status->antenna = status->antenna;
+
+	/* XXX Fix me, 64 cannot be the max rssi value, rigure it out */
 	rx_status->qual = status->rssi * 100 / 64;
 
 	if (status->flags & ATH_RX_MIC_ERROR)
@@ -427,6 +429,11 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
 		ath_rate_newstate(sc, avp);
 		/* Update ratectrl about the new state */
 		ath_rc_node_update(hw, avp->rc_node);
+
+		/* Start ANI */
+		mod_timer(&sc->sc_ani.timer,
+			jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
+
 	} else {
 		DPRINTF(sc, ATH_DBG_CONFIG,
 		"%s: Bss Info DISSOC\n", __func__);
@@ -1173,6 +1180,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
 		return error;
 	}
 
+	if (conf->type == NL80211_IFTYPE_AP) {
+		/* TODO: is this a suitable place to start ANI for AP mode? */
+		/* Start ANI */
+		mod_timer(&sc->sc_ani.timer,
+			  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
+	}
+
 	return 0;
 }
 
@@ -1195,6 +1209,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
 #ifdef CONFIG_SLOW_ANT_DIV
 	ath_slow_ant_div_stop(&sc->sc_antdiv);
 #endif
+	/* Stop ANI */
+	del_timer_sync(&sc->sc_ani.timer);
 
 	/* Update ratectrl */
 	ath_rate_newstate(sc, avp);
drivers/net/wireless/ath9k/recv.c +2 -11
index f4be5d1..4983402 100644
@@ -999,20 +999,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 				rx_status.flags |= ATH_RX_SHORT_GI;
 		}
 
-		/* sc->sc_noise_floor is only available when the station
+		/* sc_noise_floor is only available when the station
 		   attaches to an AP, so we use a default value
 		   if we are not yet attached. */
-
-		/* XXX we should use either sc->sc_noise_floor or
-		 * ath_hal_getChanNoise(ah, &sc->sc_curchan)
-		 * to calculate the noise floor.
-		 * However, the value returned by ath_hal_getChanNoise
-		 * seems to be incorrect (-31dBm on the last test),
-		 * so we will use a hard-coded value until we
-		 * figure out what is going on.
-		 */
 		rx_status.abs_rssi =
-			ds->ds_rxstat.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
+			ds->ds_rxstat.rs_rssi + sc->sc_ani.sc_noise_floor;
 
 		pci_dma_sync_single_for_cpu(sc->pdev,
 					    bf->bf_buf_addr,
Signature · 1 line
1.5.6.rc2.15.g457bb.dirty
#4 lore raw

Re: [PATCH 2/3] ath9k: fix oops on trying to hold the wrong spinlock

In reply to Luis R. Rodriguez
Quoted 8 lines · Luis R. Rodriguez

We were trying to hold the wrong spinlock due to a typo on IEEE80211_BAR_CTL_TID_S's definition. We use this to compute the tid number and then hold this this tid number's spinlock.

Just a head up John -- Ingo has already sucked this into his tree with a proper Reported-by. We still need it in wireless-testing though, not sure how that will be handled.

Luis

Tested-by
#5 lore raw

Re: [PATCH 2/3] ath9k: fix oops on trying to hold the wrong spinlock

Quoted 11 lines · Luis R. Rodriguez
Quoted 8 lines · Luis R. Rodriguez

We were trying to hold the wrong spinlock due to a typo on IEEE80211_BAR_CTL_TID_S's definition. We use this to compute the tid number and then hold this this tid number's spinlock.

Quoted 5 lines

Just a head up John -- Ingo has already sucked this into his tree with a proper Reported-by. We still need it in wireless-testing though, not sure how that will be handled.

Luis

Oh, I should add a tested-by for this.

#6 lore raw

Re: [PATCH 2/3] ath9k: fix oops on trying to hold the wrong spinlock

Quoted 17 lines · Steven Noonan
Quoted 15 lines · Luis R. Rodriguez
Quoted 8 lines · Luis R. Rodriguez

We were trying to hold the wrong spinlock due to a typo on IEEE80211_BAR_CTL_TID_S's definition. We use this to compute the tid number and then hold this this tid number's spinlock.

Just a head up John -- Ingo has already sucked this into his tree with a proper Reported-by. We still need it in wireless-testing though, not sure how that will be handled.

Quoted 5 lines
Quoted 1 line

Luis

Oh, I should add a tested-by for this.

Thanks a lot for testing this Steven, your reports and tests are greatly appreciated.

Let us know how ANI goes :)

Luis

#7 lore raw

PATCH 1/1 ath9k: fix oops on trying to hold the wrong spinlock

In reply to Luis R. Rodriguez
Quoted 7 lines · Luis R. Rodriguez
Quoted 5 lines · Luis R. Rodriguez

We were trying to hold the wrong spinlock due to a typo on IEEE80211_BAR_CTL_TID_S's definition. We use this to compute the tid number and then hold this this tid number's spinlock.

Quoted 7 lines
Quoted 3 lines

Just a head up John -- Ingo has already sucked this into his tree with a proper Reported-by. We still need it in wireless-testing though, not sure how that will be handled.

Small sidenote: in terms of upstream merging tip/out-of-tree is a dead-end (as its name implies) - it's a special temporary throw-away branch for hot fixes that fall outside the normal scope of -tip. We periodically rebase tip/out-of-tree against -git and throw away patches that go upstream via other routes. It's never merged directly to Linus. Perhaps we should rename it tip/not-for-linus ?

So we are glad to test out patches, but John please apply the patch below to the wireless tree so that it's not lost. (probably for v2.6.27.1) We are just helping out with testing and we do not want to interfere in any way with the wireless git workflow.

Ingo

------------------>

Quoted 1 line

From fff3ddac71cf05dda8501a3449c167340e46b755 Mon Sep 17 00:00:00 2001

From: Luis R. Rodriguez <[email protected]>
Date: Fri, 3 Oct 2008 04:49:21 -0700
Subject: [PATCH] ath9k: fix oops on trying to hold the wrong spinlock

Steven Noonan reported a crash that occurs during ath9k module load.

We were trying to hold the wrong spinlock due to a typo on IEEE80211_BAR_CTL_TID_S's definition. We use this to compute the tid number and then hold this this tid number's spinlock during ath_bar_rx().

---
 drivers/net/wireless/ath9k/core.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wireless/ath9k/core.h +1 -1
index 2f84093..88f4cc3 100644
@@ -316,7 +316,7 @@ void ath_descdma_cleanup(struct ath_softc *sc,
 #define ATH_RX_TIMEOUT           40      /* 40 milliseconds */
 #define WME_NUM_TID              16
 #define IEEE80211_BAR_CTL_TID_M  0xF000  /* tid mask */
-#define IEEE80211_BAR_CTL_TID_S  2       /* tid shift */
+#define IEEE80211_BAR_CTL_TID_S  12      /* tid shift */
 
 enum ATH_RX_TYPE {
 	ATH_RX_NON_CONSUMED = 0,