--- /dev/null
+From ebd022873aa61937603d2c4dfea19ce63ea1a3c8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+Date: Sun, 10 Oct 2010 22:44:39 +0200
+Subject: ath9k: A-MPDU rate control info fix
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+
+commit ebd022873aa61937603d2c4dfea19ce63ea1a3c8 upstream.
+
+This patch fixes the following problems with the rate control feedback
+generated by ath9k for A-MPDU frames:
+
+1. Rate control feedback is carried on the first frame of an aggregate
+that is either ACKed, or has execeeded the software retry count and is
+considered failed. However, ath9k would incorrectly assume the aggregate
+had the length 1 if one of these conditions did not apply to the first
+frame of the aggregate, but instead a later frame. This fix therefor
+copies the bf_nframes field of the buffer in the same manner as the rates
+field of the tx status.
+
+2. Sometimes the ampdu_len and ampdu_ack_len fields of the tx status was
+left uninitialized eventhough the IEEE80211_TX_STAT_AMPDU flag was set.
+This is now avoid by setting flag and fields in the same place.
+
+3. Even if a frame has been selected for aggregation by mac80211 and
+marked with the IEEE80211_TX_CTL_AMPDU flag it can sometimes happen that
+ath9k transmits the frame without aggregation. In these cases the
+ampdu_ack_len field could be incorrectly computed because the nbad
+parameter to ath_tx_rc_status was incorrect.
+
+Signed-off-by: Björn Smedman <bjorn.smedman@venatech.se>
+Acked-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/xmit.c | 19 +++++++++++++------
+ 1 file changed, 13 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -312,6 +312,7 @@ static void ath_tx_complete_aggr(struct
+ int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
+ bool rc_update = true;
+ struct ieee80211_tx_rate rates[4];
++ int nframes;
+
+ skb = bf->bf_mpdu;
+ hdr = (struct ieee80211_hdr *)skb->data;
+@@ -320,6 +321,7 @@ static void ath_tx_complete_aggr(struct
+ hw = bf->aphy->hw;
+
+ memcpy(rates, tx_info->control.rates, sizeof(rates));
++ nframes = bf->bf_nframes;
+
+ rcu_read_lock();
+
+@@ -337,7 +339,7 @@ static void ath_tx_complete_aggr(struct
+ !bf->bf_stale || bf_next != NULL)
+ list_move_tail(&bf->list, &bf_head);
+
+- ath_tx_rc_status(bf, ts, 0, 0, false);
++ ath_tx_rc_status(bf, ts, 1, 0, false);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+ 0, 0);
+
+@@ -442,6 +444,7 @@ static void ath_tx_complete_aggr(struct
+
+ if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+ memcpy(tx_info->control.rates, rates, sizeof(rates));
++ bf->bf_nframes = nframes;
+ ath_tx_rc_status(bf, ts, nbad, txok, true);
+ rc_update = false;
+ } else {
+@@ -2024,9 +2027,15 @@ static void ath_tx_rc_status(struct ath_
+
+ if (ts->ts_status & ATH9K_TXERR_FILT)
+ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc)
++ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+
++ BUG_ON(nbad > bf->bf_nframes);
++
++ tx_info->status.ampdu_len = bf->bf_nframes;
++ tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
++ }
++
+ if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
+ (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
+ if (ieee80211_is_data(hdr->frame_control)) {
+@@ -2036,8 +2045,6 @@ static void ath_tx_rc_status(struct ath_
+ if ((ts->ts_status & ATH9K_TXERR_XRETRY) ||
+ (ts->ts_status & ATH9K_TXERR_FIFO))
+ tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
+- tx_info->status.ampdu_len = bf->bf_nframes;
+- tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
+ }
+ }
+
+@@ -2159,7 +2166,7 @@ static void ath_tx_processq(struct ath_s
+ */
+ if (ts.ts_status & ATH9K_TXERR_XRETRY)
+ bf->bf_state.bf_type |= BUF_XRETRY;
+- ath_tx_rc_status(bf, &ts, 0, txok, true);
++ ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
+ }
+
+ if (bf_isampdu(bf))
+@@ -2288,7 +2295,7 @@ void ath_tx_edma_tasklet(struct ath_soft
+ if (!bf_isampdu(bf)) {
+ if (txs.ts_status & ATH9K_TXERR_XRETRY)
+ bf->bf_state.bf_type |= BUF_XRETRY;
+- ath_tx_rc_status(bf, &txs, 0, txok, true);
++ ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
+ }
+
+ if (bf_isampdu(bf))
--- /dev/null
+From 7583c550c3e635dcc61ab127c36ecefd59fb8dc8 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Wed, 20 Oct 2010 16:07:04 -0700
+Subject: ath9k: add locking for starting the PCU on RX
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 7583c550c3e635dcc61ab127c36ecefd59fb8dc8 upstream.
+
+There was some locking for starting some parts of
+RX but not for starting the PCU. Include this otherwise
+we can content against stopping the PCU.
+
+This can potentially lead to races against different
+buffers on the PCU which can lead to to the DMA RX
+engine writing to buffers which are already freed.
+
+This is part of a series that will help resolve the bug:
+
+https://bugzilla.kernel.org/show_bug.cgi?id=14624
+
+For more details about this issue refer to:
+
+http://marc.info/?l=linux-wireless&m=128629803703756&w=2
+
+Cc: Ben Greear <greearb@candelatech.com>
+Cc: Kyungwan Nam <kyungwan.nam@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+index e581b1f..b3c9baf 100644
+---
+ drivers/net/wireless/ath/ath9k/recv.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -288,11 +288,11 @@ static void ath_edma_start_recv(struct a
+ ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
+ sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
+
+- spin_unlock_bh(&sc->rx.rxbuflock);
+-
+ ath_opmode_init(sc);
+
+ ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
++
++ spin_unlock_bh(&sc->rx.rxbuflock);
+ }
+
+ static void ath_edma_stop_recv(struct ath_softc *sc)
+@@ -494,10 +494,11 @@ int ath_startrecv(struct ath_softc *sc)
+ ath9k_hw_rxena(ah);
+
+ start_recv:
+- spin_unlock_bh(&sc->rx.rxbuflock);
+ ath_opmode_init(sc);
+ ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
+
++ spin_unlock_bh(&sc->rx.rxbuflock);
++
+ return 0;
+ }
+
--- /dev/null
+From 1e450285281bdf766272c181ecd43d4f2f0711ce Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Wed, 20 Oct 2010 16:07:03 -0700
+Subject: ath9k: add locking for stopping RX
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 1e450285281bdf766272c181ecd43d4f2f0711ce upstream.
+
+ath9k locks for starting RX but not for stopping RX. We could
+potentially run into a situation where tried to stop RX
+but immediately started RX. This allows for races on the
+the RX engine deciding what buffer we last left off on
+and could potentially cause ath9k to DMA into already
+free'd memory or in the worst case at a later time to
+already given memory to other drivers.
+
+Fix this by locking stopping RX.
+
+This is part of a series that will help resolve the bug:
+
+https://bugzilla.kernel.org/show_bug.cgi?id=14624
+
+For more details about this issue refer to:
+
+http://marc.info/?l=linux-wireless&m=128629803703756&w=2
+
+Cc: Ben Greear <greearb@candelatech.com>
+Cc: Kyungwan Nam <kyungwan.nam@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/recv.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -297,10 +297,8 @@ static void ath_edma_start_recv(struct a
+
+ static void ath_edma_stop_recv(struct ath_softc *sc)
+ {
+- spin_lock_bh(&sc->rx.rxbuflock);
+ ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
+ ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
+- spin_unlock_bh(&sc->rx.rxbuflock);
+ }
+
+ int ath_rx_init(struct ath_softc *sc, int nbufs)
+@@ -508,6 +506,7 @@ bool ath_stoprecv(struct ath_softc *sc)
+ struct ath_hw *ah = sc->sc_ah;
+ bool stopped;
+
++ spin_lock_bh(&sc->rx.rxbuflock);
+ ath9k_hw_stoppcurecv(ah);
+ ath9k_hw_setrxfilter(ah, 0);
+ stopped = ath9k_hw_stopdmarecv(ah);
+@@ -516,6 +515,7 @@ bool ath_stoprecv(struct ath_softc *sc)
+ ath_edma_stop_recv(sc);
+ else
+ sc->rx.rxlink = NULL;
++ spin_unlock_bh(&sc->rx.rxbuflock);
+
+ return stopped;
+ }
--- /dev/null
+From a8909cfb1832ac623142898df2a9374722cfe68f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+Date: Sun, 10 Oct 2010 22:51:54 +0200
+Subject: ath9k: built-in rate control A-MPDU fix
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= <bjorn.smedman@venatech.se>
+
+commit a8909cfb1832ac623142898df2a9374722cfe68f upstream.
+
+This patch attempts to ensure that ath9k's built-in rate control algorithm
+does not rely on the value of the ampdu_len and ampdu_ack_len tx status
+fields unless the IEEE80211_TX_STAT_AMPDU flag is set.
+
+This patch has not been tested.
+
+Signed-off-by: Björn Smedman <bjorn.smedman@venatech.se>
+Acked-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/rc.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/rc.c
++++ b/drivers/net/wireless/ath/ath9k/rc.c
+@@ -1359,6 +1359,12 @@ static void ath_tx_status(void *priv, st
+ if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
+ return;
+
++ if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) {
++ tx_info->status.ampdu_ack_len =
++ (tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
++ tx_info->status.ampdu_len = 1;
++ }
++
+ /*
+ * If an underrun error is seen assume it as an excessive retry only
+ * if max frame trigger level has been reached (2 KB for singel stream,
--- /dev/null
+From 90fa539ca3f07323da5a90f5c8f4e5cd952875e7 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Mon, 20 Sep 2010 13:45:38 +0200
+Subject: ath9k: clean up / fix aggregation session flush
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 90fa539ca3f07323da5a90f5c8f4e5cd952875e7 upstream.
+
+The tid aggregation cleanup is a bit fragile, as it discards failed
+subframes in some places, and retransmits them in others. This could
+block the cleanup of an existing aggregation session, if a retransmission
+for a tid is issued, yet the tid is never scheduled again because of
+the cleanup state.
+
+Fix this by getting rid of as many subframes as possible, as early
+as possible, and immediately transmitting pending subframes as regular
+HT frames instead of waiting for the cleanup to complete.
+
+Drop all pending subframes while keeping track of the Block ACK window
+during aggregate tx completion to prevent sending out stale subframes,
+which could confuse the receiver side.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/xmit.c | 63 ++++++++++++++--------------------
+ 1 file changed, 26 insertions(+), 37 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -61,6 +61,8 @@ static int ath_tx_num_badfrms(struct ath
+ struct ath_tx_status *ts, int txok);
+ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
+ int nbad, int txok, bool update_rc);
++static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
++ int seqno);
+
+ enum {
+ MCS_HT20,
+@@ -143,18 +145,23 @@ static void ath_tx_flush_tid(struct ath_
+ struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+ struct ath_buf *bf;
+ struct list_head bf_head;
+- INIT_LIST_HEAD(&bf_head);
++ struct ath_tx_status ts;
+
+- WARN_ON(!tid->paused);
++ INIT_LIST_HEAD(&bf_head);
+
++ memset(&ts, 0, sizeof(ts));
+ spin_lock_bh(&txq->axq_lock);
+- tid->paused = false;
+
+ while (!list_empty(&tid->buf_q)) {
+ bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+- BUG_ON(bf_isretried(bf));
+ list_move_tail(&bf->list, &bf_head);
+- ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
++
++ if (bf_isretried(bf)) {
++ ath_tx_update_baw(sc, tid, bf->bf_seqno);
++ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
++ } else {
++ ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
++ }
+ }
+
+ spin_unlock_bh(&txq->axq_lock);
+@@ -433,7 +440,7 @@ static void ath_tx_complete_aggr(struct
+ list_move_tail(&bf->list, &bf_head);
+ }
+
+- if (!txpending) {
++ if (!txpending || (tid->state & AGGR_CLEANUP)) {
+ /*
+ * complete the acked-ones/xretried ones; update
+ * block-ack window
+@@ -513,15 +520,12 @@ static void ath_tx_complete_aggr(struct
+ }
+
+ if (tid->state & AGGR_CLEANUP) {
++ ath_tx_flush_tid(sc, tid);
++
+ if (tid->baw_head == tid->baw_tail) {
+ tid->state &= ~AGGR_ADDBA_COMPLETE;
+ tid->state &= ~AGGR_CLEANUP;
+-
+- /* send buffered frames as singles */
+- ath_tx_flush_tid(sc, tid);
+ }
+- rcu_read_unlock();
+- return;
+ }
+
+ rcu_read_unlock();
+@@ -806,12 +810,6 @@ void ath_tx_aggr_stop(struct ath_softc *
+ struct ath_node *an = (struct ath_node *)sta->drv_priv;
+ struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
+ struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
+- struct ath_tx_status ts;
+- struct ath_buf *bf;
+- struct list_head bf_head;
+-
+- memset(&ts, 0, sizeof(ts));
+- INIT_LIST_HEAD(&bf_head);
+
+ if (txtid->state & AGGR_CLEANUP)
+ return;
+@@ -821,31 +819,22 @@ void ath_tx_aggr_stop(struct ath_softc *
+ return;
+ }
+
+- /* drop all software retried frames and mark this TID */
+ spin_lock_bh(&txq->axq_lock);
+ txtid->paused = true;
+- while (!list_empty(&txtid->buf_q)) {
+- bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
+- if (!bf_isretried(bf)) {
+- /*
+- * NB: it's based on the assumption that
+- * software retried frame will always stay
+- * at the head of software queue.
+- */
+- break;
+- }
+- list_move_tail(&bf->list, &bf_head);
+- ath_tx_update_baw(sc, txtid, bf->bf_seqno);
+- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+- }
+- spin_unlock_bh(&txq->axq_lock);
+
+- if (txtid->baw_head != txtid->baw_tail) {
++ /*
++ * If frames are still being transmitted for this TID, they will be
++ * cleaned up during tx completion. To prevent race conditions, this
++ * TID can only be reused after all in-progress subframes have been
++ * completed.
++ */
++ if (txtid->baw_head != txtid->baw_tail)
+ txtid->state |= AGGR_CLEANUP;
+- } else {
++ else
+ txtid->state &= ~AGGR_ADDBA_COMPLETE;
+- ath_tx_flush_tid(sc, txtid);
+- }
++ spin_unlock_bh(&txq->axq_lock);
++
++ ath_tx_flush_tid(sc, txtid);
+ }
+
+ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
--- /dev/null
+From 231c3a1f0630c07a584905507a1cb7b705a56ab7 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Mon, 20 Sep 2010 19:35:28 +0200
+Subject: ath9k: fix an aggregation start related race condition
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 231c3a1f0630c07a584905507a1cb7b705a56ab7 upstream.
+
+A new aggregation session start can be issued by mac80211, even when the
+cleanup of the previous session has not completed yet. Since the data structure
+for the session is not recreated, this could corrupt the block ack window
+and lock up the aggregation session. Fix this by delaying the new session
+until the old one has been cleaned up.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 4 ++--
+ drivers/net/wireless/ath/ath9k/main.c | 5 +++--
+ drivers/net/wireless/ath/ath9k/xmit.c | 10 ++++++++--
+ 3 files changed, 13 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -346,8 +346,8 @@ void ath_tx_tasklet(struct ath_softc *sc
+ void ath_tx_edma_tasklet(struct ath_softc *sc);
+ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
+ bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
+-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+- u16 tid, u16 *ssn);
++int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
++ u16 tid, u16 *ssn);
+ void 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 ath9k_enable_ps(struct ath_softc *sc);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1973,8 +1973,9 @@ static int ath9k_ampdu_action(struct iee
+ break;
+ case IEEE80211_AMPDU_TX_START:
+ ath9k_ps_wakeup(sc);
+- ath_tx_aggr_start(sc, sta, tid, ssn);
+- ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
++ ret = ath_tx_aggr_start(sc, sta, tid, ssn);
++ if (!ret)
++ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ ath9k_ps_restore(sc);
+ break;
+ case IEEE80211_AMPDU_TX_STOP:
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -792,17 +792,23 @@ static void ath_tx_sched_aggr(struct ath
+ status != ATH_AGGR_BAW_CLOSED);
+ }
+
+-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+- u16 tid, u16 *ssn)
++int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
++ u16 tid, u16 *ssn)
+ {
+ struct ath_atx_tid *txtid;
+ struct ath_node *an;
+
+ an = (struct ath_node *)sta->drv_priv;
+ txtid = ATH_AN_2_TID(an, tid);
++
++ if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
++ return -EAGAIN;
++
+ txtid->state |= AGGR_ADDBA_PROGRESS;
+ txtid->paused = true;
+ *ssn = txtid->seq_start;
++
++ return 0;
+ }
+
+ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
--- /dev/null
+From f209f5298217cf54cd5a9163e18b08d093faf8d9 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Fri, 1 Oct 2010 01:06:53 +0200
+Subject: ath9k: fix channel flag / regd issues with multiple cards
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit f209f5298217cf54cd5a9163e18b08d093faf8d9 upstream.
+
+Since the regulatory code touches the channel array, it needs to be
+copied for each device instance. That way the original channel array
+can also be made const.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/init.c | 37 ++++++++++++++++++++++++++++------
+ 1 file changed, 31 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -56,7 +56,7 @@ MODULE_PARM_DESC(blink, "Enable LED blin
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+-static struct ieee80211_channel ath9k_2ghz_chantable[] = {
++static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
+ CHAN2G(2412, 0), /* Channel 1 */
+ CHAN2G(2417, 1), /* Channel 2 */
+ CHAN2G(2422, 2), /* Channel 3 */
+@@ -77,7 +77,7 @@ static struct ieee80211_channel ath9k_2g
+ * on 5 MHz steps, we support the channels which we know
+ * we have calibration data for all cards though to make
+ * this static */
+-static struct ieee80211_channel ath9k_5ghz_chantable[] = {
++static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
+ /* _We_ call this UNII 1 */
+ CHAN5G(5180, 14), /* Channel 36 */
+ CHAN5G(5200, 15), /* Channel 40 */
+@@ -477,10 +477,17 @@ err:
+ return -EIO;
+ }
+
+-static void ath9k_init_channels_rates(struct ath_softc *sc)
++static int ath9k_init_channels_rates(struct ath_softc *sc)
+ {
++ void *channels;
++
+ if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
+- sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
++ channels = kmemdup(ath9k_2ghz_chantable,
++ sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
++ if (!channels)
++ return -ENOMEM;
++
++ sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
+ sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+ sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
+ ARRAY_SIZE(ath9k_2ghz_chantable);
+@@ -490,7 +497,15 @@ static void ath9k_init_channels_rates(st
+ }
+
+ if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
+- sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
++ channels = kmemdup(ath9k_5ghz_chantable,
++ sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
++ if (!channels) {
++ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
++ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
++ return -ENOMEM;
++ }
++
++ sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
+ sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
+ sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
+ ARRAY_SIZE(ath9k_5ghz_chantable);
+@@ -499,6 +514,7 @@ static void ath9k_init_channels_rates(st
+ sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
+ ARRAY_SIZE(ath9k_legacy_rates) - 4;
+ }
++ return 0;
+ }
+
+ static void ath9k_init_misc(struct ath_softc *sc)
+@@ -593,8 +609,11 @@ static int ath9k_init_softc(u16 devid, s
+ if (ret)
+ goto err_btcoex;
+
++ ret = ath9k_init_channels_rates(sc);
++ if (ret)
++ goto err_btcoex;
++
+ ath9k_init_crypto(sc);
+- ath9k_init_channels_rates(sc);
+ ath9k_init_misc(sc);
+
+ return 0;
+@@ -751,6 +770,12 @@ static void ath9k_deinit_softc(struct at
+ {
+ int i = 0;
+
++ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
++ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
++
++ if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
++ kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
++
+ if ((sc->btcoex.no_stomp_timer) &&
+ sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+ ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
--- /dev/null
+From 48a6a468198aadb54bc5d3fdd065364d43ff5197 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:28 -0400
+Subject: ath9k: fix enabling ANI / tx monitor after bg scan
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 48a6a468198aadb54bc5d3fdd065364d43ff5197 upstream.
+
+ath9k's entire logic with SC_OP_SCANNING is incorrect due to the
+way mac80211 currently implements the scan complete callback and
+we handle it in ath9k. This patch removes the flag completely in
+preference for the SC_OP_OFFCHANNEL which is really what we wanted.
+
+The scanning flag was used to ensure we reset ANI to the old values
+when we go back to the home channel, but if we are offchannel we
+use some defaults. The flag was also used to re-enable the TX monitor.
+
+Without this patch we simply never re-enabled ANI and the TX monitor
+after going offchannel. This means that after one background
+scan we are prone to noise issues and if we had a TX hang we would
+not recover. To get this to work properly we must enable ANI after
+we have configured the beacon timers, otherwise hardware acts really
+oddly.
+
+This patch has stable fixes which apply down to [2.6.36+], there
+*may* be a to fix this on older kernels but requires a bit of
+work since this patch relies on the new mac80211 flag
+IEEE80211_CONF_OFFCHANNEL which was introduced as of 2.6.36.
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 1 -
+ drivers/net/wireless/ath/ath9k/main.c | 10 +++-------
+ drivers/net/wireless/ath/ath9k/recv.c | 4 ++--
+ 3 files changed, 5 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -516,7 +516,6 @@ void ath_deinit_leds(struct ath_softc *s
+ #define SC_OP_RXFLUSH BIT(7)
+ #define SC_OP_LED_ASSOCIATED BIT(8)
+ #define SC_OP_LED_ON BIT(9)
+-#define SC_OP_SCANNING BIT(10)
+ #define SC_OP_TSF_RESET BIT(11)
+ #define SC_OP_BT_PRIORITY_DETECTED BIT(12)
+ #define SC_OP_BT_SCAN BIT(13)
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -254,14 +254,12 @@ int ath_set_channel(struct ath_softc *sc
+ ath_update_txpow(sc);
+ ath9k_hw_set_interrupts(ah, ah->imask);
+
+- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) {
+- ath_start_ani(common);
++ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
++ ath_beacon_config(sc, NULL);
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
++ ath_start_ani(common);
+ }
+
+- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)))
+- ath_beacon_config(sc, NULL);
+-
+ ps_restore:
+ ath9k_ps_restore(sc);
+ return r;
+@@ -2040,7 +2038,6 @@ static void ath9k_sw_scan_start(struct i
+
+ aphy->state = ATH_WIPHY_SCAN;
+ ath9k_wiphy_pause_all_forced(sc, aphy);
+- sc->sc_flags |= SC_OP_SCANNING;
+ mutex_unlock(&sc->mutex);
+ }
+
+@@ -2055,7 +2052,6 @@ static void ath9k_sw_scan_complete(struc
+
+ mutex_lock(&sc->mutex);
+ aphy->state = ATH_WIPHY_ACTIVE;
+- sc->sc_flags &= ~SC_OP_SCANNING;
+ mutex_unlock(&sc->mutex);
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -292,7 +292,7 @@ static void ath_edma_start_recv(struct a
+
+ ath_opmode_init(sc);
+
+- ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING));
++ ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
+ }
+
+ static void ath_edma_stop_recv(struct ath_softc *sc)
+@@ -496,7 +496,7 @@ int ath_startrecv(struct ath_softc *sc)
+ start_recv:
+ spin_unlock_bh(&sc->rx.rxbuflock);
+ ath_opmode_init(sc);
+- ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING));
++ ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
+
+ return 0;
+ }
--- /dev/null
+From 4fc4fbd1d9a05fa4f348b499aca3a6f8d3c9bbe6 Mon Sep 17 00:00:00 2001
+From: Mohammed Shafi Shajakhan <mshajakhan@atheros.com>
+Date: Thu, 28 Oct 2010 19:51:47 +0530
+Subject: ath9k: Fix incorrect access of rate flags in RC
+
+From: Mohammed Shafi Shajakhan <mshajakhan@atheros.com>
+
+commit 4fc4fbd1d9a05fa4f348b499aca3a6f8d3c9bbe6 upstream.
+
+The index variable to access the rate flags should be obtained from the
+inner loop counter which corresponds to the rate table structure.This
+fixes the invalid rate selection i.e when the supported basic rate is
+invalid on a particular band and also the following warning message.
+Thanks to Raj for finding this out.
+
+Call Trace:
+
+ [<ffffffff8104ee4a>] warn_slowpath_common+0x7a/0xb0
+
+ [<ffffffff8104ee95>] warn_slowpath_null+0x15/0x20
+
+ [<ffffffffa0583c45>] ath_get_rate+0x595/0x5b0 [ath9k]
+
+ [<ffffffff811a0636>] ? cpumask_next_and+0x36/0x50
+
+ [<ffffffffa0405186>] rate_control_get_rate+0x86/0x160 [mac80211]
+
+ [<ffffffffa040dfac>] invoke_tx_handlers+0x81c/0x12d0 [mac80211]
+
+ [<ffffffffa040eae9>] ieee80211_tx+0x89/0x2b0 [mac80211]
+
+ [<ffffffff812891bc>] ? pskb_expand_head+0x1cc/0x1f0
+
+ [<ffffffffa040edc5>] ieee80211_xmit+0xb5/0x1c0 [mac80211]
+
+ [<ffffffffa041026f>] ieee80211_tx_skb+0x4f/0x60 [mac80211]
+
+ [<ffffffffa03fe016>] ieee80211_send_nullfunc+0x46/0x60 [mac80211]
+
+ [<ffffffffa03f91d7>] ieee80211_offchannel_stop_station+0x107/0x150
+[mac80211]
+
+ [<ffffffff812891bc>] ? pskb_expand_head+0x1cc/0x1f0
+
+ [<ffffffffa040edc5>] ieee80211_xmit+0xb5/0x1c0 [mac80211]
+
+ [<ffffffffa041026f>] ieee80211_tx_skb+0x4f/0x60 [mac80211]
+
+ [<ffffffffa03fe016>] ieee80211_send_nullfunc+0x46/0x60 [mac80211]
+
+ [<ffffffffa03f91d7>] ieee80211_offchannel_stop_station+0x107/0x150
+[mac80211]
+
+ [<ffffffffa03f8896>] ieee80211_scan_work+0x146/0x600 [mac80211]
+
+ [<ffffffff8133a375>] ? schedule+0x2f5/0x8e0
+
+ [<ffffffffa03f8750>] ? ieee80211_scan_work+0x0/0x600 [mac80211]
+
+ [<ffffffff81064fcf>] process_one_work+0x10f/0x380
+
+ [<ffffffff81066bc2>] worker_thread+0x162/0x340
+
+ [<ffffffff81066a60>] ? worker_thread+0x0/0x340
+
+Signed-off-by: Mohammed Shafi Shajakhan <mshajakhan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/rc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/rc.c
++++ b/drivers/net/wireless/ath/ath9k/rc.c
+@@ -538,7 +538,7 @@ static u8 ath_rc_setvalid_rates(struct a
+ for (i = 0; i < rateset->rs_nrates; i++) {
+ for (j = 0; j < rate_table->rate_cnt; j++) {
+ u32 phy = rate_table->info[j].phy;
+- u16 rate_flags = rate_table->info[i].rate_flags;
++ u16 rate_flags = rate_table->info[j].rate_flags;
+ u8 rate = rateset->rs_rates[i];
+ u8 dot11rate = rate_table->info[j].dot11rate;
+
--- /dev/null
+From 8ab2cd09fecc8819bbaee2d0fd8f3a092d866ce3 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:26 -0400
+Subject: ath9k: fix power save race conditions
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 8ab2cd09fecc8819bbaee2d0fd8f3a092d866ce3 upstream.
+
+ath9k has a race on putting the chip into network sleep and
+having registers read from hardware. The race occurs because
+although ath9k_ps_restore() locks its own callers it makes use
+of some variables which get altered in the driver at different
+code paths. The variables are the ps_enabled and ps_flags.
+
+This is easily reprodicible in large network environments when
+roaming with the wpa_supplicant simple bgscan. You'd get some
+0xdeadbeef read out on certain registers such as:
+
+ath: timeout (100000 us) on reg 0x806c: 0xdeadbeef & 0x01f00000 != 0x00000000
+ath: RX failed to go idle in 10 ms RXSM=0xdeadbeef
+
+ath: timeout (100000 us) on reg 0x7000: 0xdeadbeef & 0x00000003 != 0x00000000
+ath: Chip reset failed
+
+The fix is to protect the ath9k_config(hw, IEEE80211_CONF_CHANGE_PS)
+calls with a spin_lock_irqsave() which will disable contendors for
+these variables from interrupt context, timers, re-entry from mac80211
+on the same callback, and most importantly from ath9k_ps_restore()
+which is the only call which will put the device into network sleep.
+
+There are quite a few threads and bug reports on these a few of them are:
+
+https://bugs.launchpad.net/ubuntu/karmic/+source/linux/+bug/407040
+http://code.google.com/p/chromium-os/issues/detail?id=5709
+http://code.google.com/p/chromium-os/issues/detail?id=5943
+
+Stable fixes apply to [2.6.32+]
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/main.c | 5 ++++-
+ drivers/net/wireless/ath/ath9k/recv.c | 3 +++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1558,6 +1558,8 @@ static int ath9k_config(struct ieee80211
+ * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode.
+ */
+ if (changed & IEEE80211_CONF_CHANGE_PS) {
++ unsigned long flags;
++ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ if (conf->flags & IEEE80211_CONF_PS) {
+ sc->ps_flags |= PS_ENABLED;
+ /*
+@@ -1572,7 +1574,7 @@ static int ath9k_config(struct ieee80211
+ sc->ps_enabled = false;
+ sc->ps_flags &= ~(PS_ENABLED |
+ PS_NULLFUNC_COMPLETED);
+- ath9k_setpower(sc, ATH9K_PM_AWAKE);
++ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
+ if (!(ah->caps.hw_caps &
+ ATH9K_HW_CAP_AUTOSLEEP)) {
+ ath9k_hw_setrxabort(sc->sc_ah, 0);
+@@ -1587,6 +1589,7 @@ static int ath9k_config(struct ieee80211
+ }
+ }
+ }
++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -1096,6 +1096,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
+ u8 rx_status_len = ah->caps.rx_status_len;
+ u64 tsf = 0;
+ u32 tsf_lower = 0;
++ unsigned long flags;
+
+ if (edma)
+ dma_type = DMA_BIDIRECTIONAL;
+@@ -1204,11 +1205,13 @@ int ath_rx_tasklet(struct ath_softc *sc,
+ sc->rx.rxotherant = 0;
+ }
+
++ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ if (unlikely(ath9k_check_auto_sleep(sc) ||
+ (sc->ps_flags & (PS_WAIT_FOR_BEACON |
+ PS_WAIT_FOR_CAB |
+ PS_WAIT_FOR_PSPOLL_DATA))))
+ ath_rx_ps(sc, skb);
++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+
+ ath_rx_send_to_mac80211(hw, sc, skb, rxs);
+
--- /dev/null
+From 52b8ac92496e03d6b5619204d7f3bae6ce6eae45 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:27 -0400
+Subject: ath9k: fix regression on beacon loss after bgscan
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 52b8ac92496e03d6b5619204d7f3bae6ce6eae45 upstream.
+
+When we return to the home channel we were never reseting our beacon
+timers, this was casued by the fact that the scanning flag was still
+on even after we returned to our home channel. There are also other
+reasons why we would get a reset and if we are not off channel
+we always need to resynch our beacon timers, because a reset will
+clear them.
+
+This bug is a regression introduced on 2.6.36. The order of the
+changes are as follows:
+
+5ee08656 - Sat Jul 31 - ath9k: prevent calibration during off-channel activity
+a0daa0e7 - Tue Jul 27 - Revert "mac80211: fix sw scan bracketing"
+543708be - Fri Jun 18 - mac80211: fix sw scan bracketing
+
+mcgrof@tux ~/linux-2.6-allstable (git::master)$ git describe \
+ --contains 5ee0865615f65f84e6ee9174771a6716c29e08e1
+v2.6.36-rc1~43^2~34^2~22
+
+mcgrof@tux ~/linux-2.6-allstable (git::master)$ git describe \
+ --contains a0daa0e7592ada797d6835f11529097aabc27ad2
+v2.6.36-rc1~571^2~64^2~13
+
+mcgrof@tux ~/linux-2.6-allstable (git::master)$ git describe \
+ --contains 543708be320d7df692d24b349ca01a947b340764
+v2.6.36-rc1~571^2~107^2~187
+
+So 5ee08656 would have worked if a0daa0e7 was not committed but
+it was so this means 5ee08656 was broken since it assumed that
+when we were in the channel change routine the scan flag would
+be lifted. As it turns out the scan flag will be set when we
+are already on the home channel.
+
+For more details refer to:
+
+http://code.google.com/p/chromium-os/issues/detail?id=5715
+
+These issues will need to be considered for our solution on
+reshifting the scan complete callback location on mac80211 on
+current development kernel work.
+
+This patch has stable fixes which apply down to [2.6.36+]
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/main.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -257,9 +257,11 @@ int ath_set_channel(struct ath_softc *sc
+ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) {
+ ath_start_ani(common);
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+- ath_beacon_config(sc, NULL);
+ }
+
++ if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)))
++ ath_beacon_config(sc, NULL);
++
+ ps_restore:
+ ath9k_ps_restore(sc);
+ return r;
+@@ -953,7 +955,7 @@ int ath_reset(struct ath_softc *sc, bool
+
+ ath_update_txpow(sc);
+
+- if (sc->sc_flags & SC_OP_BEACONS)
++ if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
+ ath_beacon_config(sc, NULL); /* restart beacons */
+
+ ath9k_hw_set_interrupts(ah, ah->imask);
--- /dev/null
+From 008443def34db1dcc8016763587a288254ea5735 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:36 -0400
+Subject: ath9k: fix regression which disabled ps on ath9k
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 008443def34db1dcc8016763587a288254ea5735 upstream.
+
+The patch titled "ath9k: Add new file init.c" shuffled some code
+around but in dong so for some reason also removed the revision
+check for disablign power save. Add this revision check again
+so we can get power save re-enabled again by default on cards
+newer than AR5416 and AR5418.
+
+$ git describe --contains 556242049cc3992d0ee625e9f15c4b00ea4baac8
+v2.6.34-rc1~233^2~49^2~343
+
+This patch has fixes for stable kernels [2.6.34+].
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/init.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -660,7 +660,8 @@ void ath9k_set_hw_capab(struct ath_softc
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
+
+- hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
++ if (AR_SREV_5416(sc->sc_ah))
++ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+ hw->queues = 4;
+ hw->max_rates = 4;
--- /dev/null
+From 3fac6dfdcd2b893c22b20a03dd1bf1af8b627c4b Mon Sep 17 00:00:00 2001
+From: Senthil Balasubramanian <senthilkumar@atheros.com>
+Date: Thu, 16 Sep 2010 15:12:35 -0400
+Subject: ath9k: fix regression which prevents chip sleep after CAB data
+
+From: Senthil Balasubramanian <senthilkumar@atheros.com>
+
+commit 3fac6dfdcd2b893c22b20a03dd1bf1af8b627c4b upstream.
+
+The patch:
+
+commit 293dc5dfdbcc16cde06e40a688394cc8ab083e48
+Author: Gabor Juhos <juhosg@openwrt.org>
+Date: Fri Jun 19 12:17:48 2009 +0200
+
+ ath9k: remove ath_rx_ps_back_to_sleep helper
+
+ This helper only clears the SC_OP_WAIT_FOR_{BEACON,CAB} flags.
+ Remove it and clear these flags directly in the approptiate
+ places instead.
+
+ Changes-licensed-under: ISC
+ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ Signed-off-by: John W. Linville <linville@tuxdriver.com>
+
+introduced a regression which forgot to lift the beacon flag
+after we received all broadcast and multicast data. This meant
+we never went to sleep consuming about ~650mW on idle. This pretty
+much broke power save completely.
+
+This patch has fixes for stable kernels [2.6.32+].
+
+Cc: Paul Stewart <pstew@google.com>
+Cc: Sameer Nanda <snanda@google.com>
+Cc: Gabor Juhos <juhosg@openwrt.org>
+Cc: Amod Bodas <amod.bodas@atheros.com>
+Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/recv.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -631,7 +631,7 @@ static void ath_rx_ps(struct ath_softc *
+ * No more broadcast/multicast frames to be received at this
+ * point.
+ */
+- sc->ps_flags &= ~PS_WAIT_FOR_CAB;
++ sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON);
+ ath_print(common, ATH_DBG_PS,
+ "All PS CAB frames received, back to sleep\n");
+ } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
--- /dev/null
+From 56363ddeeed3afc5277ca227209773bc1042cc7b Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 28 Aug 2010 18:21:21 +0200
+Subject: ath9k: fix spurious MIC failure reports
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 56363ddeeed3afc5277ca227209773bc1042cc7b upstream.
+
+According to the hardware documentation, the MIC failure bit is only
+valid if the frame was decrypted using a valid TKIP key and is not a
+fragment.
+In some setups I've seen hardware-reported MIC failures on an AP that
+was configured for CCMP only, so it's clear that additional checks are
+necessary.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath.h | 1 +
+ drivers/net/wireless/ath/ath9k/common.c | 11 +++++++++++
+ drivers/net/wireless/ath/ath9k/mac.c | 3 ++-
+ drivers/net/wireless/ath/ath9k/recv.c | 19 +++++++++++--------
+ 4 files changed, 25 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -119,6 +119,7 @@ struct ath_common {
+
+ u32 keymax;
+ DECLARE_BITMAP(keymap, ATH_KEYMAX);
++ DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX);
+ u8 splitmic;
+
+ struct ath_regulatory regulatory;
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -366,9 +366,13 @@ int ath9k_cmn_key_config(struct ath_comm
+ set_bit(idx, common->keymap);
+ if (key->alg == ALG_TKIP) {
+ set_bit(idx + 64, common->keymap);
++ set_bit(idx, common->tkip_keymap);
++ set_bit(idx + 64, common->tkip_keymap);
+ if (common->splitmic) {
+ set_bit(idx + 32, common->keymap);
+ set_bit(idx + 64 + 32, common->keymap);
++ set_bit(idx + 32, common->tkip_keymap);
++ set_bit(idx + 64 + 32, common->tkip_keymap);
+ }
+ }
+
+@@ -393,10 +397,17 @@ void ath9k_cmn_key_delete(struct ath_com
+ return;
+
+ clear_bit(key->hw_key_idx + 64, common->keymap);
++
++ clear_bit(key->hw_key_idx, common->tkip_keymap);
++ clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
++
+ if (common->splitmic) {
+ ath9k_hw_keyreset(ah, key->hw_key_idx + 32);
+ clear_bit(key->hw_key_idx + 32, common->keymap);
+ clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
++
++ clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
++ clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
+ }
+ }
+ EXPORT_SYMBOL(ath9k_cmn_key_delete);
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -711,7 +711,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+ rs->rs_phyerr = phyerr;
+ } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+- else if (ads.ds_rxstatus8 & AR_MichaelErr)
++ else if ((ads.ds_rxstatus8 & AR_MichaelErr) &&
++ rs->rs_keyix != ATH9K_RXKEYIX_INVALID)
+ rs->rs_status |= ATH9K_RXERR_MIC;
+ else if (ads.ds_rxstatus8 & AR_KeyMiss)
+ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -870,15 +870,18 @@ static bool ath9k_rx_accept(struct ath_c
+ if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
+ *decrypt_error = true;
+ } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
+- if (ieee80211_is_ctl(fc))
+- /*
+- * Sometimes, we get invalid
+- * MIC failures on valid control frames.
+- * Remove these mic errors.
+- */
+- rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
+- else
++ /*
++ * The MIC error bit is only valid if the frame
++ * is not a control frame or fragment, and it was
++ * decrypted using a valid TKIP key.
++ */
++ if (!ieee80211_is_ctl(fc) &&
++ !ieee80211_has_morefrags(fc) &&
++ !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
++ test_bit(rx_stats->rs_keyix, common->tkip_keymap))
+ rxs->flag |= RX_FLAG_MMIC_ERROR;
++ else
++ rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
+ }
+ /*
+ * Reject error frames with the exception of
--- /dev/null
+From e609e2ea2cdb3448e7849703179cd792a28dcc55 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Wed, 27 Oct 2010 02:15:05 +0200
+Subject: ath9k: fix tx aggregation flush on AR9003
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit e609e2ea2cdb3448e7849703179cd792a28dcc55 upstream.
+
+Completing aggregate frames can lead to new buffers being pushed into
+the tid queues due to software retransmission.
+When the tx queues are being drained, all pending aggregates must be
+completed before the tid queues get drained, otherwise buffers might be
+leaked.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/xmit.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1101,15 +1101,6 @@ void ath_draintxq(struct ath_softc *sc,
+ txq->axq_tx_inprogress = false;
+ spin_unlock_bh(&txq->axq_lock);
+
+- /* flush any pending frames if aggregation is enabled */
+- if (sc->sc_flags & SC_OP_TXAGGR) {
+- if (!retry_tx) {
+- spin_lock_bh(&txq->axq_lock);
+- ath_txq_drain_pending_buffers(sc, txq);
+- spin_unlock_bh(&txq->axq_lock);
+- }
+- }
+-
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ spin_lock_bh(&txq->axq_lock);
+ while (!list_empty(&txq->txq_fifo_pending)) {
+@@ -1130,6 +1121,15 @@ void ath_draintxq(struct ath_softc *sc,
+ }
+ spin_unlock_bh(&txq->axq_lock);
+ }
++
++ /* flush any pending frames if aggregation is enabled */
++ if (sc->sc_flags & SC_OP_TXAGGR) {
++ if (!retry_tx) {
++ spin_lock_bh(&txq->axq_lock);
++ ath_txq_drain_pending_buffers(sc, txq);
++ spin_unlock_bh(&txq->axq_lock);
++ }
++ }
+ }
+
+ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
--- /dev/null
+From 9094537c3a9ef9e127e844254a74186735c9a90b Mon Sep 17 00:00:00 2001
+From: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+Date: Mon, 20 Sep 2010 22:54:46 -0700
+Subject: ath9k: Fix tx struck state with paprd
+
+From: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+
+commit 9094537c3a9ef9e127e844254a74186735c9a90b upstream.
+
+Paprd needs to be done only on active chains(not for all the chains
+that hw can support). The paprd training frames which are sent
+for inactive chains would be hanging on the hw queue without
+getting transmitted and would make the connection so unstable.
+This issue happens only with the hw which supports paprd cal(ar9003).
+
+Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/main.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -269,6 +269,7 @@ static void ath_paprd_activate(struct at
+ {
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
++ struct ath_common *common = ath9k_hw_common(ah);
+ int chain;
+
+ if (!caldata || !caldata->paprd_done)
+@@ -277,7 +278,7 @@ static void ath_paprd_activate(struct at
+ ath9k_ps_wakeup(sc);
+ ar9003_paprd_enable(ah, false);
+ for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+- if (!(ah->caps.tx_chainmask & BIT(chain)))
++ if (!(common->tx_chainmask & BIT(chain)))
+ continue;
+
+ ar9003_paprd_populate_single_table(ah, caldata, chain);
+@@ -299,6 +300,7 @@ void ath_paprd_calibrate(struct work_str
+ struct ieee80211_supported_band *sband = &sc->sbands[band];
+ struct ath_tx_control txctl;
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
++ struct ath_common *common = ath9k_hw_common(ah);
+ int qnum, ftype;
+ int chain_ok = 0;
+ int chain;
+@@ -332,7 +334,7 @@ void ath_paprd_calibrate(struct work_str
+ ath9k_ps_wakeup(sc);
+ ar9003_paprd_init_table(ah);
+ for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+- if (!(ah->caps.tx_chainmask & BIT(chain)))
++ if (!(common->tx_chainmask & BIT(chain)))
+ continue;
+
+ chain_ok = 0;
--- /dev/null
+From 5e848f789d60000d39d9a5f26ab02dbdd963f6cd Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Wed, 20 Oct 2010 16:07:06 -0700
+Subject: ath9k: lock reset and PCU start/stopping
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 5e848f789d60000d39d9a5f26ab02dbdd963f6cd upstream.
+
+Apart from locking the start and stop PCU we need
+to ensure we also content starting and stopping the PCU
+between hardware resets.
+
+This is part of a series that will help resolve the bug:
+
+https://bugzilla.kernel.org/show_bug.cgi?id=14624
+
+For more details about this issue refer to:
+
+http://marc.info/?l=linux-wireless&m=128629803703756&w=2
+
+Cc: Ben Greear <greearb@candelatech.com>
+Cc: Kyungwan Nam <kyungwan.nam@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/main.c | 27 +++++++++++++++++++++++++++
+ drivers/net/wireless/ath/ath9k/recv.c | 2 --
+ 2 files changed, 27 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -213,6 +213,9 @@ int ath_set_channel(struct ath_softc *sc
+ */
+ ath9k_hw_set_interrupts(ah, 0);
+ ath_drain_all_txq(sc, false);
++
++ spin_lock_bh(&sc->rx.pcu_lock);
++
+ stopped = ath_stoprecv(sc);
+
+ /* XXX: do not flush receive queue here. We don't want
+@@ -239,6 +242,7 @@ int ath_set_channel(struct ath_softc *sc
+ "reset status %d\n",
+ channel->center_freq, r);
+ spin_unlock_bh(&sc->sc_resetlock);
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ goto ps_restore;
+ }
+ spin_unlock_bh(&sc->sc_resetlock);
+@@ -247,9 +251,12 @@ int ath_set_channel(struct ath_softc *sc
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to restart recv logic\n");
+ r = -EIO;
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ goto ps_restore;
+ }
+
++ spin_unlock_bh(&sc->rx.pcu_lock);
++
+ ath_cache_conf_rate(sc, &hw->conf);
+ ath_update_txpow(sc);
+ ath9k_hw_set_interrupts(ah, ah->imask);
+@@ -840,6 +847,7 @@ void ath_radio_enable(struct ath_softc *
+ if (!ah->curchan)
+ ah->curchan = ath_get_curchannel(sc, sc->hw);
+
++ spin_lock_bh(&sc->rx.pcu_lock);
+ spin_lock_bh(&sc->sc_resetlock);
+ r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+ if (r) {
+@@ -854,8 +862,10 @@ void ath_radio_enable(struct ath_softc *
+ if (ath_startrecv(sc) != 0) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to restart recv logic\n");
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ return;
+ }
++ spin_unlock_bh(&sc->rx.pcu_lock);
+
+ if (sc->sc_flags & SC_OP_BEACONS)
+ ath_beacon_config(sc, NULL); /* restart beacons */
+@@ -894,6 +904,9 @@ void ath_radio_disable(struct ath_softc
+ ath9k_hw_set_interrupts(ah, 0);
+
+ ath_drain_all_txq(sc, false); /* clear pending tx frames */
++
++ spin_lock_bh(&sc->rx.pcu_lock);
++
+ ath_stoprecv(sc); /* turn off frame recv */
+ ath_flushrecv(sc); /* flush recv queue */
+
+@@ -911,6 +924,9 @@ void ath_radio_disable(struct ath_softc
+ spin_unlock_bh(&sc->sc_resetlock);
+
+ ath9k_hw_phy_disable(ah);
++
++ spin_unlock_bh(&sc->rx.pcu_lock);
++
+ ath9k_hw_configpcipowersave(ah, 1, 1);
+ ath9k_ps_restore(sc);
+ ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
+@@ -930,6 +946,9 @@ int ath_reset(struct ath_softc *sc, bool
+
+ ath9k_hw_set_interrupts(ah, 0);
+ ath_drain_all_txq(sc, retry_tx);
++
++ spin_lock_bh(&sc->rx.pcu_lock);
++
+ ath_stoprecv(sc);
+ ath_flushrecv(sc);
+
+@@ -944,6 +963,8 @@ int ath_reset(struct ath_softc *sc, bool
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to start recv logic\n");
+
++ spin_unlock_bh(&sc->rx.pcu_lock);
++
+ /*
+ * We may be doing a reset in response to a request
+ * that changes the channel so update any state that
+@@ -1108,6 +1129,7 @@ static int ath9k_start(struct ieee80211_
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
++ spin_lock_bh(&sc->rx.pcu_lock);
+ spin_lock_bh(&sc->sc_resetlock);
+ r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
+ if (r) {
+@@ -1116,6 +1138,7 @@ static int ath9k_start(struct ieee80211_
+ "(freq %u MHz)\n", r,
+ curchan->center_freq);
+ spin_unlock_bh(&sc->sc_resetlock);
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ goto mutex_unlock;
+ }
+ spin_unlock_bh(&sc->sc_resetlock);
+@@ -1137,8 +1160,10 @@ static int ath9k_start(struct ieee80211_
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to start recv logic\n");
+ r = -EIO;
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ goto mutex_unlock;
+ }
++ spin_unlock_bh(&sc->rx.pcu_lock);
+
+ /* Setup our intr mask. */
+ ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
+@@ -1340,12 +1365,14 @@ static void ath9k_stop(struct ieee80211_
+ * before setting the invalid flag. */
+ ath9k_hw_set_interrupts(ah, 0);
+
++ spin_lock_bh(&sc->rx.pcu_lock);
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
+ ath_drain_all_txq(sc, false);
+ ath_stoprecv(sc);
+ ath9k_hw_phy_disable(ah);
+ } else
+ sc->rx.rxlink = NULL;
++ spin_unlock_bh(&sc->rx.pcu_lock);
+
+ /* disable HAL and put h/w to sleep */
+ ath9k_hw_disable(ah);
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -523,13 +523,11 @@ bool ath_stoprecv(struct ath_softc *sc)
+
+ void ath_flushrecv(struct ath_softc *sc)
+ {
+- spin_lock_bh(&sc->rx.pcu_lock);
+ sc->sc_flags |= SC_OP_RXFLUSH;
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ ath_rx_tasklet(sc, 1, true);
+ ath_rx_tasklet(sc, 1, false);
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+- spin_unlock_bh(&sc->rx.pcu_lock);
+ }
+
+ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
--- /dev/null
+From b79b33c4baf2532aac2c0924dce5a738099b888c Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Wed, 20 Oct 2010 16:07:05 -0700
+Subject: ath9k: rename rxflushlock to pcu_lock
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit b79b33c4baf2532aac2c0924dce5a738099b888c upstream.
+
+The real way to lock RX is to contend on the PCU
+and reset, this will be fixed in the next patch but for
+now just do the renames so that the next patch which changes
+the locking order is crystal clear.
+
+This is part of a series that will help resolve the bug:
+
+https://bugzilla.kernel.org/show_bug.cgi?id=14624
+
+For more details about this issue refer to:
+
+http://marc.info/?l=linux-wireless&m=128629803703756&w=2
+
+Cc: Ben Greear <greearb@candelatech.com>
+Cc: Kyungwan Nam <kyungwan.nam@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Tested-by: Ben Greear <greearb@candelatech.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 2 +-
+ drivers/net/wireless/ath/ath9k/main.c | 4 ++--
+ drivers/net/wireless/ath/ath9k/recv.c | 6 +++---
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -312,7 +312,7 @@ struct ath_rx {
+ u8 rxotherant;
+ u32 *rxlink;
+ unsigned int rxfilter;
+- spinlock_t rxflushlock;
++ spinlock_t pcu_lock;
+ spinlock_t rxbuflock;
+ struct list_head rxbuf;
+ struct ath_descdma rxdma;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -587,7 +587,7 @@ void ath9k_tasklet(unsigned long data)
+ rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+
+ if (status & rxmask) {
+- spin_lock_bh(&sc->rx.rxflushlock);
++ spin_lock_bh(&sc->rx.pcu_lock);
+
+ /* Check for high priority Rx first */
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
+@@ -595,7 +595,7 @@ void ath9k_tasklet(unsigned long data)
+ ath_rx_tasklet(sc, 0, true);
+
+ ath_rx_tasklet(sc, 0, false);
+- spin_unlock_bh(&sc->rx.rxflushlock);
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ }
+
+ if (status & ATH9K_INT_TX) {
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -310,7 +310,7 @@ int ath_rx_init(struct ath_softc *sc, in
+ struct ath_buf *bf;
+ int error = 0;
+
+- spin_lock_init(&sc->rx.rxflushlock);
++ spin_lock_init(&sc->rx.pcu_lock);
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+ spin_lock_init(&sc->rx.rxbuflock);
+
+@@ -522,13 +522,13 @@ bool ath_stoprecv(struct ath_softc *sc)
+
+ void ath_flushrecv(struct ath_softc *sc)
+ {
+- spin_lock_bh(&sc->rx.rxflushlock);
++ spin_lock_bh(&sc->rx.pcu_lock);
+ sc->sc_flags |= SC_OP_RXFLUSH;
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ ath_rx_tasklet(sc, 1, true);
+ ath_rx_tasklet(sc, 1, false);
+ sc->sc_flags &= ~SC_OP_RXFLUSH;
+- spin_unlock_bh(&sc->rx.rxflushlock);
++ spin_unlock_bh(&sc->rx.pcu_lock);
+ }
+
+ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
--- /dev/null
+From fac6b6a065da42f826088c58bddad82e1b1ccb40 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 23 Oct 2010 17:45:38 +0200
+Subject: ath9k: resume aggregation immediately after a hardware reset
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit fac6b6a065da42f826088c58bddad82e1b1ccb40 upstream.
+
+Since aggregation is usually triggered by tx completion, a hardware
+reset (because of beacon stuck, tx hang or baseband hang) can
+significantly delay the transmission of the next AMPDU (until the next
+tx completion event).
+Fix this by rescheduling aggregation after such a reset.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/beacon.c | 2 +-
+ drivers/net/wireless/ath/ath9k/main.c | 4 ++--
+ drivers/net/wireless/ath/ath9k/xmit.c | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -366,7 +366,7 @@ void ath_beacon_tasklet(unsigned long da
+ ath_print(common, ATH_DBG_BEACON,
+ "beacon is officially stuck\n");
+ sc->sc_flags |= SC_OP_TSF_RESET;
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+ }
+
+ return;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -554,7 +554,7 @@ void ath_hw_check(struct work_struct *wo
+
+ msleep(1);
+ }
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+
+ out:
+ ath9k_ps_restore(sc);
+@@ -572,7 +572,7 @@ void ath9k_tasklet(unsigned long data)
+ ath9k_ps_wakeup(sc);
+
+ if (status & ATH9K_INT_FATAL) {
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+ ath9k_ps_restore(sc);
+ return;
+ }
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -2206,7 +2206,7 @@ static void ath_tx_complete_poll_work(st
+ ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
+ "tx hung, resetting the chip\n");
+ ath9k_ps_wakeup(sc);
+- ath_reset(sc, false);
++ ath_reset(sc, true);
+ ath9k_ps_restore(sc);
+ }
+
--- /dev/null
+From 7cbf2611dac8d5f76fe64795a9426b8c97e6c3f8 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Wed, 10 Nov 2010 17:51:25 +0530
+Subject: ath9k_htc: Add new devices into AR7010
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit 7cbf2611dac8d5f76fe64795a9426b8c97e6c3f8 upstream.
+
+Treat new PIDs (0xA704, 0x1200) as AR7010 devices.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hif_usb.c | 4 ++++
+ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 2 ++
+ drivers/net/wireless/ath/ath9k/reg.h | 4 +++-
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -803,6 +803,8 @@ static int ath9k_hif_usb_download_fw(str
+ case 0x7010:
+ case 0x7015:
+ case 0x9018:
++ case 0xA704:
++ case 0x1200:
+ firm_offset = AR7010_FIRMWARE_TEXT;
+ break;
+ default:
+@@ -909,6 +911,8 @@ static int ath9k_hif_usb_probe(struct us
+ case 0x7010:
+ case 0x7015:
+ case 0x9018:
++ case 0xA704:
++ case 0x1200:
+ if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
+ hif_dev->fw_name = FIRMWARE_AR7010_1_1;
+ else
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -247,6 +247,8 @@ static int ath9k_init_htc_services(struc
+ case 0x7010:
+ case 0x7015:
+ case 0x9018:
++ case 0xA704:
++ case 0x1200:
+ priv->htc->credits = 45;
+ break;
+ default:
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -901,7 +901,9 @@
+ #define AR_DEVID_7010(_ah) \
+ (((_ah)->hw_version.devid == 0x7010) || \
+ ((_ah)->hw_version.devid == 0x7015) || \
+- ((_ah)->hw_version.devid == 0x9018))
++ ((_ah)->hw_version.devid == 0x9018) || \
++ ((_ah)->hw_version.devid == 0xA704) || \
++ ((_ah)->hw_version.devid == 0x1200))
+
+ #define AR9287_HTC_DEVID(_ah) \
+ (((_ah)->hw_version.devid == 0x7015) || \
--- /dev/null
+From ac618d70aeb681df7b77c1107fdf26f3249f855f Mon Sep 17 00:00:00 2001
+From: Haitao Zhang <minipanda@linuxrobot.org>
+Date: Sun, 7 Nov 2010 12:50:24 +0800
+Subject: ath9k_htc: Add support for device ID 3346
+
+From: Haitao Zhang <minipanda@linuxrobot.org>
+
+commit ac618d70aeb681df7b77c1107fdf26f3249f855f upstream.
+
+This patch adds support for USB dongle with device ID 3346 from IMC Networks.
+
+Signed-off-by: Haitao Zhang <minipanda@linuxrobot.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hif_usb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -35,6 +35,7 @@ static struct usb_device_id ath9k_hif_us
+ { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */
+ { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
+ { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
++ { USB_DEVICE(0x13D3, 0x3346) }, /* IMC Networks */
+ { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
+ { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
+ { },
--- /dev/null
+From 3bf30b56c4f0a1c4fae34050b7db4527c92891e8 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Thu, 18 Nov 2010 12:19:52 +0530
+Subject: ath9k_htc: Avoid setting QoS control for non-QoS frames
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit 3bf30b56c4f0a1c4fae34050b7db4527c92891e8 upstream.
+
+Setting tid information in the TX header is required only for QoS
+frames. Not handling this case causes severe data loss with some APs.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+@@ -121,7 +121,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_
+ tx_hdr.data_type = ATH9K_HTC_NORMAL;
+ }
+
+- if (ieee80211_is_data(fc)) {
++ if (ieee80211_is_data_qos(fc)) {
+ qc = ieee80211_get_qos_ctl(hdr);
+ tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+ }
--- /dev/null
+From d654567dec75782d6fd9add4b7b9c50e0926d369 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Wed, 27 Oct 2010 12:02:54 +0530
+Subject: ath9k_htc: Set proper firmware offset for Netgear WNDA3200
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit d654567dec75782d6fd9add4b7b9c50e0926d369 upstream.
+
+Netgear WNDA3200 device uses ar7010 firmware but it is failed to set
+correct firmware offset on firmware download which causes device initialization
+failure.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hif_usb.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -799,10 +799,16 @@ static int ath9k_hif_usb_download_fw(str
+ }
+ kfree(buf);
+
+- if ((hif_dev->device_id == 0x7010) || (hif_dev->device_id == 0x7015))
++ switch (hif_dev->device_id) {
++ case 0x7010:
++ case 0x7015:
++ case 0x9018:
+ firm_offset = AR7010_FIRMWARE_TEXT;
+- else
++ break;
++ default:
+ firm_offset = AR9271_FIRMWARE_TEXT;
++ break;
++ }
+
+ /*
+ * Issue FW download complete command to firmware.
--- /dev/null
+From 32b089558c54792028f14ae830ca7c0a8d9ac9a3 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Wed, 10 Nov 2010 17:51:24 +0530
+Subject: ath9k_htc: Update usb device ID list
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit 32b089558c54792028f14ae830ca7c0a8d9ac9a3 upstream.
+
+Added new VID/PIDs into supported devices list
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hif_usb.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -36,8 +36,13 @@ static struct usb_device_id ath9k_hif_us
+ { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
+ { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
+ { USB_DEVICE(0x13D3, 0x3346) }, /* IMC Networks */
++ { USB_DEVICE(0x13D3, 0x3348) }, /* Azurewave */
++ { USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */
++ { USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */
+ { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
+ { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
++ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */
++ { USB_DEVICE(0x1668, 0x1200) }, /* Verizon */
+ { },
+ };
+
--- /dev/null
+From f119da3015712dc32bdf1c311652479e02dcb49a Mon Sep 17 00:00:00 2001
+From: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+Date: Thu, 4 Nov 2010 17:41:25 -0700
+Subject: ath9k_hw: Fix AR9280 surprise removal during frequent idle on/off
+
+From: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+
+commit f119da3015712dc32bdf1c311652479e02dcb49a upstream.
+
+Bit 22 of AR_WA should be set to fix the situation where chip reset
+is asynchronous to clock of analog shift registers, such that when
+reset is released, it could mess up the values of analog shift registers
+and cause some hw issue on AR9280.
+
+This bit is write only, but the driver does a read-modify-write
+on AR_WA without setting bit 22 in ar9002_hw_configpcipowersave()
+during radio disable. This causes surprise removal of hw. It can
+never recover from this state and the hw will become usable only
+after a power on/off cycle, and sometimes only during a cold reboot.
+
+This issue can be triggered by doing frequent roaming with the
+simple/test-roam script available from the wifi-test project [1]
+when roaming between APs quickly. When roaming there is a is a high
+possibility that the device being put into idle (radio disable) state
+by mac80211 during AUTH->ASSOC. A device hardware reset would fail
+and the kernel would output:
+
+[40251.363799] ath: AWAKE -> FULL-SLEEP
+[40251.363815] ieee80211 phy17: device no longer idle - working
+[40251.363817] ath: Marking phy17 as not-idle
+[40251.363819] ath: FULL-SLEEP -> AWAKE
+[40251.415978] pciehp 0000:00:1c.3:pcie04: Card not present on Slot(3)
+[40251.419896] ath: ah->misc_mode 0x4
+[40251.428138] pciehp 0000:00:1c.3:pcie04: Card present on Slot(3)
+[40251.532247] ath: timeout (100000 us) on reg 0x9860: 0xffffffff & 0x00000001 != 0x00000000
+[40251.532250] ath: Unable to reset channel (2462 MHz), reset status -5
+[40251.532422] ath: Set channel: 5745 MHz
+[40251.540639] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.548826] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.557023] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.565211] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.573415] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.581603] ath: Failed to stop TX DMA in 100 msec after killing last frame
+[40251.581606] ath: Failed to stop TX DMA. Resetting hardware!
+[40251.592679] ath: DMA failed to stop in 10 ms AR_CR=0xffffffff AR_DIAG_SW=0xffffffff
+[40251.703330] ath: timeout (100000 us) on reg 0x7000: 0xffffffff & 0x00000003 != 0x00000000
+[40251.703333] ath: RTC stuck in MAC reset
+[40251.703334] ath: Chip reset failed
+[40251.703335] ath: Unable to reset hardware; reset status -22
+
+This is currently only reproducible with some HB92 (Half Mini-PCIE)
+cards but the fix applies to all AR9280 cards. This patch fixes this
+issue by setting bit 22 during radio disable.
+
+This patch has fixes for all kernels that has ath9k.
+
+[1] http://wireless.kernel.org/en/developers/Testing/wifi-test
+
+Cc: kyungwan.nam@atheros.com
+Cc: amod.bodas@atheros.com
+Cc: david.quan@atheros.com
+Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ar9002_hw.c | 3 +++
+ drivers/net/wireless/ath/ath9k/reg.h | 1 +
+ 2 files changed, 4 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+@@ -411,6 +411,9 @@ static void ar9002_hw_configpcipowersave
+ val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
+ }
+
++ if (AR_SREV_9280(ah))
++ val |= AR_WA_BIT22;
++
+ if (AR_SREV_9285E_20(ah))
+ val |= AR_WA_BIT23;
+
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -709,6 +709,7 @@
+ #define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
+ #define AR_WA_ANALOG_SHIFT (1 << 20)
+ #define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */
++#define AR_WA_BIT22 (1 << 22)
+ #define AR9285_WA_DEFAULT 0x004a050b
+ #define AR9280_WA_DEFAULT 0x0040073b
+ #define AR_WA_DEFAULT 0x0000073f
--- /dev/null
+From 2d3fca180710c6832de22c44155ce6a3a4953c6b Mon Sep 17 00:00:00 2001
+From: Senthil Balasubramanian <senthilkumar@atheros.com>
+Date: Tue, 19 Oct 2010 20:01:41 +0530
+Subject: ath9k_hw: Fix divide by zero cases in paprd.
+
+From: Senthil Balasubramanian <senthilkumar@atheros.com>
+
+commit 2d3fca180710c6832de22c44155ce6a3a4953c6b upstream.
+
+We are not handling all divide by zero cases in paprd.
+Add additional checks for divide by zero cases in papard.
+
+This patch has fixes intended for kernel 2.6.36.
+
+Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+@@ -347,6 +347,10 @@ static bool create_pa_curve(u32 *data_L,
+ (((Y[6] - Y[3]) * 1 << scale_factor) +
+ (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]);
+
++ /* prevent division by zero */
++ if (G_fxp == 0)
++ return false;
++
+ Y_intercept =
+ (G_fxp * (x_est[0] - x_est[3]) +
+ (1 << scale_factor)) / (1 << scale_factor) + Y[3];
+@@ -356,14 +360,12 @@ static bool create_pa_curve(u32 *data_L,
+
+ for (i = 0; i <= 3; i++) {
+ y_est[i] = i * 32;
+-
+- /* prevent division by zero */
+- if (G_fxp == 0)
+- return false;
+-
+ x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp;
+ }
+
++ if (y_est[max_index] == 0)
++ return false;
++
+ x_est_fxp1_nonlin =
+ x_est[max_index] - ((1 << scale_factor) * y_est[max_index] +
+ G_fxp) / G_fxp;
+@@ -457,6 +459,8 @@ static bool create_pa_curve(u32 *data_L,
+
+ Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10);
+ scale_B = scale_B / (1 << Q_scale_B);
++ if (scale_B == 0)
++ return false;
+ Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10);
+ Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10);
+ beta_raw = beta_raw / (1 << Q_beta);
--- /dev/null
+From 48a7c3df14d0cda850337a9b3f9e667a0b12a996 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Mon, 8 Nov 2010 20:40:53 +0530
+Subject: ath9k_hw: Fix memory leak on ath9k_hw_rf_alloc_ext_banks failure
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit 48a7c3df14d0cda850337a9b3f9e667a0b12a996 upstream.
+
+The allocated externel radio banks have to be freed in
+case of ath9k_hw_rf_alloc_ext_banks failure.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/hw.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -486,6 +486,7 @@ static int ath9k_hw_post_init(struct ath
+ ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
+ "Failed allocating banks for "
+ "external radio\n");
++ ath9k_hw_rf_free_ext_banks(ah);
+ return ecode;
+ }
+
--- /dev/null
+From 0dfa6dbb7372e581d3beb38b11772152114796b8 Mon Sep 17 00:00:00 2001
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+Date: Mon, 18 Oct 2010 22:47:54 -0700
+Subject: ath9k_hw: Fix TX carrier leakage for IEEE compliance on AR9003 2.2
+
+From: Luis R. Rodriguez <lrodriguez@atheros.com>
+
+commit 0dfa6dbb7372e581d3beb38b11772152114796b8 upstream.
+
+This updates the initvals for the AR9003 2.2 chipsets. The initvals
+are the initial register values we use for our registers upon hardware
+reset. This synchs up the initvals to match what our latest recommendation
+from our systems engineering team.
+
+The description of changes in this update:
+
+ Improves ability to support very strong Rx conditions.
+ Enhances DFS support for AP-mode.
+ Improves performance of Tx carrier leak calibration.
+ Adds support for Japan channel 14 Tx filtering requirements.
+ Improves Tx power accuracy.
+
+Impact:
+
+ Update required to address degraded throughput at very short range.
+ Update required for AP-mode DFS certification.
+ Update required to comply to IEEE Tx carrier leak specification.
+ May not meet expected +/- 2 dB Tx power accuracy without update.
+
+The most important fix here would be the TX carrier leakage required
+to comply with IEEE 802.11 specifications. The group of changes have
+been tested all together in one release.
+
+References:
+
+ Osprey 2.2 header file ver #33
+
+Checksums:
+
+$ ./initvals -f ar9003-2p2
+0x000000004a488fc7 ar9300_2p2_radio_postamble
+0x0000000046cb1300 ar9300Modes_lowest_ob_db_tx_gain_table_2p2
+0x00000000e912711f ar9300Modes_fast_clock_2p2
+0x0000000037ac0ee8 ar9300_2p2_radio_core
+0x00000000047a7700 ar9300Common_rx_gain_table_merlin_2p2
+0x0000000003f783bb ar9300_2p2_mac_postamble
+0x00000000301fc841 ar9300_2p2_soc_postamble
+0x000000005ec8075f ar9200_merlin_2p2_radio_core
+0x0000000083372ffa ar9300_2p2_baseband_postamble
+0x00000000c4f59974 ar9300_2p2_baseband_core
+0x00000000e20d2e72 ar9300Modes_high_power_tx_gain_table_2p2
+0x000000007fd55c70 ar9300Modes_high_ob_db_tx_gain_table_2p2
+0x0000000029495000 ar9300Common_rx_gain_table_2p2
+0x0000000042cb1300 ar9300Modes_low_ob_db_tx_gain_table_2p2
+0x00000000c4739cd6 ar9300_2p2_mac_core
+0x000000003521a300 ar9300Common_wo_xlna_rx_gain_table_2p2
+0x00000000a15ccf1b ar9300_2p2_soc_preamble
+0x0000000029734396 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2
+0x000000002d834396 ar9300PciePhy_clkreq_enable_L1_2p2
+0x0000000029834396 ar9300PciePhy_clkreq_disable_L1_2p2
+
+$ ./initvals -f ar9003-2p2 | sha1sum
+0ceddb5cf66737610fb51f04cf3e9ff71870c7b4 -
+
+Cc: Yixiang Li <yixiang.li@atheros.com>
+Cc: Don Breslin <don.breslin@atheros.com>
+Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 191 +++++++++++++------
+ 1 file changed, 135 insertions(+), 56 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
++++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+@@ -34,6 +34,10 @@ static const u32 ar9300_2p2_radio_postam
+
+ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
++ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+@@ -99,6 +103,30 @@ static const u32 ar9300Modes_lowest_ob_d
+ {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
++ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
++ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
++ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
++ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
++ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
++ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
++ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
++ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+@@ -118,7 +146,7 @@ static const u32 ar9300Modes_fast_clock_
+ {0x00008014, 0x044c044c, 0x08980898},
+ {0x0000801c, 0x148ec02b, 0x148ec057},
+ {0x00008318, 0x000044c0, 0x00008980},
+- {0x00009e00, 0x03721821, 0x03721821},
++ {0x00009e00, 0x0372131c, 0x0372131c},
+ {0x0000a230, 0x0000000b, 0x00000016},
+ {0x0000a254, 0x00000898, 0x00001130},
+ };
+@@ -595,15 +623,16 @@ static const u32 ar9300_2p2_baseband_pos
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+ {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+- {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+- {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
++ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
++ {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+- {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
++ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
++ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+@@ -624,16 +653,16 @@ static const u32 ar9300_2p2_baseband_pos
+ {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
+- {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
++ {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+- {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
++ {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
+ {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+- {0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
++ {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+@@ -649,13 +678,13 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x00009814, 0x9280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+- {0x00009834, 0x5f3ca3de},
++ {0x00009834, 0x6400a290},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14750600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+- {0x000098b0, 0x52440bbe},
++ {0x000098b0, 0x32840bbe},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+@@ -681,7 +710,6 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+- {0x00009e3c, 0xcf946222},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+@@ -694,7 +722,7 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+- {0x0000a22c, 0x01036a1e},
++ {0x0000a22c, 0x01036a27},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a2a0, 0x00000001},
+@@ -702,10 +730,6 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2cc, 0x18c43433},
+ {0x0000a2d4, 0x00000000},
+- {0x0000a2dc, 0x00000000},
+- {0x0000a2e0, 0x00000000},
+- {0x0000a2e4, 0x00000000},
+- {0x0000a2e8, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+@@ -753,33 +777,17 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+- {0x0000a43c, 0x00000000},
++ {0x0000a43c, 0x00100000},
+ {0x0000a440, 0x00000000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x06000080},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+- {0x0000a600, 0x00000000},
+- {0x0000a604, 0x00000000},
+- {0x0000a608, 0x00000000},
+- {0x0000a60c, 0x00000000},
+- {0x0000a610, 0x00000000},
+- {0x0000a614, 0x00000000},
+- {0x0000a618, 0x00000000},
+- {0x0000a61c, 0x00000000},
+- {0x0000a620, 0x00000000},
+- {0x0000a624, 0x00000000},
+- {0x0000a628, 0x00000000},
+- {0x0000a62c, 0x00000000},
+- {0x0000a630, 0x00000000},
+- {0x0000a634, 0x00000000},
+- {0x0000a638, 0x00000000},
+- {0x0000a63c, 0x00000000},
+ {0x0000a640, 0x00000000},
+ {0x0000a644, 0x3fad9d74},
+ {0x0000a648, 0x0048060a},
+- {0x0000a64c, 0x00000637},
++ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+@@ -802,10 +810,6 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000a8f4, 0x00000000},
+ {0x0000b2d0, 0x00000080},
+ {0x0000b2d4, 0x00000000},
+- {0x0000b2dc, 0x00000000},
+- {0x0000b2e0, 0x00000000},
+- {0x0000b2e4, 0x00000000},
+- {0x0000b2e8, 0x00000000},
+ {0x0000b2ec, 0x00000000},
+ {0x0000b2f0, 0x00000000},
+ {0x0000b2f4, 0x00000000},
+@@ -820,10 +824,6 @@ static const u32 ar9300_2p2_baseband_cor
+ {0x0000b8f4, 0x00000000},
+ {0x0000c2d0, 0x00000080},
+ {0x0000c2d4, 0x00000000},
+- {0x0000c2dc, 0x00000000},
+- {0x0000c2e0, 0x00000000},
+- {0x0000c2e4, 0x00000000},
+- {0x0000c2e8, 0x00000000},
+ {0x0000c2ec, 0x00000000},
+ {0x0000c2f0, 0x00000000},
+ {0x0000c2f4, 0x00000000},
+@@ -835,6 +835,10 @@ static const u32 ar9300_2p2_baseband_cor
+
+ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
++ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+@@ -855,7 +859,7 @@ static const u32 ar9300Modes_high_power_
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+- {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
++ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+@@ -900,6 +904,30 @@ static const u32 ar9300Modes_high_power_
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
++ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
++ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
++ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
++ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
++ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
++ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
++ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
+ {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
+ {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
+@@ -913,6 +941,10 @@ static const u32 ar9300Modes_high_power_
+
+ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
++ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
++ {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
++ {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+@@ -933,7 +965,7 @@ static const u32 ar9300Modes_high_ob_db_
+ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+- {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83},
++ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+@@ -978,6 +1010,30 @@ static const u32 ar9300Modes_high_ob_db_
+ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
++ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
++ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
++ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
++ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
++ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
++ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
++ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
++ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
++ {0x0000b2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
++ {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
++ {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000c2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800},
++ {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000},
++ {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
+ {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+@@ -1151,14 +1207,14 @@ static const u32 ar9300Common_rx_gain_ta
+ {0x0000b074, 0x00000000},
+ {0x0000b078, 0x00000000},
+ {0x0000b07c, 0x00000000},
+- {0x0000b080, 0x32323232},
+- {0x0000b084, 0x2f2f3232},
+- {0x0000b088, 0x23282a2d},
+- {0x0000b08c, 0x1c1e2123},
+- {0x0000b090, 0x14171919},
+- {0x0000b094, 0x0e0e1214},
+- {0x0000b098, 0x03050707},
+- {0x0000b09c, 0x00030303},
++ {0x0000b080, 0x2a2d2f32},
++ {0x0000b084, 0x21232328},
++ {0x0000b088, 0x19191c1e},
++ {0x0000b08c, 0x12141417},
++ {0x0000b090, 0x07070e0e},
++ {0x0000b094, 0x03030305},
++ {0x0000b098, 0x00000003},
++ {0x0000b09c, 0x00000000},
+ {0x0000b0a0, 0x00000000},
+ {0x0000b0a4, 0x00000000},
+ {0x0000b0a8, 0x00000000},
+@@ -1251,6 +1307,10 @@ static const u32 ar9300Common_rx_gain_ta
+
+ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
++ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+@@ -1316,6 +1376,30 @@ static const u32 ar9300Modes_low_ob_db_t
+ {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
+ {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
++ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
++ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
++ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
++ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
++ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
++ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
++ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
++ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
++ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
++ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
++ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
++ {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+ {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+ {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+@@ -1414,15 +1498,10 @@ static const u32 ar9300_2p2_mac_core[][2
+ {0x00008144, 0xffffffff},
+ {0x00008168, 0x00000000},
+ {0x0000816c, 0x00000000},
+- {0x00008170, 0x18486200},
+- {0x00008174, 0x33332210},
+- {0x00008178, 0x00000000},
+- {0x0000817c, 0x00020000},
+ {0x000081c0, 0x00000000},
+ {0x000081c4, 0x33332210},
+ {0x000081c8, 0x00000000},
+ {0x000081cc, 0x00000000},
+- {0x000081d4, 0x00000000},
+ {0x000081ec, 0x00000000},
+ {0x000081f0, 0x00000000},
+ {0x000081f4, 0x00000000},
--- /dev/null
+From 3ae74c33c4f799f6bf6d67240a94a0814a8f1944 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Tue, 14 Sep 2010 18:38:26 +0200
+Subject: ath9k_hw: handle rx key miss
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 3ae74c33c4f799f6bf6d67240a94a0814a8f1944 upstream.
+
+If AR_KeyMiss is set in the rx descriptor and AR_RxFrameOK is unset,
+the hardware could not locate a valid key during a decryption attempt.
+
+In this case, the frame must not be reported as decrypted, otherwise
+mac80211 sees only random garbage.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/ar9003_mac.c | 3 ++-
+ drivers/net/wireless/ath/ath9k/mac.c | 2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -616,7 +616,8 @@ int ath9k_hw_process_rxdesc_edma(struct
+ rxs->rs_status |= ATH9K_RXERR_DECRYPT;
+ } else if (rxsp->status11 & AR_MichaelErr) {
+ rxs->rs_status |= ATH9K_RXERR_MIC;
+- }
++ } else if (rxsp->status11 & AR_KeyMiss)
++ rxs->rs_status |= ATH9K_RXERR_DECRYPT;
+ }
+
+ return 0;
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -713,6 +713,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+ else if (ads.ds_rxstatus8 & AR_MichaelErr)
+ rs->rs_status |= ATH9K_RXERR_MIC;
++ else if (ads.ds_rxstatus8 & AR_KeyMiss)
++ rs->rs_status |= ATH9K_RXERR_DECRYPT;
+ }
+
+ return 0;
--- /dev/null
+From b5261cf4f3860bd772346a3e692683b6144dd44c Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+Date: Wed, 10 Nov 2010 17:51:26 +0530
+Subject: ath9k_hw: Set proper eeprom offset for AR9287 HTC devices
+
+From: Rajkumar Manoharan <rmanoharan@atheros.com>
+
+commit b5261cf4f3860bd772346a3e692683b6144dd44c upstream.
+
+AR9287 based PCI & USB devices are differed in eeprom start offset.
+So set proper the offset for HTC devices to read nvram correctly.
+
+Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/ath/ath9k/eeprom_9287.c | 2 +-
+ drivers/net/wireless/ath/ath9k/reg.h | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -37,7 +37,7 @@ static bool ath9k_hw_ar9287_fill_eeprom(
+ int addr, eep_start_loc;
+ eep_data = (u16 *)eep;
+
+- if (ah->hw_version.devid == 0x7015)
++ if (AR9287_HTC_DEVID(ah))
+ eep_start_loc = AR9287_HTC_EEP_START_LOC;
+ else
+ eep_start_loc = AR9287_EEP_START_LOC;
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -903,6 +903,10 @@
+ ((_ah)->hw_version.devid == 0x7015) || \
+ ((_ah)->hw_version.devid == 0x9018))
+
++#define AR9287_HTC_DEVID(_ah) \
++ (((_ah)->hw_version.devid == 0x7015) || \
++ ((_ah)->hw_version.devid == 0x1200))
++
+ #define AR_RADIO_SREV_MAJOR 0xf0
+ #define AR_RAD5133_SREV_MAJOR 0xc0
+ #define AR_RAD2133_SREV_MAJOR 0xd0
--- /dev/null
+From 354da653233898ed1e51f20cebac9705456bf9b1 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexdeucher@gmail.com>
+Date: Mon, 18 Oct 2010 23:45:39 -0400
+Subject: drm/radeon/kms: fix 2D tile height alignment in the r600 CS checker
+
+From: Alex Deucher <alexdeucher@gmail.com>
+
+commit 354da653233898ed1e51f20cebac9705456bf9b1 upstream.
+
+macro tile heights are aligned to num channels, not num banks.
+
+Noticed by Dave Airlie.
+
+Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/r600_cs.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/r600_cs.c
++++ b/drivers/gpu/drm/radeon/r600_cs.c
+@@ -228,7 +228,7 @@ static inline int r600_cs_track_validate
+ __func__, __LINE__, pitch);
+ return -EINVAL;
+ }
+- if (!IS_ALIGNED((height / 8), track->nbanks)) {
++ if (!IS_ALIGNED((height / 8), track->npipes)) {
+ dev_warn(p->dev, "%s:%d cb height (%d) invalid\n",
+ __func__, __LINE__, height);
+ return -EINVAL;
+@@ -367,7 +367,7 @@ static int r600_cs_track_check(struct ra
+ __func__, __LINE__, pitch);
+ return -EINVAL;
+ }
+- if ((height / 8) & (track->nbanks - 1)) {
++ if (!IS_ALIGNED((height / 8), track->npipes)) {
+ dev_warn(p->dev, "%s:%d db height (%d) invalid\n",
+ __func__, __LINE__, height);
+ return -EINVAL;
--- /dev/null
+From e2269308359d5863b6aa1fcb95a425a2ab255f1f Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu, 14 Oct 2010 17:41:53 +0000
+Subject: r6040: Fix multicast filter some more
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+commit e2269308359d5863b6aa1fcb95a425a2ab255f1f upstream.
+
+This code has been broken forever, but in several different and
+creative ways.
+
+So far as I can work out, the R6040 MAC filter has 4 exact-match
+entries, the first of which the driver uses for its assigned unicast
+address, plus a 64-entry hash-based filter for multicast addresses
+(maybe unicast as well?).
+
+The original version of this code would write the first 4 multicast
+addresses as exact-match entries from offset 1 (bug #1: there is no
+entry 4 so this could write to some PHY registers). It would fill the
+remainder of the exact-match entries with the broadcast address (bug #2:
+this would overwrite the last used entry). If more than 4 multicast
+addresses were configured, it would set up the hash table, write some
+random crap to the MAC control register (bug #3) and finally walk off
+the end of the list when filling the exact-match entries (bug #4).
+
+All of this seems to be pointless, since it sets the promiscuous bit
+when the interface is made promiscuous or if >4 multicast addresses
+are enabled, and never clears it (bug #5, masking bug #2).
+
+The recent(ish) changes to the multicast list fixed bug #4, but
+completely removed the limit on iteration over the exact-match entries
+(bug #6).
+
+Bug #4 was reported as
+<https://bugzilla.kernel.org/show_bug.cgi?id=15355> and more recently
+as <http://bugs.debian.org/600155>. Florian Fainelli attempted to fix
+these in commit 3bcf8229a8c49769e48d3e0bd1e20d8e003f8106, but that
+actually dealt with bugs #1-3, bug #4 having been fixed in mainline at
+that point.
+
+That commit fixes the most important current bug #6.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/r6040.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/r6040.c
++++ b/drivers/net/r6040.c
+@@ -893,16 +893,18 @@ static void r6040_multicast_list(struct
+ /* Multicast Address 1~4 case */
+ i = 0;
+ netdev_for_each_mc_addr(ha, dev) {
+- if (i < MCAST_MAX) {
+- adrp = (u16 *) ha->addr;
+- iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
+- iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
+- iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
+- } else {
+- iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
+- iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
+- iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
+- }
++ if (i >= MCAST_MAX)
++ break;
++ adrp = (u16 *) ha->addr;
++ iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
++ iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
++ iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
++ i++;
++ }
++ while (i < MCAST_MAX) {
++ iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
++ iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
++ iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
+ i++;
+ }
+ }
jme-fix-phy-power-off-error.patch
irda-fix-parameter-extraction-stack-overflow.patch
irda-fix-heap-memory-corruption-in-iriap.c.patch
+r6040-fix-multicast-filter-some-more.patch
+drm-radeon-kms-fix-2d-tile-height-alignment-in-the-r600-cs-checker.patch
+ath9k-built-in-rate-control-a-mpdu-fix.patch
+ath9k-fix-channel-flag-regd-issues-with-multiple-cards.patch
+ath9k-a-mpdu-rate-control-info-fix.patch
+ath9k-fix-tx-struck-state-with-paprd.patch
+ath9k-clean-up-fix-aggregation-session-flush.patch
+ath9k-fix-power-save-race-conditions.patch
+ath9k-fix-an-aggregation-start-related-race-condition.patch
+ath9k-fix-regression-which-prevents-chip-sleep-after-cab-data.patch
+ath9k_hw-handle-rx-key-miss.patch
+ath9k-fix-regression-which-disabled-ps-on-ath9k.patch
+ath9k-fix-regression-on-beacon-loss-after-bgscan.patch
+ath9k-fix-spurious-mic-failure-reports.patch
+ath9k-resume-aggregation-immediately-after-a-hardware-reset.patch
+ath9k_hw-fix-divide-by-zero-cases-in-paprd.patch
+ath9k_hw-fix-tx-carrier-leakage-for-ieee-compliance-on-ar9003-2.2.patch
+ath9k_htc-set-proper-firmware-offset-for-netgear-wnda3200.patch
+ath9k-fix-incorrect-access-of-rate-flags-in-rc.patch
+ath9k-rename-rxflushlock-to-pcu_lock.patch
+ath9k-fix-tx-aggregation-flush-on-ar9003.patch
+ath9k-add-locking-for-stopping-rx.patch
+ath9k-fix-enabling-ani-tx-monitor-after-bg-scan.patch
+ath9k_hw-fix-memory-leak-on-ath9k_hw_rf_alloc_ext_banks-failure.patch
+ath9k_hw-fix-ar9280-surprise-removal-during-frequent-idle-on-off.patch
+ath9k_htc-avoid-setting-qos-control-for-non-qos-frames.patch
+ath9k-add-locking-for-starting-the-pcu-on-rx.patch
+ath9k_hw-set-proper-eeprom-offset-for-ar9287-htc-devices.patch
+ath9k_htc-add-new-devices-into-ar7010.patch
+ath9k_htc-add-support-for-device-id-3346.patch
+ath9k_htc-update-usb-device-id-list.patch
+ath9k-lock-reset-and-pcu-start-stopping.patch