2012-08-06 16:44:42

by Sujith Manoharan

[permalink] [raw]
Subject: [PATCH 3.5.y 2/2] compat-wireless: Add new cherry-picked patches

Signed-off-by: Sujith Manoharan <[email protected]>
---
...art-noisefloor-calibration-after-MCI-rese.patch | 37 ++
...-not-load-noise-floor-readings-when-it-is.patch | 42 ++
...ullsleep-power-consumption-when-BTCOEX-is.patch | 59 +++
...ower-consumption-on-network-sleep-when-BT.patch | 89 ++++
...k_hw-fix-AR9462-2g5g-switch-on-full-reset.patch | 57 +++
.../0117-ath9k-Fix-MCI-cleanup.patch | 35 ++
...the-BTCOEX-timers-before-disabling-BTCOEX.patch | 46 +++
...move-debugging-masks-from-AR_MCI_INTERRUP.patch | 34 ++
.../0143-ath9k-Fix-beacon-setup.patch | 309 ++++++++++++++
...4-ath9k_hw-Cleanup-ath9k_hw_set_tsfadjust.patch | 90 +++++
.../0145-ath9k-Cleanup-interface-handling.patch | 62 +++
.../0146-ath9k-Simplify-ASSOC-handling.patch | 197 +++++++++
.../0147-ath9k-Cleanup-beacon-logic.patch | 448 +++++++++++++++++++++
.../0148-ath9k-Remove-is_bslot_active.patch | 88 ++++
...-ath9k-Cleanup-beacon-queue-configuration.patch | 119 ++++++
...0-ath9k-Set-the-TSF-adjust-value-properly.patch | 61 +++
.../0151-ath9k-Cleanup-the-beacon-tasklet.patch | 281 +++++++++++++
.../0152-ath9k-Fix-ANI-management.patch | 206 ++++++++++
...0153-ath9k-Reconfigure-VIF-state-properly.patch | 73 ++++
.../0154-ath9k-Fix-race-in-reset-work-usage.patch | 256 ++++++++++++
20 files changed, 2589 insertions(+)
create mode 100644 linux-next-cherry-picks/0092-ath9k_hw-start-noisefloor-calibration-after-MCI-rese.patch
create mode 100644 linux-next-cherry-picks/0093-ath9k_hw-do-not-load-noise-floor-readings-when-it-is.patch
create mode 100644 linux-next-cherry-picks/0094-ath9k-fix-fullsleep-power-consumption-when-BTCOEX-is.patch
create mode 100644 linux-next-cherry-picks/0095-ath9k-fix-power-consumption-on-network-sleep-when-BT.patch
create mode 100644 linux-next-cherry-picks/0096-ath9k_hw-fix-AR9462-2g5g-switch-on-full-reset.patch
create mode 100644 linux-next-cherry-picks/0117-ath9k-Fix-MCI-cleanup.patch
create mode 100644 linux-next-cherry-picks/0118-ath9k-Stop-the-BTCOEX-timers-before-disabling-BTCOEX.patch
create mode 100644 linux-next-cherry-picks/0119-ath9k_hw-remove-debugging-masks-from-AR_MCI_INTERRUP.patch
create mode 100644 linux-next-cherry-picks/0143-ath9k-Fix-beacon-setup.patch
create mode 100644 linux-next-cherry-picks/0144-ath9k_hw-Cleanup-ath9k_hw_set_tsfadjust.patch
create mode 100644 linux-next-cherry-picks/0145-ath9k-Cleanup-interface-handling.patch
create mode 100644 linux-next-cherry-picks/0146-ath9k-Simplify-ASSOC-handling.patch
create mode 100644 linux-next-cherry-picks/0147-ath9k-Cleanup-beacon-logic.patch
create mode 100644 linux-next-cherry-picks/0148-ath9k-Remove-is_bslot_active.patch
create mode 100644 linux-next-cherry-picks/0149-ath9k-Cleanup-beacon-queue-configuration.patch
create mode 100644 linux-next-cherry-picks/0150-ath9k-Set-the-TSF-adjust-value-properly.patch
create mode 100644 linux-next-cherry-picks/0151-ath9k-Cleanup-the-beacon-tasklet.patch
create mode 100644 linux-next-cherry-picks/0152-ath9k-Fix-ANI-management.patch
create mode 100644 linux-next-cherry-picks/0153-ath9k-Reconfigure-VIF-state-properly.patch
create mode 100644 linux-next-cherry-picks/0154-ath9k-Fix-race-in-reset-work-usage.patch

diff --git a/linux-next-cherry-picks/0092-ath9k_hw-start-noisefloor-calibration-after-MCI-rese.patch b/linux-next-cherry-picks/0092-ath9k_hw-start-noisefloor-calibration-after-MCI-rese.patch
new file mode 100644
index 0000000..bbed3d8
--- /dev/null
+++ b/linux-next-cherry-picks/0092-ath9k_hw-start-noisefloor-calibration-after-MCI-rese.patch
@@ -0,0 +1,37 @@
+From 1fe860edb0787fa2df6d043e34a55dc739e235f0 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <[email protected]>
+Date: Sun, 1 Jul 2012 19:53:51 +0530
+Subject: [PATCH] ath9k_hw: start noisefloor calibration after MCI reset
+
+noisefloor calibration has to be loaded and started after
+chip reset completion and restoring chainmask. Right now it is
+being started before MCI reset completion on full reset. Fix that.
+
+Signed-off-by: Rajkumar Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/hw.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1949,9 +1949,6 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ if (!ath9k_hw_init_cal(ah, chan))
+ return -EIO;
+
+- ath9k_hw_loadnf(ah, chan);
+- ath9k_hw_start_nfcal(ah, true);
+-
+ if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata))
+ return -EIO;
+
+@@ -2000,6 +1997,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ if (ath9k_hw_mci_is_enabled(ah))
+ ar9003_mci_check_bt(ah);
+
++ ath9k_hw_loadnf(ah, chan);
++ ath9k_hw_start_nfcal(ah, true);
++
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ ar9003_hw_bb_watchdog_config(ah);
+
diff --git a/linux-next-cherry-picks/0093-ath9k_hw-do-not-load-noise-floor-readings-when-it-is.patch b/linux-next-cherry-picks/0093-ath9k_hw-do-not-load-noise-floor-readings-when-it-is.patch
new file mode 100644
index 0000000..635fd6a
--- /dev/null
+++ b/linux-next-cherry-picks/0093-ath9k_hw-do-not-load-noise-floor-readings-when-it-is.patch
@@ -0,0 +1,42 @@
+From 54717e5330318d53180a1f3026f617509031ee68 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <[email protected]>
+Date: Sun, 1 Jul 2012 19:53:52 +0530
+Subject: [PATCH] ath9k_hw: do not load noise floor readings when it is
+ running
+
+Noise floor calibration is performed on longcal interval and
+the reading will be updated in history buffer. On rare occasions,
+the previous noisefloor calibration might not be completed within
+the period and trying to load nf reading will be failed. In such
+situation, postpone the nf cabliration to next cycle to give
+enough time to complete the calibration. This was already taken
+care for ar9002 chips.
+
+Signed-off-by: Rajkumar Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ar9003_calib.c | 13 +++++--------
+ 1 file changed, 5 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+@@ -159,14 +159,11 @@ static bool ar9003_hw_calibrate(struct a
+ }
+ }
+
+- /* Do NF cal only at longer intervals */
+- if (longcal) {
+- /*
+- * Get the value from the previous NF cal and update
+- * history buffer.
+- */
+- ath9k_hw_getnf(ah, chan);
+-
++ /*
++ * Do NF cal only at longer intervals. Get the value from
++ * the previous NF cal and update history buffer.
++ */
++ if (longcal && ath9k_hw_getnf(ah, chan)) {
+ /*
+ * Load the NF from history buffer of the current channel.
+ * NF is slow time-variant, so it is OK to use a historical
diff --git a/linux-next-cherry-picks/0094-ath9k-fix-fullsleep-power-consumption-when-BTCOEX-is.patch b/linux-next-cherry-picks/0094-ath9k-fix-fullsleep-power-consumption-when-BTCOEX-is.patch
new file mode 100644
index 0000000..d59005a
--- /dev/null
+++ b/linux-next-cherry-picks/0094-ath9k-fix-fullsleep-power-consumption-when-BTCOEX-is.patch
@@ -0,0 +1,59 @@
+From b73f3e78047abdcc8bc33f97445ef6691ce3cc3d Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <[email protected]>
+Date: Sun, 1 Jul 2012 19:53:53 +0530
+Subject: [PATCH] ath9k: fix fullsleep power consumption when BTCOEX is
+ enabled
+
+As soon as the interface brought up, btcoex timer starts running
+eventhough the interface is in idle state and WLAN chip is moved
+to full sleep mode. There is no point in running btcoex timer when
+the wlan interface is in sleep mode and also it might consumes
+more power on WLAN idle unassociated state. So lets stop the
+btcoex when wlan is idle state.
+
+Signed-off-by: Rajkumar Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/main.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -666,8 +666,6 @@ static int ath9k_start(struct ieee80211_
+
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
+- ath9k_start_btcoex(sc);
+-
+ if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
+ common->bus_ops->extn_synch_en(common);
+
+@@ -774,8 +772,6 @@ static void ath9k_stop(struct ieee80211_
+ /* Ensure HW is awake when we try to shut it down. */
+ ath9k_ps_wakeup(sc);
+
+- ath9k_stop_btcoex(sc);
+-
+ spin_lock_bh(&sc->sc_pcu_lock);
+
+ /* prevent tasklets to enable interrupts once we disable them */
+@@ -1139,14 +1135,17 @@ static int ath9k_config(struct ieee80211
+
+ if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+ sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
+- if (sc->ps_idle)
++ if (sc->ps_idle) {
+ ath_cancel_work(sc);
+- else
++ ath9k_stop_btcoex(sc);
++ } else {
++ ath9k_start_btcoex(sc);
+ /*
+ * The chip needs a reset to properly wake up from
+ * full sleep
+ */
+ reset_channel = ah->chip_fullsleep;
++ }
+ }
+
+ /*
diff --git a/linux-next-cherry-picks/0095-ath9k-fix-power-consumption-on-network-sleep-when-BT.patch b/linux-next-cherry-picks/0095-ath9k-fix-power-consumption-on-network-sleep-when-BT.patch
new file mode 100644
index 0000000..b18fffd
--- /dev/null
+++ b/linux-next-cherry-picks/0095-ath9k-fix-power-consumption-on-network-sleep-when-BT.patch
@@ -0,0 +1,89 @@
+From 08d4df410a9ff02c999e69268ec2f4fbfeaac8d7 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <[email protected]>
+Date: Sun, 1 Jul 2012 19:53:54 +0530
+Subject: [PATCH] ath9k: fix power consumption on network sleep when BTCOEX is
+ enabled
+
+The chip is waken up for every 45ms in btcoex timer cycle to
+for sharing the radio between BT and WLAN. Whenever the wlan
+interface is in network sleep mode, do not schedule hw timers.
+This could reduce power consumption on idle associated state.
+
+Signed-off-by: Rajkumar Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 4 ++++
+ drivers/net/wireless/ath/ath9k/gpio.c | 16 ++++++++++++++++
+ drivers/net/wireless/ath/ath9k/main.c | 2 ++
+ 3 files changed, 22 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -481,6 +481,7 @@ void ath9k_btcoex_timer_resume(struct at
+ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
+ void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
+ u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
++void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
+ #else
+ static inline int ath9k_init_btcoex(struct ath_softc *sc)
+ {
+@@ -504,6 +505,9 @@ static inline u16 ath9k_btcoex_aggr_limi
+ {
+ return 0;
+ }
++static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
++{
++}
+ #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
+
+ /********************/
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -194,6 +194,14 @@ static void ath_btcoex_period_timer(unsi
+ struct ath_mci_profile *mci = &btcoex->mci;
+ u32 timer_period;
+ bool is_btscan;
++ unsigned long flags;
++
++ spin_lock_irqsave(&sc->sc_pm_lock, flags);
++ if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
++ goto skip_hw_wakeup;
++ }
++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+
+ ath9k_ps_wakeup(sc);
+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
+@@ -232,6 +240,7 @@ static void ath_btcoex_period_timer(unsi
+ }
+
+ ath9k_ps_restore(sc);
++skip_hw_wakeup:
+ timer_period = btcoex->btcoex_period;
+ mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
+ }
+@@ -328,6 +337,13 @@ void ath9k_btcoex_timer_pause(struct ath
+ btcoex->hw_timer_enabled = false;
+ }
+
++void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
++{
++ struct ath_btcoex *btcoex = &sc->btcoex;
++
++ ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
++}
++
+ u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
+ {
+ struct ath_btcoex *btcoex = &sc->btcoex;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -130,6 +130,8 @@ void ath9k_ps_restore(struct ath_softc *
+ PS_WAIT_FOR_PSPOLL_DATA |
+ PS_WAIT_FOR_TX_ACK))) {
+ mode = ATH9K_PM_NETWORK_SLEEP;
++ if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
++ ath9k_btcoex_stop_gen_timer(sc);
+ } else {
+ goto unlock;
+ }
diff --git a/linux-next-cherry-picks/0096-ath9k_hw-fix-AR9462-2g5g-switch-on-full-reset.patch b/linux-next-cherry-picks/0096-ath9k_hw-fix-AR9462-2g5g-switch-on-full-reset.patch
new file mode 100644
index 0000000..cf159ac
--- /dev/null
+++ b/linux-next-cherry-picks/0096-ath9k_hw-fix-AR9462-2g5g-switch-on-full-reset.patch
@@ -0,0 +1,57 @@
+From 83bfea42190b72acc1a1653bc10b21e741490087 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <[email protected]>
+Date: Sun, 1 Jul 2012 19:53:55 +0530
+Subject: [PATCH] ath9k_hw: fix AR9462 2g5g switch on full reset
+
+On full reset, mci reset will put LNA update on 2G mode. And
+Whenever 2g5g_switch is forced at the end of full reset, lna
+update should not be skipped. Not doing so, is affecting WLAN
+rx and causing beacon loss when BTCOEX is enabled on AR9462.
+
+Signed-off-by: Rajkumar Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ar9003_mci.c | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+@@ -1015,12 +1015,9 @@ void ar9003_mci_2g5g_switch(struct ath_h
+ return;
+
+ if (mci->is_2g) {
+- if (!force) {
+- ar9003_mci_send_2g5g_status(ah, true);
+-
+- ar9003_mci_send_lna_transfer(ah, true);
+- udelay(5);
+- }
++ ar9003_mci_send_2g5g_status(ah, true);
++ ar9003_mci_send_lna_transfer(ah, true);
++ udelay(5);
+
+ REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
+ AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+@@ -1030,10 +1027,8 @@ void ar9003_mci_2g5g_switch(struct ath_h
+ if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
+ ar9003_mci_osla_setup(ah, true);
+ } else {
+- if (!force) {
+- ar9003_mci_send_lna_take(ah, true);
+- udelay(5);
+- }
++ ar9003_mci_send_lna_take(ah, true);
++ udelay(5);
+
+ REG_SET_BIT(ah, AR_MCI_TX_CTRL,
+ AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
+@@ -1041,8 +1036,7 @@ void ar9003_mci_2g5g_switch(struct ath_h
+ AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
+
+ ar9003_mci_osla_setup(ah, false);
+- if (!force)
+- ar9003_mci_send_2g5g_status(ah, true);
++ ar9003_mci_send_2g5g_status(ah, true);
+ }
+ }
+
diff --git a/linux-next-cherry-picks/0117-ath9k-Fix-MCI-cleanup.patch b/linux-next-cherry-picks/0117-ath9k-Fix-MCI-cleanup.patch
new file mode 100644
index 0000000..9696abb
--- /dev/null
+++ b/linux-next-cherry-picks/0117-ath9k-Fix-MCI-cleanup.patch
@@ -0,0 +1,35 @@
+From dd89f05a7572684bbbc1483c60418504cc91cfe6 Mon Sep 17 00:00:00 2001
+From: Mohammed Shafi Shajakhan <[email protected]>
+Date: Fri, 6 Jul 2012 20:09:16 +0530
+Subject: [PATCH] ath9k: Fix MCI cleanup
+
+We are doing MCI cleanup eventhough BTCOEX is not enabled
+via module parameter. This means we do ath_mci_cleanup
+though we skipped calling ath_mci_setup. Yet it does not
+causes any issues now as we free the DMA buffer allocated
+only when it is allocated during ath_mci_setup.
+
+Reviewed-by: Bala Shanmugam <[email protected]>
+Signed-off-by: Mohammed Shafi Shajakhan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/gpio.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -403,11 +403,13 @@ void ath9k_stop_btcoex(struct ath_softc
+
+ void ath9k_deinit_btcoex(struct ath_softc *sc)
+ {
++ struct ath_hw *ah = sc->sc_ah;
++
+ if ((sc->btcoex.no_stomp_timer) &&
+ ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
+ ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
+
+- if (AR_SREV_9462(sc->sc_ah))
++ if (ath9k_hw_mci_is_enabled(ah))
+ ath_mci_cleanup(sc);
+ }
+
diff --git a/linux-next-cherry-picks/0118-ath9k-Stop-the-BTCOEX-timers-before-disabling-BTCOEX.patch b/linux-next-cherry-picks/0118-ath9k-Stop-the-BTCOEX-timers-before-disabling-BTCOEX.patch
new file mode 100644
index 0000000..4acb062
--- /dev/null
+++ b/linux-next-cherry-picks/0118-ath9k-Stop-the-BTCOEX-timers-before-disabling-BTCOEX.patch
@@ -0,0 +1,46 @@
+From c32cdbd84ffe289a1386eccb794b047a8366913d Mon Sep 17 00:00:00 2001
+From: Mohammed Shafi Shajakhan <[email protected]>
+Date: Fri, 6 Jul 2012 20:09:32 +0530
+Subject: [PATCH] ath9k: Stop the BTCOEX timers before disabling BTCOEX
+
+Its safe to stop the BTCOEX timers 'period_timer' and
+'no_stomp_timer' before disabling BTCOEX. These timers
+can call ath9k_hw_btcoex_enable (or) change the BT
+stomp type if they seem to be running after we had
+called ath9k_hw_btcoex_disable, which is obviously
+not correct.
+
+Cc: Rajkumar Manoharan <[email protected]>
+Cc: Bala Shanmugam <[email protected]>
+Signed-off-by: Mohammed Shafi Shajakhan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/gpio.c | 2 +-
+ drivers/net/wireless/ath/ath9k/mci.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -393,9 +393,9 @@ void ath9k_stop_btcoex(struct ath_softc
+
+ if (ah->btcoex_hw.enabled &&
+ ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
+- ath9k_hw_btcoex_disable(ah);
+ if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
+ ath9k_btcoex_timer_pause(sc);
++ ath9k_hw_btcoex_disable(ah);
+ if (AR_SREV_9462(ah))
+ ath_mci_flush_profile(&sc->btcoex.mci);
+ }
+--- a/drivers/net/wireless/ath/ath9k/mci.c
++++ b/drivers/net/wireless/ath/ath9k/mci.c
+@@ -174,8 +174,8 @@ skip_tuning:
+ btcoex->btcoex_period >>= 1;
+ }
+
+- ath9k_hw_btcoex_disable(sc->sc_ah);
+ ath9k_btcoex_timer_pause(sc);
++ ath9k_hw_btcoex_disable(sc->sc_ah);
+
+ if (IS_CHAN_5GHZ(sc->sc_ah->curchan))
+ return;
diff --git a/linux-next-cherry-picks/0119-ath9k_hw-remove-debugging-masks-from-AR_MCI_INTERRUP.patch b/linux-next-cherry-picks/0119-ath9k_hw-remove-debugging-masks-from-AR_MCI_INTERRUP.patch
new file mode 100644
index 0000000..252e4f3
--- /dev/null
+++ b/linux-next-cherry-picks/0119-ath9k_hw-remove-debugging-masks-from-AR_MCI_INTERRUP.patch
@@ -0,0 +1,34 @@
+From d081257c78ace442db2a59f0aa4c52c69b252663 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <[email protected]>
+Date: Sun, 8 Jul 2012 12:53:16 +0530
+Subject: [PATCH] ath9k_hw: remove debugging masks from
+ AR_MCI_INTERRUPT_RX_MSG_DEFAULT
+
+Remove the CONT_* and LNA_* messages from
+AR_MCI_INTERRUPT_RX_MSG_DEFAULT. Those MCI rx messages only
+meant for debugging purpose. Including them in default rx_msg
+series could raise huge amount of MCI interrupts when BT traffic
+is going on. And also it increases power consumption when WLAN
+is scanning.
+
+Signed-off-by: Rajkumar Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/reg.h | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -2077,12 +2077,6 @@ enum {
+ AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET| \
+ AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \
+ AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING| \
+- AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \
+- AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \
+- AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \
+- AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \
+- AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \
+- AR_MCI_INTERRUPT_RX_MSG_CONT_RST | \
+ AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)
+
+ #define AR_MCI_CPU_INT 0x1840
diff --git a/linux-next-cherry-picks/0143-ath9k-Fix-beacon-setup.patch b/linux-next-cherry-picks/0143-ath9k-Fix-beacon-setup.patch
new file mode 100644
index 0000000..31c3f4c
--- /dev/null
+++ b/linux-next-cherry-picks/0143-ath9k-Fix-beacon-setup.patch
@@ -0,0 +1,309 @@
+From 130ef6e9dc76f821caf98fa9ed6e2dafe15f3b1f Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:15:30 +0530
+Subject: [PATCH] ath9k: Fix beacon setup
+
+This patch revamps interface addition and deletion and simplifies
+slot allocation. There is no need to setup the beacon buffer
+in add/remove interface, remove this and use simple APIs for
+assigning/deleting slots.
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 4 +-
+ drivers/net/wireless/ath/ath9k/beacon.c | 141 ++++++++------------------------
+ drivers/net/wireless/ath/ath9k/main.c | 48 +++--------
+ 3 files changed, 47 insertions(+), 146 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -413,8 +413,8 @@ struct ath_beacon {
+
+ void ath_beacon_tasklet(unsigned long data);
+ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
+-int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif);
+-void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
++void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
++void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+ int ath_beaconq_config(struct ath_softc *sc);
+ void ath_set_beacon(struct ath_softc *sc);
+ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -222,132 +222,57 @@ static struct ath_buf *ath_beacon_genera
+ return bf;
+ }
+
+-int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
++void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
+ {
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+- struct ath_vif *avp;
+- struct ath_buf *bf;
+- struct sk_buff *skb;
+- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+- __le64 tstamp;
+-
+- avp = (void *)vif->drv_priv;
+-
+- /* Allocate a beacon descriptor if we haven't done so. */
+- if (!avp->av_bcbuf) {
+- /* Allocate beacon state for hostap/ibss. We know
+- * a buffer is available. */
+- avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf,
+- struct ath_buf, list);
+- list_del(&avp->av_bcbuf->list);
+-
+- if (ath9k_uses_beacons(vif->type)) {
+- int slot;
+- /*
+- * Assign the vif to a beacon xmit slot. As
+- * above, this cannot fail to find one.
+- */
+- avp->av_bslot = 0;
+- for (slot = 0; slot < ATH_BCBUF; slot++)
+- if (sc->beacon.bslot[slot] == NULL) {
+- avp->av_bslot = slot;
+- avp->is_bslot_active = false;
+-
+- /* NB: keep looking for a double slot */
+- if (slot == 0 || !sc->beacon.bslot[slot-1])
+- break;
+- }
+- BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
+- sc->beacon.bslot[avp->av_bslot] = vif;
+- sc->nbcnvifs++;
+- }
+- }
++ struct ath_vif *avp = (void *)vif->drv_priv;
++ int slot;
+
+- /* release the previous beacon frame, if it already exists. */
+- bf = avp->av_bcbuf;
+- if (bf->bf_mpdu != NULL) {
+- skb = bf->bf_mpdu;
+- dma_unmap_single(sc->dev, bf->bf_buf_addr,
+- skb->len, DMA_TO_DEVICE);
+- dev_kfree_skb_any(skb);
+- bf->bf_mpdu = NULL;
+- bf->bf_buf_addr = 0;
+- }
++ avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, struct ath_buf, list);
++ list_del(&avp->av_bcbuf->list);
+
+- /* NB: the beacon data buffer must be 32-bit aligned. */
+- skb = ieee80211_beacon_get(sc->hw, vif);
+- if (skb == NULL)
+- return -ENOMEM;
+-
+- tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+- sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp);
+- /* Calculate a TSF adjustment factor required for staggered beacons. */
+- if (avp->av_bslot > 0) {
+- u64 tsfadjust;
+- int intval;
+-
+- intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+-
+- /*
+- * Calculate the TSF offset for this beacon slot, i.e., the
+- * number of usecs that need to be added to the timestamp field
+- * in Beacon and Probe Response frames. Beacon slot 0 is
+- * processed at the correct offset, so it does not require TSF
+- * adjustment. Other slots are adjusted to get the timestamp
+- * close to the TBTT for the BSS.
+- */
+- tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF;
+- avp->tsf_adjust = cpu_to_le64(tsfadjust);
+-
+- ath_dbg(common, BEACON,
+- "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
+- avp->av_bslot, intval, (unsigned long long)tsfadjust);
+-
+- ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
+- avp->tsf_adjust;
+- } else
+- avp->tsf_adjust = cpu_to_le64(0);
+-
+- bf->bf_mpdu = skb;
+- bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+- skb->len, DMA_TO_DEVICE);
+- if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
+- dev_kfree_skb_any(skb);
+- bf->bf_mpdu = NULL;
+- bf->bf_buf_addr = 0;
+- ath_err(common, "dma_mapping_error on beacon alloc\n");
+- return -ENOMEM;
++ for (slot = 0; slot < ATH_BCBUF; slot++) {
++ if (sc->beacon.bslot[slot] == NULL) {
++ avp->av_bslot = slot;
++ avp->is_bslot_active = false;
++ break;
++ }
+ }
+- avp->is_bslot_active = true;
+
+- return 0;
++ sc->beacon.bslot[avp->av_bslot] = vif;
++ sc->nbcnvifs++;
++
++ ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n",
++ avp->av_bslot);
+ }
+
+-void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
++void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
+ {
+- if (avp->av_bcbuf != NULL) {
+- struct ath_buf *bf;
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ struct ath_vif *avp = (void *)vif->drv_priv;
++ struct ath_buf *bf = avp->av_bcbuf;
+
+- avp->is_bslot_active = false;
+- if (avp->av_bslot != -1) {
+- sc->beacon.bslot[avp->av_bslot] = NULL;
+- sc->nbcnvifs--;
+- avp->av_bslot = -1;
+- }
++ ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
++ avp->av_bslot);
+
+- bf = avp->av_bcbuf;
+- if (bf->bf_mpdu != NULL) {
+- struct sk_buff *skb = bf->bf_mpdu;
+- dma_unmap_single(sc->dev, bf->bf_buf_addr,
+- skb->len, DMA_TO_DEVICE);
+- dev_kfree_skb_any(skb);
+- bf->bf_mpdu = NULL;
+- bf->bf_buf_addr = 0;
+- }
+- list_add_tail(&bf->list, &sc->beacon.bbuf);
++ tasklet_disable(&sc->bcon_tasklet);
+
+- avp->av_bcbuf = NULL;
++ if (bf && bf->bf_mpdu) {
++ struct sk_buff *skb = bf->bf_mpdu;
++ dma_unmap_single(sc->dev, bf->bf_buf_addr,
++ skb->len, DMA_TO_DEVICE);
++ dev_kfree_skb_any(skb);
++ bf->bf_mpdu = NULL;
++ bf->bf_buf_addr = 0;
+ }
++
++ avp->av_bcbuf = NULL;
++ avp->is_bslot_active = false;
++ sc->beacon.bslot[avp->av_bslot] = NULL;
++ sc->nbcnvifs--;
++ list_add_tail(&bf->list, &sc->beacon.bbuf);
++
++ tasklet_enable(&sc->bcon_tasklet);
+ }
+
+ void ath_beacon_tasklet(unsigned long data)
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -840,16 +840,6 @@ bool ath9k_uses_beacons(int type)
+ }
+ }
+
+-static void ath9k_reclaim_beacon(struct ath_softc *sc,
+- struct ieee80211_vif *vif)
+-{
+- struct ath_vif *avp = (void *)vif->drv_priv;
+-
+- ath9k_set_beaconing_status(sc, false);
+- ath_beacon_return(sc, avp);
+- ath9k_set_beaconing_status(sc, true);
+-}
+-
+ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+ {
+ struct ath9k_vif_iter_data *iter_data = data;
+@@ -965,22 +955,6 @@ static void ath9k_calculate_summary_stat
+ }
+ }
+
+-/* Called with sc->mutex held, vif counts set up properly. */
+-static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw,
+- struct ieee80211_vif *vif)
+-{
+- struct ath_softc *sc = hw->priv;
+-
+- ath9k_calculate_summary_state(hw, vif);
+-
+- if (ath9k_uses_beacons(vif->type)) {
+- /* Reserve a beacon slot for the vif */
+- ath9k_set_beaconing_status(sc, false);
+- ath_beacon_alloc(sc, vif);
+- ath9k_set_beaconing_status(sc, true);
+- }
+-}
+-
+ static int ath9k_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+ {
+@@ -1020,7 +994,10 @@ static int ath9k_add_interface(struct ie
+
+ sc->nvifs++;
+
+- ath9k_do_vif_add_setup(hw, vif);
++ ath9k_calculate_summary_state(hw, vif);
++ if (ath9k_uses_beacons(vif->type))
++ ath9k_beacon_assign_slot(sc, vif);
++
+ out:
+ mutex_unlock(&sc->mutex);
+ ath9k_ps_restore(sc);
+@@ -1037,6 +1014,7 @@ static int ath9k_change_interface(struct
+ int ret = 0;
+
+ ath_dbg(common, CONFIG, "Change Interface\n");
++
+ mutex_lock(&sc->mutex);
+ ath9k_ps_wakeup(sc);
+
+@@ -1049,15 +1027,16 @@ static int ath9k_change_interface(struct
+ }
+ }
+
+- /* Clean up old vif stuff */
+ if (ath9k_uses_beacons(vif->type))
+- ath9k_reclaim_beacon(sc, vif);
++ ath9k_beacon_remove_slot(sc, vif);
+
+- /* Add new settings */
+ vif->type = new_type;
+ vif->p2p = p2p;
+
+- ath9k_do_vif_add_setup(hw, vif);
++ ath9k_calculate_summary_state(hw, vif);
++ if (ath9k_uses_beacons(vif->type))
++ ath9k_beacon_assign_slot(sc, vif);
++
+ out:
+ ath9k_ps_restore(sc);
+ mutex_unlock(&sc->mutex);
+@@ -1077,9 +1056,8 @@ static void ath9k_remove_interface(struc
+
+ sc->nvifs--;
+
+- /* Reclaim beacon resources */
+ if (ath9k_uses_beacons(vif->type))
+- ath9k_reclaim_beacon(sc, vif);
++ ath9k_beacon_remove_slot(sc, vif);
+
+ ath9k_calculate_summary_state(hw, NULL);
+
+@@ -1597,9 +1575,7 @@ static void ath9k_bss_info_changed(struc
+ (changed & BSS_CHANGED_BEACON_ENABLED) ||
+ (changed & BSS_CHANGED_BEACON_INT))) {
+ ath9k_set_beaconing_status(sc, false);
+- if (bss_conf->enable_beacon)
+- ath_beacon_alloc(sc, vif);
+- else
++ if (!bss_conf->enable_beacon)
+ avp->is_bslot_active = false;
+ ath_beacon_config(sc, vif);
+ ath9k_set_beaconing_status(sc, true);
diff --git a/linux-next-cherry-picks/0144-ath9k_hw-Cleanup-ath9k_hw_set_tsfadjust.patch b/linux-next-cherry-picks/0144-ath9k_hw-Cleanup-ath9k_hw_set_tsfadjust.patch
new file mode 100644
index 0000000..5d0aa16
--- /dev/null
+++ b/linux-next-cherry-picks/0144-ath9k_hw-Cleanup-ath9k_hw_set_tsfadjust.patch
@@ -0,0 +1,90 @@
+From 60ca9f8744d29b8fdfd33d3dec8fc2cfc9ec381a Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:15:37 +0530
+Subject: [PATCH] ath9k_hw: Cleanup ath9k_hw_set_tsfadjust
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
+ drivers/net/wireless/ath/ath9k/hw.c | 4 ++--
+ drivers/net/wireless/ath/ath9k/hw.h | 2 +-
+ drivers/net/wireless/ath/ath9k/main.c | 10 ++--------
+ 4 files changed, 6 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+@@ -1106,7 +1106,7 @@ static int ath9k_htc_add_interface(struc
+
+ if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
+ !(priv->op_flags & OP_ANI_RUNNING)) {
+- ath9k_hw_set_tsfadjust(priv->ah, 1);
++ ath9k_hw_set_tsfadjust(priv->ah, true);
+ ath9k_htc_start_ani(priv);
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2891,9 +2891,9 @@ void ath9k_hw_reset_tsf(struct ath_hw *a
+ }
+ EXPORT_SYMBOL(ath9k_hw_reset_tsf);
+
+-void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
++void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set)
+ {
+- if (setting)
++ if (set)
+ ah->misc_mode |= AR_PCU_TX_ADD_TSF;
+ else
+ ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -941,7 +941,7 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah)
+ u64 ath9k_hw_gettsf64(struct ath_hw *ah);
+ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
+ void ath9k_hw_reset_tsf(struct ath_hw *ah);
+-void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
++void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set);
+ void ath9k_hw_init_global_settings(struct ath_hw *ah);
+ u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
+ void ath9k_hw_set11nmac2040(struct ath_hw *ah);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -907,17 +907,15 @@ static void ath9k_calculate_summary_stat
+
+ ath9k_calculate_iter_data(hw, vif, &iter_data);
+
+- /* Set BSSID mask. */
+ memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+ ath_hw_setbssidmask(common);
+
+- /* Set op-mode & TSF */
+ if (iter_data.naps > 0) {
+- ath9k_hw_set_tsfadjust(ah, 1);
++ ath9k_hw_set_tsfadjust(ah, true);
+ set_bit(SC_OP_TSF_RESET, &sc->sc_flags);
+ ah->opmode = NL80211_IFTYPE_AP;
+ } else {
+- ath9k_hw_set_tsfadjust(ah, 0);
++ ath9k_hw_set_tsfadjust(ah, false);
+ clear_bit(SC_OP_TSF_RESET, &sc->sc_flags);
+
+ if (iter_data.nmeshes)
+@@ -930,9 +928,6 @@ static void ath9k_calculate_summary_stat
+ ah->opmode = NL80211_IFTYPE_STATION;
+ }
+
+- /*
+- * Enable MIB interrupts when there are hardware phy counters.
+- */
+ if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
+ ah->imask |= ATH9K_INT_TSFOOR;
+ else
+@@ -940,7 +935,6 @@ static void ath9k_calculate_summary_stat
+
+ ath9k_hw_set_interrupts(ah);
+
+- /* Set up ANI */
+ if (iter_data.naps > 0) {
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+
diff --git a/linux-next-cherry-picks/0145-ath9k-Cleanup-interface-handling.patch b/linux-next-cherry-picks/0145-ath9k-Cleanup-interface-handling.patch
new file mode 100644
index 0000000..7d60233
--- /dev/null
+++ b/linux-next-cherry-picks/0145-ath9k-Cleanup-interface-handling.patch
@@ -0,0 +1,62 @@
+From df35d29e171ef043976b339812276ff96d1f4c21 Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:15:43 +0530
+Subject: [PATCH] ath9k: Cleanup interface handling
+
+* Do not set/clear TSF when adding/deleting an interface.
+ This should be done when the BSS is set up and should also
+ take into account the existence of other interfaces.
+
+* Set opmode explicitly.
+
+* ANI setup needs to be decided based on multiple interfaces.
+ This can be done via the bss_info_changed() callback.
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/main.c | 17 ++---------------
+ 1 file changed, 2 insertions(+), 15 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -912,11 +912,9 @@ static void ath9k_calculate_summary_stat
+
+ if (iter_data.naps > 0) {
+ ath9k_hw_set_tsfadjust(ah, true);
+- set_bit(SC_OP_TSF_RESET, &sc->sc_flags);
+ ah->opmode = NL80211_IFTYPE_AP;
+ } else {
+ ath9k_hw_set_tsfadjust(ah, false);
+- clear_bit(SC_OP_TSF_RESET, &sc->sc_flags);
+
+ if (iter_data.nmeshes)
+ ah->opmode = NL80211_IFTYPE_MESH_POINT;
+@@ -928,25 +926,14 @@ static void ath9k_calculate_summary_stat
+ ah->opmode = NL80211_IFTYPE_STATION;
+ }
+
++ ath9k_hw_setopmode(ah);
++
+ if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
+ ah->imask |= ATH9K_INT_TSFOOR;
+ else
+ ah->imask &= ~ATH9K_INT_TSFOOR;
+
+ ath9k_hw_set_interrupts(ah);
+-
+- if (iter_data.naps > 0) {
+- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+-
+- if (!common->disable_ani) {
+- set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+- ath_start_ani(common);
+- }
+-
+- } else {
+- clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+- del_timer_sync(&common->ani.timer);
+- }
+ }
+
+ static int ath9k_add_interface(struct ieee80211_hw *hw,
diff --git a/linux-next-cherry-picks/0146-ath9k-Simplify-ASSOC-handling.patch b/linux-next-cherry-picks/0146-ath9k-Simplify-ASSOC-handling.patch
new file mode 100644
index 0000000..c097e7f
--- /dev/null
+++ b/linux-next-cherry-picks/0146-ath9k-Simplify-ASSOC-handling.patch
@@ -0,0 +1,197 @@
+From 6c43c090a92938c3e89ce3b7459f91c5159535e2 Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:15:50 +0530
+Subject: [PATCH] ath9k: Simplify ASSOC handling
+
+Cleanup the messy logic dealing with station association
+and disassociation.
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/beacon.c | 2 +-
+ drivers/net/wireless/ath/ath9k/main.c | 118 +++++++++++++-------------------
+ 2 files changed, 49 insertions(+), 71 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -472,7 +472,7 @@ static void ath_beacon_config_sta(struct
+ int num_beacons, offset, dtim_dec_count, cfp_dec_count;
+
+ /* No need to configure beacon if we are not associated */
+- if (!common->curaid) {
++ if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
+ ath_dbg(common, BEACON,
+ "STA is not yet associated..skipping beacon config\n");
+ return;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1418,86 +1418,53 @@ static int ath9k_set_key(struct ieee8021
+
+ return ret;
+ }
+-static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
++
++static void ath9k_set_assoc_state(struct ath_softc *sc,
++ struct ieee80211_vif *vif)
+ {
+- struct ath_softc *sc = data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct ath_vif *avp = (void *)vif->drv_priv;
++ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ unsigned long flags;
++
++ set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
++ avp->primary_sta_vif = true;
++
+ /*
+- * Skip iteration if primary station vif's bss info
+- * was not changed
++ * Set the AID, BSSID and do beacon-sync only when
++ * the HW opmode is STATION.
++ *
++ * But the primary bit is set above in any case.
+ */
+- if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
++ if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+ return;
+
+- if (bss_conf->assoc) {
+- set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
+- avp->primary_sta_vif = true;
+- memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+- common->curaid = bss_conf->aid;
+- ath9k_hw_write_associd(sc->sc_ah);
+- ath_dbg(common, CONFIG, "Bss Info ASSOC %d, bssid: %pM\n",
+- bss_conf->aid, common->curbssid);
+- ath_beacon_config(sc, vif);
+- /*
+- * Request a re-configuration of Beacon related timers
+- * on the receipt of the first Beacon frame (i.e.,
+- * after time sync with the AP).
+- */
+- spin_lock_irqsave(&sc->sc_pm_lock, flags);
+- sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+- spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+-
+- /* Reset rssi stats */
+- sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
+- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+-
+- ath_start_rx_poll(sc, 3);
+-
+- if (!common->disable_ani) {
+- set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+- ath_start_ani(common);
+- }
+-
+- }
++ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
++ common->curaid = bss_conf->aid;
++ ath9k_hw_write_associd(sc->sc_ah);
++
++ sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
++ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
++
++ spin_lock_irqsave(&sc->sc_pm_lock, flags);
++ sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
++
++ ath_dbg(common, CONFIG,
++ "Primary Station interface: %pM, BSSID: %pM\n",
++ vif->addr, common->curbssid);
+ }
+
+-static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
++static void ath9k_bss_assoc_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+ {
+- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ struct ath_softc *sc = data;
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+- struct ath_vif *avp = (void *)vif->drv_priv;
+
+- if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
++ if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
+ return;
+
+- /* Reconfigure bss info */
+- if (avp->primary_sta_vif && !bss_conf->assoc) {
+- ath_dbg(common, CONFIG, "Bss Info DISASSOC %d, bssid %pM\n",
+- common->curaid, common->curbssid);
+- clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
+- clear_bit(SC_OP_BEACONS, &sc->sc_flags);
+- avp->primary_sta_vif = false;
+- memset(common->curbssid, 0, ETH_ALEN);
+- common->curaid = 0;
+- }
+-
+- ieee80211_iterate_active_interfaces_atomic(
+- sc->hw, ath9k_bss_iter, sc);
+-
+- /*
+- * None of station vifs are associated.
+- * Clear bssid & aid
+- */
+- if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
+- ath9k_hw_write_associd(sc->sc_ah);
+- clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+- del_timer_sync(&common->ani.timer);
+- del_timer_sync(&sc->rx_poll_timer);
+- memset(&sc->caldata, 0, sizeof(sc->caldata));
+- }
++ if (bss_conf->assoc)
++ ath9k_set_assoc_state(sc, vif);
+ }
+
+ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
+@@ -1515,30 +1482,41 @@ static void ath9k_bss_info_changed(struc
+ mutex_lock(&sc->mutex);
+
+ if (changed & BSS_CHANGED_ASSOC) {
+- ath9k_config_bss(sc, vif);
++ ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
++ bss_conf->bssid, bss_conf->assoc);
++
++ if (avp->primary_sta_vif && !bss_conf->assoc) {
++ clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
++ avp->primary_sta_vif = false;
++
++ if (ah->opmode == NL80211_IFTYPE_STATION)
++ clear_bit(SC_OP_BEACONS, &sc->sc_flags);
++ }
+
+- ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",
+- common->curbssid, common->curaid);
++ ieee80211_iterate_active_interfaces_atomic(sc->hw,
++ ath9k_bss_assoc_iter, sc);
++
++ if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags) &&
++ ah->opmode == NL80211_IFTYPE_STATION) {
++ memset(common->curbssid, 0, ETH_ALEN);
++ common->curaid = 0;
++ ath9k_hw_write_associd(sc->sc_ah);
++ }
+ }
+
+ if (changed & BSS_CHANGED_IBSS) {
+- /* There can be only one vif available */
+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+ common->curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc->sc_ah);
+
+ if (bss_conf->ibss_joined) {
+- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+-
+ if (!common->disable_ani) {
+ set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+ ath_start_ani(common);
+ }
+-
+ } else {
+ clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+ del_timer_sync(&common->ani.timer);
+- del_timer_sync(&sc->rx_poll_timer);
+ }
+ }
+
diff --git a/linux-next-cherry-picks/0147-ath9k-Cleanup-beacon-logic.patch b/linux-next-cherry-picks/0147-ath9k-Cleanup-beacon-logic.patch
new file mode 100644
index 0000000..762a380
--- /dev/null
+++ b/linux-next-cherry-picks/0147-ath9k-Cleanup-beacon-logic.patch
@@ -0,0 +1,448 @@
+From ef4ad63368e6162fb0b18861748fac49edfcbd03 Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:15:56 +0530
+Subject: [PATCH] ath9k: Cleanup beacon logic
+
+* The beaconing status routine is not required, since in
+ multi-VIF cases the HW beacon parameters should not be
+ re-configured.
+
+* Remove SC_OP_TSF_RESET - when a beaconing interface comes
+ up the first time, the TSF has to be reset.
+
+* Simplify ath9k_allow_beacon_config().
+
+* Handle setting/clearing the SWBA interrupt properly.
+
+* Remove the TSF mangling in IBSS mode, it is not required.
+
+* General code cleanup.
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 8 +-
+ drivers/net/wireless/ath/ath9k/beacon.c | 226 ++++++++++++--------------------
+ drivers/net/wireless/ath/ath9k/main.c | 24 +---
+ drivers/net/wireless/ath/ath9k/recv.c | 2 +-
+ 4 files changed, 98 insertions(+), 162 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -386,6 +386,7 @@ struct ath_beacon_config {
+ u16 dtim_period;
+ u16 bmiss_timeout;
+ u8 dtim_count;
++ bool enable_beacon;
+ };
+
+ struct ath_beacon {
+@@ -412,11 +413,13 @@ struct ath_beacon {
+ };
+
+ void ath_beacon_tasklet(unsigned long data);
+-void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
++bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
++void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
++ u32 changed);
+ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+ int ath_beaconq_config(struct ath_softc *sc);
+-void ath_set_beacon(struct ath_softc *sc);
++void ath9k_set_beacon(struct ath_softc *sc);
+ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
+
+ /*******************/
+@@ -613,7 +616,6 @@ enum sc_op_flags {
+ SC_OP_INVALID,
+ SC_OP_BEACONS,
+ SC_OP_RXFLUSH,
+- SC_OP_TSF_RESET,
+ SC_OP_ANI_RUN,
+ SC_OP_PRIM_STA_VIF,
+ SC_OP_HW_RESET,
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -315,7 +315,6 @@ void ath_beacon_tasklet(unsigned long da
+ } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
+ ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
+ sc->beacon.bmisscnt = 0;
+- set_bit(SC_OP_TSF_RESET, &sc->sc_flags);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+ }
+
+@@ -401,21 +400,16 @@ void ath_beacon_tasklet(unsigned long da
+ }
+ }
+
+-static void ath9k_beacon_init(struct ath_softc *sc,
+- u32 next_beacon,
+- u32 beacon_period)
++static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, u32 intval)
+ {
+- if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) {
+- ath9k_ps_wakeup(sc);
+- ath9k_hw_reset_tsf(sc->sc_ah);
+- }
+-
+- ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period);
++ struct ath_hw *ah = sc->sc_ah;
+
+- if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) {
+- ath9k_ps_restore(sc);
+- clear_bit(SC_OP_TSF_RESET, &sc->sc_flags);
+- }
++ ath9k_hw_disable_interrupts(ah);
++ ath9k_hw_reset_tsf(ah);
++ ath9k_hw_beaconinit(ah, nexttbtt, intval);
++ sc->beacon.bmisscnt = 0;
++ ath9k_hw_set_interrupts(ah);
++ ath9k_hw_enable_interrupts(ah);
+ }
+
+ /*
+@@ -423,32 +417,28 @@ static void ath9k_beacon_init(struct ath
+ * burst together. For the former arrange for the SWBA to be delivered for each
+ * slot. Slots that are not occupied will generate nothing.
+ */
+-static void ath_beacon_config_ap(struct ath_softc *sc,
+- struct ath_beacon_config *conf)
++static void ath9k_beacon_config_ap(struct ath_softc *sc,
++ struct ath_beacon_config *conf)
+ {
+ struct ath_hw *ah = sc->sc_ah;
++ struct ath_common *common = ath9k_hw_common(ah);
+ u32 nexttbtt, intval;
+
+ /* NB: the beacon interval is kept internally in TU's */
+ intval = TU_TO_USEC(conf->beacon_interval);
+- intval /= ATH_BCBUF; /* for staggered beacons */
++ intval /= ATH_BCBUF;
+ nexttbtt = intval;
+
+- /*
+- * In AP mode we enable the beacon timers and SWBA interrupts to
+- * prepare beacon frames.
+- */
+- ah->imask |= ATH9K_INT_SWBA;
+- ath_beaconq_config(sc);
++ if (conf->enable_beacon)
++ ah->imask |= ATH9K_INT_SWBA;
++ else
++ ah->imask &= ~ATH9K_INT_SWBA;
+
+- /* Set the computed AP beacon timers */
++ ath_dbg(common, BEACON, "AP nexttbtt: %u intval: %u conf_intval: %u\n",
++ nexttbtt, intval, conf->beacon_interval);
+
+- ath9k_hw_disable_interrupts(ah);
+- set_bit(SC_OP_TSF_RESET, &sc->sc_flags);
++ ath_beaconq_config(sc);
+ ath9k_beacon_init(sc, nexttbtt, intval);
+- sc->beacon.bmisscnt = 0;
+- ath9k_hw_set_interrupts(ah);
+- ath9k_hw_enable_interrupts(ah);
+ }
+
+ /*
+@@ -459,8 +449,8 @@ static void ath_beacon_config_ap(struct
+ * we'll receive a BMISS interrupt when we stop seeing beacons from the AP
+ * we've associated with.
+ */
+-static void ath_beacon_config_sta(struct ath_softc *sc,
+- struct ath_beacon_config *conf)
++static void ath9k_beacon_config_sta(struct ath_softc *sc,
++ struct ath_beacon_config *conf)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -579,97 +569,66 @@ static void ath_beacon_config_sta(struct
+ ath9k_hw_enable_interrupts(ah);
+ }
+
+-static void ath_beacon_config_adhoc(struct ath_softc *sc,
+- struct ath_beacon_config *conf)
++static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
++ struct ath_beacon_config *conf)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+- u32 tsf, intval, nexttbtt;
++ u32 intval, nexttbtt;
+
+ ath9k_reset_beacon_status(sc);
+- if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))
+- ath9k_hw_settsf64(ah, sc->beacon.bc_tstamp);
+
+ intval = TU_TO_USEC(conf->beacon_interval);
+- tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval);
+- nexttbtt = tsf + intval;
++ nexttbtt = intval;
+
+- ath_dbg(common, BEACON, "IBSS nexttbtt %u intval %u (%u)\n",
+- nexttbtt, intval, conf->beacon_interval);
++ if (conf->enable_beacon)
++ ah->imask |= ATH9K_INT_SWBA;
++ else
++ ah->imask &= ~ATH9K_INT_SWBA;
+
+- /*
+- * In IBSS mode enable the beacon timers but only enable SWBA interrupts
+- * if we need to manually prepare beacon frames. Otherwise we use a
+- * self-linked tx descriptor and let the hardware deal with things.
+- */
+- ah->imask |= ATH9K_INT_SWBA;
++ ath_dbg(common, BEACON, "IBSS nexttbtt: %u intval: %u conf_intval: %u\n",
++ nexttbtt, intval, conf->beacon_interval);
+
+ ath_beaconq_config(sc);
+-
+- /* Set the computed ADHOC beacon timers */
+-
+- ath9k_hw_disable_interrupts(ah);
+ ath9k_beacon_init(sc, nexttbtt, intval);
+- sc->beacon.bmisscnt = 0;
+-
+- ath9k_hw_set_interrupts(ah);
+- ath9k_hw_enable_interrupts(ah);
+ }
+
+-static bool ath9k_allow_beacon_config(struct ath_softc *sc,
+- struct ieee80211_vif *vif)
++bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
+ {
+- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ struct ath_vif *avp = (void *)vif->drv_priv;
+
+- /*
+- * Can not have different beacon interval on multiple
+- * AP interface case
+- */
+- if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
+- (sc->nbcnvifs > 1) &&
+- (vif->type == NL80211_IFTYPE_AP) &&
+- (cur_conf->beacon_interval != bss_conf->beacon_int)) {
+- ath_dbg(common, CONFIG,
+- "Changing beacon interval of multiple AP interfaces !\n");
+- return false;
+- }
+- /*
+- * Can not configure station vif's beacon config
+- * while on AP opmode
+- */
+- if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
+- (vif->type != NL80211_IFTYPE_AP)) {
+- ath_dbg(common, CONFIG,
+- "STA vif's beacon not allowed on AP mode\n");
+- return false;
++ if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
++ if ((vif->type != NL80211_IFTYPE_AP) ||
++ (sc->nbcnvifs > 1)) {
++ ath_dbg(common, CONFIG,
++ "An AP interface is already present !\n");
++ return false;
++ }
+ }
+- /*
+- * Do not allow beacon config if HW was already configured
+- * with another STA vif
+- */
+- if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
+- (vif->type == NL80211_IFTYPE_STATION) &&
+- test_bit(SC_OP_BEACONS, &sc->sc_flags) &&
+- !avp->primary_sta_vif) {
+- ath_dbg(common, CONFIG,
+- "Beacon already configured for a station interface\n");
+- return false;
++
++ if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
++ if ((vif->type == NL80211_IFTYPE_STATION) &&
++ test_bit(SC_OP_BEACONS, &sc->sc_flags) &&
++ !avp->primary_sta_vif) {
++ ath_dbg(common, CONFIG,
++ "Beacon already configured for a station interface\n");
++ return false;
++ }
+ }
++
+ return true;
+ }
+
+-void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
++static void ath9k_cache_beacon_config(struct ath_softc *sc,
++ struct ieee80211_bss_conf *bss_conf)
+ {
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+- if (!ath9k_allow_beacon_config(sc, vif))
+- return;
++ ath_dbg(common, BEACON,
++ "Caching beacon data for BSS: %pM\n", bss_conf->bssid);
+
+- /* Setup the beacon configuration parameters */
+ cur_conf->beacon_interval = bss_conf->beacon_int;
+ cur_conf->dtim_period = bss_conf->dtim_period;
+ cur_conf->listen_interval = 1;
+@@ -694,73 +653,62 @@ void ath_beacon_config(struct ath_softc
+ if (cur_conf->dtim_period == 0)
+ cur_conf->dtim_period = 1;
+
+- ath_set_beacon(sc);
+ }
+
+-static bool ath_has_valid_bslot(struct ath_softc *sc)
++void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
++ u32 changed)
+ {
+- struct ath_vif *avp;
+- int slot;
+- bool found = false;
+-
+- for (slot = 0; slot < ATH_BCBUF; slot++) {
+- if (sc->beacon.bslot[slot]) {
+- avp = (void *)sc->beacon.bslot[slot]->drv_priv;
+- if (avp->is_bslot_active) {
+- found = true;
+- break;
++ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
++ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
++
++ if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
++ ath9k_cache_beacon_config(sc, bss_conf);
++ ath9k_set_beacon(sc);
++ set_bit(SC_OP_BEACONS, &sc->sc_flags);
++ } else {
++ /*
++ * Take care of multiple interfaces when
++ * enabling/disabling SWBA.
++ */
++ if (changed & BSS_CHANGED_BEACON_ENABLED) {
++ if (!bss_conf->enable_beacon &&
++ (sc->nbcnvifs <= 1)) {
++ cur_conf->enable_beacon = false;
++ } else if (bss_conf->enable_beacon) {
++ cur_conf->enable_beacon = true;
++ ath9k_cache_beacon_config(sc, bss_conf);
+ }
+ }
++
++ if (cur_conf->beacon_interval) {
++ ath9k_set_beacon(sc);
++
++ if (cur_conf->enable_beacon)
++ set_bit(SC_OP_BEACONS, &sc->sc_flags);
++ else
++ clear_bit(SC_OP_BEACONS, &sc->sc_flags);
++ }
+ }
+- return found;
+ }
+
+-
+-void ath_set_beacon(struct ath_softc *sc)
++void ath9k_set_beacon(struct ath_softc *sc)
+ {
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+
+ switch (sc->sc_ah->opmode) {
+ case NL80211_IFTYPE_AP:
+- if (ath_has_valid_bslot(sc))
+- ath_beacon_config_ap(sc, cur_conf);
++ ath9k_beacon_config_ap(sc, cur_conf);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+- ath_beacon_config_adhoc(sc, cur_conf);
++ ath9k_beacon_config_adhoc(sc, cur_conf);
+ break;
+ case NL80211_IFTYPE_STATION:
+- ath_beacon_config_sta(sc, cur_conf);
++ ath9k_beacon_config_sta(sc, cur_conf);
+ break;
+ default:
+ ath_dbg(common, CONFIG, "Unsupported beaconing mode\n");
+ return;
+ }
+-
+- set_bit(SC_OP_BEACONS, &sc->sc_flags);
+-}
+-
+-void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
+-{
+- struct ath_hw *ah = sc->sc_ah;
+-
+- if (!ath_has_valid_bslot(sc)) {
+- clear_bit(SC_OP_BEACONS, &sc->sc_flags);
+- return;
+- }
+-
+- ath9k_ps_wakeup(sc);
+- if (status) {
+- /* Re-enable beaconing */
+- ah->imask |= ATH9K_INT_SWBA;
+- ath9k_hw_set_interrupts(ah);
+- } else {
+- /* Disable SWBA interrupt */
+- ah->imask &= ~ATH9K_INT_SWBA;
+- ath9k_hw_set_interrupts(ah);
+- tasklet_kill(&sc->bcon_tasklet);
+- ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
+- }
+- ath9k_ps_restore(sc);
+ }
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -235,7 +235,7 @@ static bool ath_complete_reset(struct at
+ if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))
+ goto work;
+
+- ath_set_beacon(sc);
++ ath9k_set_beacon(sc);
+
+ if (ah->opmode == NL80211_IFTYPE_STATION &&
+ test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
+@@ -1520,24 +1520,10 @@ static void ath9k_bss_info_changed(struc
+ }
+ }
+
+- /*
+- * In case of AP mode, the HW TSF has to be reset
+- * when the beacon interval changes.
+- */
+- if ((changed & BSS_CHANGED_BEACON_INT) &&
+- (vif->type == NL80211_IFTYPE_AP))
+- set_bit(SC_OP_TSF_RESET, &sc->sc_flags);
+-
+- /* Configure beaconing (AP, IBSS, MESH) */
+- if (ath9k_uses_beacons(vif->type) &&
+- ((changed & BSS_CHANGED_BEACON) ||
+- (changed & BSS_CHANGED_BEACON_ENABLED) ||
+- (changed & BSS_CHANGED_BEACON_INT))) {
+- ath9k_set_beaconing_status(sc, false);
+- if (!bss_conf->enable_beacon)
+- avp->is_bslot_active = false;
+- ath_beacon_config(sc, vif);
+- ath9k_set_beaconing_status(sc, true);
++ if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
++ (changed & BSS_CHANGED_BEACON_INT)) {
++ if (ath9k_allow_beacon_config(sc, vif))
++ ath9k_beacon_config(sc, vif, changed);
+ }
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -550,7 +550,7 @@ static void ath_rx_ps_beacon(struct ath_
+ sc->ps_flags &= ~PS_BEACON_SYNC;
+ ath_dbg(common, PS,
+ "Reconfigure Beacon timers based on timestamp from the AP\n");
+- ath_set_beacon(sc);
++ ath9k_set_beacon(sc);
+ }
+
+ if (ath_beacon_dtim_pending_cab(skb)) {
diff --git a/linux-next-cherry-picks/0148-ath9k-Remove-is_bslot_active.patch b/linux-next-cherry-picks/0148-ath9k-Remove-is_bslot_active.patch
new file mode 100644
index 0000000..5e70d09
--- /dev/null
+++ b/linux-next-cherry-picks/0148-ath9k-Remove-is_bslot_active.patch
@@ -0,0 +1,88 @@
+From aa45fe9683ba861bf49d51479b11b3d482b57416 Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:16:03 +0530
+Subject: [PATCH] ath9k: Remove is_bslot_active
+
+In the tx_last_beacon() callback, mac80211's beaconing
+status can be used instead. The beacon tasklet doesn't require
+it because it is disabled when removing a slot.
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 2 +-
+ drivers/net/wireless/ath/ath9k/beacon.c | 15 +++++----------
+ drivers/net/wireless/ath/ath9k/main.c | 5 +++--
+ 3 files changed, 9 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -360,7 +360,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
+
+ struct ath_vif {
+ int av_bslot;
+- bool is_bslot_active, primary_sta_vif;
++ bool primary_sta_vif;
+ __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
+ struct ath_buf *av_bcbuf;
+ };
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -134,20 +134,17 @@ static struct ath_buf *ath_beacon_genera
+ struct ath_softc *sc = hw->priv;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_buf *bf;
+- struct ath_vif *avp;
++ struct ath_vif *avp = (void *)vif->drv_priv;
+ struct sk_buff *skb;
+- struct ath_txq *cabq;
++ struct ath_txq *cabq = sc->beacon.cabq;
+ struct ieee80211_tx_info *info;
+ int cabq_depth;
+
+- ath9k_reset_beacon_status(sc);
+-
+- avp = (void *)vif->drv_priv;
+- cabq = sc->beacon.cabq;
+-
+- if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active)
++ if (avp->av_bcbuf == NULL)
+ return NULL;
+
++ ath9k_reset_beacon_status(sc);
++
+ /* Release the old beacon first */
+
+ bf = avp->av_bcbuf;
+@@ -234,7 +231,6 @@ void ath9k_beacon_assign_slot(struct ath
+ for (slot = 0; slot < ATH_BCBUF; slot++) {
+ if (sc->beacon.bslot[slot] == NULL) {
+ avp->av_bslot = slot;
+- avp->is_bslot_active = false;
+ break;
+ }
+ }
+@@ -267,7 +263,6 @@ void ath9k_beacon_remove_slot(struct ath
+ }
+
+ avp->av_bcbuf = NULL;
+- avp->is_bslot_active = false;
+ sc->beacon.bslot[avp->av_bslot] = NULL;
+ sc->nbcnvifs--;
+ list_add_tail(&bf->list, &sc->beacon.bbuf);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1775,10 +1775,11 @@ static int ath9k_tx_last_beacon(struct i
+ if (!vif)
+ return 0;
+
+- avp = (void *)vif->drv_priv;
+- if (!avp->is_bslot_active)
++ if (!vif->bss_conf.enable_beacon)
+ return 0;
+
++ avp = (void *)vif->drv_priv;
++
+ if (!sc->beacon.tx_processed && !edma) {
+ tasklet_disable(&sc->bcon_tasklet);
+
diff --git a/linux-next-cherry-picks/0149-ath9k-Cleanup-beacon-queue-configuration.patch b/linux-next-cherry-picks/0149-ath9k-Cleanup-beacon-queue-configuration.patch
new file mode 100644
index 0000000..59977be
--- /dev/null
+++ b/linux-next-cherry-picks/0149-ath9k-Cleanup-beacon-queue-configuration.patch
@@ -0,0 +1,119 @@
+From 7e52c8aa35c987236a80b7063c418a3d29b51052 Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:16:09 +0530
+Subject: [PATCH] ath9k: Cleanup beacon queue configuration
+
+Setup the beacon queue parameters after disabling
+interrupts. Also, remove the redundant call in conf_tx()
+for IBSS mode since the queue would be configured
+with the appropriate cwmin/cwmax values when beaconing
+is enabled.
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 1 -
+ drivers/net/wireless/ath/ath9k/beacon.c | 11 ++++-------
+ drivers/net/wireless/ath/ath9k/main.c | 4 ----
+ drivers/net/wireless/ath/ath9k/xmit.c | 10 ----------
+ 4 files changed, 4 insertions(+), 22 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -418,7 +418,6 @@ void ath9k_beacon_config(struct ath_soft
+ u32 changed);
+ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+-int ath_beaconq_config(struct ath_softc *sc);
+ void ath9k_set_beacon(struct ath_softc *sc);
+ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
+
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -30,7 +30,7 @@ static void ath9k_reset_beacon_status(st
+ * the operating mode of the station (AP or AdHoc). Parameters are AIFS
+ * settings and channel width min/max
+ */
+-int ath_beaconq_config(struct ath_softc *sc)
++static void ath9k_beaconq_config(struct ath_softc *sc)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -38,6 +38,7 @@ int ath_beaconq_config(struct ath_softc
+ struct ath_txq *txq;
+
+ ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
++
+ if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
+ /* Always burst out beacon and CAB traffic. */
+ qi.tqi_aifs = 1;
+@@ -56,12 +57,9 @@ int ath_beaconq_config(struct ath_softc
+ }
+
+ if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
+- ath_err(common,
+- "Unable to update h/w beacon queue parameters\n");
+- return 0;
++ ath_err(common, "Unable to update h/w beacon queue parameters\n");
+ } else {
+ ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
+- return 1;
+ }
+ }
+
+@@ -401,6 +399,7 @@ static void ath9k_beacon_init(struct ath
+
+ ath9k_hw_disable_interrupts(ah);
+ ath9k_hw_reset_tsf(ah);
++ ath9k_beaconq_config(sc);
+ ath9k_hw_beaconinit(ah, nexttbtt, intval);
+ sc->beacon.bmisscnt = 0;
+ ath9k_hw_set_interrupts(ah);
+@@ -432,7 +431,6 @@ static void ath9k_beacon_config_ap(struc
+ ath_dbg(common, BEACON, "AP nexttbtt: %u intval: %u conf_intval: %u\n",
+ nexttbtt, intval, conf->beacon_interval);
+
+- ath_beaconq_config(sc);
+ ath9k_beacon_init(sc, nexttbtt, intval);
+ }
+
+@@ -584,7 +582,6 @@ static void ath9k_beacon_config_adhoc(st
+ ath_dbg(common, BEACON, "IBSS nexttbtt: %u intval: %u conf_intval: %u\n",
+ nexttbtt, intval, conf->beacon_interval);
+
+- ath_beaconq_config(sc);
+ ath9k_beacon_init(sc, nexttbtt, intval);
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1346,10 +1346,6 @@ static int ath9k_conf_tx(struct ieee8021
+ if (ret)
+ ath_err(common, "TXQ Update failed\n");
+
+- if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
+- if (queue == WME_AC_BE && !ret)
+- ath_beaconq_config(sc);
+-
+ mutex_unlock(&sc->mutex);
+ ath9k_ps_restore(sc);
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1403,16 +1403,6 @@ int ath_txq_update(struct ath_softc *sc,
+ int error = 0;
+ struct ath9k_tx_queue_info qi;
+
+- if (qnum == sc->beacon.beaconq) {
+- /*
+- * XXX: for beacon queue, we just save the parameter.
+- * It will be picked up by ath_beaconq_config when
+- * it's necessary.
+- */
+- sc->beacon.beacon_qi = *qinfo;
+- return 0;
+- }
+-
+ BUG_ON(sc->tx.txq[qnum].axq_qnum != qnum);
+
+ ath9k_hw_get_txq_props(ah, qnum, &qi);
diff --git a/linux-next-cherry-picks/0150-ath9k-Set-the-TSF-adjust-value-properly.patch b/linux-next-cherry-picks/0150-ath9k-Set-the-TSF-adjust-value-properly.patch
new file mode 100644
index 0000000..8163d66
--- /dev/null
+++ b/linux-next-cherry-picks/0150-ath9k-Set-the-TSF-adjust-value-properly.patch
@@ -0,0 +1,61 @@
+From 2f8e82e8ab4629e648925c566cc26bdcf25f0aec Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:16:16 +0530
+Subject: [PATCH] ath9k: Set the TSF adjust value properly
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 1 +
+ drivers/net/wireless/ath/ath9k/beacon.c | 17 +++++++++++++++++
+ drivers/net/wireless/ath/ath9k/main.c | 3 +++
+ 3 files changed, 21 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -418,6 +418,7 @@ void ath9k_beacon_config(struct ath_soft
+ u32 changed);
+ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
++void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif);
+ void ath9k_set_beacon(struct ath_softc *sc);
+ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
+
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -268,6 +268,23 @@ void ath9k_beacon_remove_slot(struct ath
+ tasklet_enable(&sc->bcon_tasklet);
+ }
+
++void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
++{
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
++ struct ath_vif *avp = (void *)vif->drv_priv;
++ u64 tsfadjust;
++
++ if (avp->av_bslot == 0)
++ return;
++
++ tsfadjust = cur_conf->beacon_interval * avp->av_bslot / ATH_BCBUF;
++ avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
++
++ ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
++ (unsigned long long)tsfadjust, avp->av_bslot);
++}
++
+ void ath_beacon_tasklet(unsigned long data)
+ {
+ struct ath_softc *sc = (struct ath_softc *)data;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1518,6 +1518,9 @@ static void ath9k_bss_info_changed(struc
+
+ if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
+ (changed & BSS_CHANGED_BEACON_INT)) {
++ if (ah->opmode == NL80211_IFTYPE_AP &&
++ bss_conf->enable_beacon)
++ ath9k_set_tsfadjust(sc, vif);
+ if (ath9k_allow_beacon_config(sc, vif))
+ ath9k_beacon_config(sc, vif, changed);
+ }
diff --git a/linux-next-cherry-picks/0151-ath9k-Cleanup-the-beacon-tasklet.patch b/linux-next-cherry-picks/0151-ath9k-Cleanup-the-beacon-tasklet.patch
new file mode 100644
index 0000000..27cc216
--- /dev/null
+++ b/linux-next-cherry-picks/0151-ath9k-Cleanup-the-beacon-tasklet.patch
@@ -0,0 +1,281 @@
+From fb6e252f8d262d05da3ae023b4a6f83d0eec17d9 Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:16:22 +0530
+Subject: [PATCH] ath9k: Cleanup the beacon tasklet
+
+Remove unused variables, use a helper function to choose
+the slot and reset beaconing status at one place.
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 3 +-
+ drivers/net/wireless/ath/ath9k/beacon.c | 126 ++++++++++++++++----------------
+ drivers/net/wireless/ath/ath9k/init.c | 2 +-
+ 3 files changed, 63 insertions(+), 68 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -398,7 +398,6 @@ struct ath_beacon {
+
+ u32 beaconq;
+ u32 bmisscnt;
+- u32 ast_be_xmit;
+ u32 bc_tstamp;
+ struct ieee80211_vif *bslot[ATH_BCBUF];
+ int slottime;
+@@ -412,7 +411,7 @@ struct ath_beacon {
+ bool tx_last;
+ };
+
+-void ath_beacon_tasklet(unsigned long data);
++void ath9k_beacon_tasklet(unsigned long data);
+ bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
+ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
+ u32 changed);
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -68,7 +68,7 @@ static void ath9k_beaconq_config(struct
+ * up rate codes, and channel flags. Beacons are always sent out at the
+ * lowest rate, and are not retried.
+ */
+-static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
++static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
+ struct ath_buf *bf, int rateidx)
+ {
+ struct sk_buff *skb = bf->bf_mpdu;
+@@ -79,8 +79,6 @@ static void ath_beacon_setup(struct ath_
+ u8 chainmask = ah->txchainmask;
+ u8 rate = 0;
+
+- ath9k_reset_beacon_status(sc);
+-
+ sband = &sc->sbands[common->hw->conf.channel->band];
+ rate = sband->bitrates[rateidx].hw_value;
+ if (vif->bss_conf.use_short_preamble)
+@@ -109,7 +107,7 @@ static void ath_beacon_setup(struct ath_
+ ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
+ }
+
+-static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
++static void ath9k_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
+ {
+ struct ath_softc *sc = hw->priv;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+@@ -126,8 +124,8 @@ static void ath_tx_cabq(struct ieee80211
+ }
+ }
+
+-static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
+- struct ieee80211_vif *vif)
++static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
++ struct ieee80211_vif *vif)
+ {
+ struct ath_softc *sc = hw->priv;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+@@ -136,15 +134,12 @@ static struct ath_buf *ath_beacon_genera
+ struct sk_buff *skb;
+ struct ath_txq *cabq = sc->beacon.cabq;
+ struct ieee80211_tx_info *info;
++ struct ieee80211_mgmt *mgmt_hdr;
+ int cabq_depth;
+
+ if (avp->av_bcbuf == NULL)
+ return NULL;
+
+- ath9k_reset_beacon_status(sc);
+-
+- /* Release the old beacon first */
+-
+ bf = avp->av_bcbuf;
+ skb = bf->bf_mpdu;
+ if (skb) {
+@@ -154,14 +149,14 @@ static struct ath_buf *ath_beacon_genera
+ bf->bf_buf_addr = 0;
+ }
+
+- /* Get a new beacon from mac80211 */
+-
+ skb = ieee80211_beacon_get(hw, vif);
+- bf->bf_mpdu = skb;
+ if (skb == NULL)
+ return NULL;
+- ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
+- avp->tsf_adjust;
++
++ bf->bf_mpdu = skb;
++
++ mgmt_hdr = (struct ieee80211_mgmt *)skb->data;
++ mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust;
+
+ info = IEEE80211_SKB_CB(skb);
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+@@ -207,10 +202,10 @@ static struct ath_buf *ath_beacon_genera
+ }
+ }
+
+- ath_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
++ ath9k_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
+
+ while (skb) {
+- ath_tx_cabq(hw, skb);
++ ath9k_tx_cabq(hw, skb);
+ skb = ieee80211_get_buffered_bc(hw, vif);
+ }
+
+@@ -268,6 +263,33 @@ void ath9k_beacon_remove_slot(struct ath
+ tasklet_enable(&sc->bcon_tasklet);
+ }
+
++static int ath9k_beacon_choose_slot(struct ath_softc *sc)
++{
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
++ u16 intval;
++ u32 tsftu;
++ u64 tsf;
++ int slot;
++
++ if (sc->sc_ah->opmode != NL80211_IFTYPE_AP) {
++ ath_dbg(common, BEACON, "slot 0, tsf: %llu\n",
++ ath9k_hw_gettsf64(sc->sc_ah));
++ return 0;
++ }
++
++ intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
++ tsf = ath9k_hw_gettsf64(sc->sc_ah);
++ tsf += TU_TO_USEC(sc->sc_ah->config.sw_beacon_response_time);
++ tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
++ slot = (tsftu % (intval * ATH_BCBUF)) / intval;
++
++ ath_dbg(common, BEACON, "slot: %d tsf: %llu tsftu: %u\n",
++ slot, tsf, tsftu / ATH_BCBUF);
++
++ return slot;
++}
++
+ void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
+ {
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+@@ -285,17 +307,15 @@ void ath9k_set_tsfadjust(struct ath_soft
+ (unsigned long long)tsfadjust, avp->av_bslot);
+ }
+
+-void ath_beacon_tasklet(unsigned long data)
++void ath9k_beacon_tasklet(unsigned long data)
+ {
+ struct ath_softc *sc = (struct ath_softc *)data;
+- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_buf *bf = NULL;
+ struct ieee80211_vif *vif;
+ bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+ int slot;
+- u32 bfaddr, bc = 0;
+
+ if (work_pending(&sc->hw_reset_work)) {
+ ath_dbg(common, RESET,
+@@ -331,48 +351,19 @@ void ath_beacon_tasklet(unsigned long da
+ return;
+ }
+
+- /*
+- * Generate beacon frames. we are sending frames
+- * staggered so calculate the slot for this frame based
+- * on the tsf to safeguard against missing an swba.
+- */
+-
+-
+- if (ah->opmode == NL80211_IFTYPE_AP) {
+- u16 intval;
+- u32 tsftu;
+- u64 tsf;
+-
+- intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+- tsf = ath9k_hw_gettsf64(ah);
+- tsf += TU_TO_USEC(ah->config.sw_beacon_response_time);
+- tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
+- slot = (tsftu % (intval * ATH_BCBUF)) / intval;
+- vif = sc->beacon.bslot[slot];
+-
+- ath_dbg(common, BEACON,
+- "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
+- slot, tsf, tsftu / ATH_BCBUF, intval, vif);
+- } else {
+- slot = 0;
+- vif = sc->beacon.bslot[slot];
+- }
++ slot = ath9k_beacon_choose_slot(sc);
++ vif = sc->beacon.bslot[slot];
+
++ if (!vif || !vif->bss_conf.enable_beacon)
++ return;
+
+- bfaddr = 0;
+- if (vif) {
+- bf = ath_beacon_generate(sc->hw, vif);
+- if (bf != NULL) {
+- bfaddr = bf->bf_daddr;
+- bc = 1;
+- }
++ bf = ath9k_beacon_generate(sc->hw, vif);
++ WARN_ON(!bf);
+
+- if (sc->beacon.bmisscnt != 0) {
+- ath_dbg(common, BSTUCK,
+- "resume beacon xmit after %u misses\n",
+- sc->beacon.bmisscnt);
+- sc->beacon.bmisscnt = 0;
+- }
++ if (sc->beacon.bmisscnt != 0) {
++ ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n",
++ sc->beacon.bmisscnt);
++ sc->beacon.bmisscnt = 0;
+ }
+
+ /*
+@@ -392,21 +383,26 @@ void ath_beacon_tasklet(unsigned long da
+ * set to ATH_BCBUF so this check is a noop.
+ */
+ if (sc->beacon.updateslot == UPDATE) {
+- sc->beacon.updateslot = COMMIT; /* commit next beacon */
++ sc->beacon.updateslot = COMMIT;
+ sc->beacon.slotupdate = slot;
+- } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
++ } else if (sc->beacon.updateslot == COMMIT &&
++ sc->beacon.slotupdate == slot) {
+ ah->slottime = sc->beacon.slottime;
+ ath9k_hw_init_global_settings(ah);
+ sc->beacon.updateslot = OK;
+ }
+- if (bfaddr != 0) {
++
++ if (bf) {
++ ath9k_reset_beacon_status(sc);
++
++ ath_dbg(common, BEACON,
++ "Transmitting beacon for slot: %d\n", slot);
++
+ /* NB: cabq traffic should already be queued and primed */
+- ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
++ ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
+
+ if (!edma)
+ ath9k_hw_txstart(ah, sc->beacon.beaconq);
+-
+- sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
+ }
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -560,7 +560,7 @@ static int ath9k_init_softc(u16 devid, s
+ spin_lock_init(&sc->debug.samp_lock);
+ #endif
+ tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
+- tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
++ tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
+ (unsigned long)sc);
+
+ INIT_WORK(&sc->hw_reset_work, ath_reset_work);
diff --git a/linux-next-cherry-picks/0152-ath9k-Fix-ANI-management.patch b/linux-next-cherry-picks/0152-ath9k-Fix-ANI-management.patch
new file mode 100644
index 0000000..96b7757
--- /dev/null
+++ b/linux-next-cherry-picks/0152-ath9k-Fix-ANI-management.patch
@@ -0,0 +1,206 @@
+From da0d45f7b1dd08ab1ea4f542db797a0c51724281 Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:16:29 +0530
+Subject: [PATCH] ath9k: Fix ANI management
+
+Currently, there are problems with how ANI is handled in
+multi-VIF scenarios. This patch addresses them by unifying
+the start/stop logic.
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 4 ++-
+ drivers/net/wireless/ath/ath9k/debug.c | 5 ++-
+ drivers/net/wireless/ath/ath9k/link.c | 60 ++++++++++++++++++++++++++++++----
+ drivers/net/wireless/ath/ath9k/main.c | 29 +++++++---------
+ 4 files changed, 70 insertions(+), 28 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -444,7 +444,9 @@ void ath_rx_poll(unsigned long data);
+ void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon);
+ void ath_paprd_calibrate(struct work_struct *work);
+ void ath_ani_calibrate(unsigned long data);
+-void ath_start_ani(struct ath_common *common);
++void ath_start_ani(struct ath_softc *sc);
++void ath_stop_ani(struct ath_softc *sc);
++void ath_check_ani(struct ath_softc *sc);
+ int ath_update_survey_stats(struct ath_softc *sc);
+ void ath_update_survey_nf(struct ath_softc *sc, int channel);
+
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -206,10 +206,9 @@ static ssize_t write_file_disable_ani(st
+
+ if (disable_ani) {
+ clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+- del_timer_sync(&common->ani.timer);
++ ath_stop_ani(sc);
+ } else {
+- set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+- ath_start_ani(common);
++ ath_check_ani(sc);
+ }
+
+ return count;
+--- a/drivers/net/wireless/ath/ath9k/link.c
++++ b/drivers/net/wireless/ath/ath9k/link.c
+@@ -432,26 +432,72 @@ set_timer:
+ }
+ }
+
+-void ath_start_ani(struct ath_common *common)
++void ath_start_ani(struct ath_softc *sc)
+ {
+- struct ath_hw *ah = common->ah;
++ struct ath_hw *ah = sc->sc_ah;
++ struct ath_common *common = ath9k_hw_common(ah);
+ unsigned long timestamp = jiffies_to_msecs(jiffies);
+- struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+- if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags))
+- return;
+-
+- if (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
++ if (common->disable_ani ||
++ !test_bit(SC_OP_ANI_RUN, &sc->sc_flags) ||
++ (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+ return;
+
+ common->ani.longcal_timer = timestamp;
+ common->ani.shortcal_timer = timestamp;
+ common->ani.checkani_timer = timestamp;
+
++ ath_dbg(common, ANI, "Starting ANI\n");
+ mod_timer(&common->ani.timer,
+ jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval));
+ }
+
++void ath_stop_ani(struct ath_softc *sc)
++{
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++
++ ath_dbg(common, ANI, "Stopping ANI\n");
++ del_timer_sync(&common->ani.timer);
++}
++
++void ath_check_ani(struct ath_softc *sc)
++{
++ struct ath_hw *ah = sc->sc_ah;
++ struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
++
++ /*
++ * Check for the various conditions in which ANI has to
++ * be stopped.
++ */
++ if (ah->opmode == NL80211_IFTYPE_ADHOC) {
++ if (!cur_conf->enable_beacon)
++ goto stop_ani;
++ } else if (ah->opmode == NL80211_IFTYPE_AP) {
++ if (!cur_conf->enable_beacon) {
++ /*
++ * Disable ANI only when there are no
++ * associated stations.
++ */
++ if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
++ goto stop_ani;
++ }
++ } else if (ah->opmode == NL80211_IFTYPE_STATION) {
++ if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
++ goto stop_ani;
++ }
++
++ if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags)) {
++ set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
++ ath_start_ani(sc);
++ }
++
++ return;
++
++stop_ani:
++ clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
++ ath_stop_ani(sc);
++}
++
+ void ath_update_survey_nf(struct ath_softc *sc, int channel)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -167,8 +167,6 @@ static void ath_cancel_work(struct ath_s
+
+ static void ath_restart_work(struct ath_softc *sc)
+ {
+- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+-
+ ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+
+ if (AR_SREV_9485(sc->sc_ah) || AR_SREV_9340(sc->sc_ah))
+@@ -176,21 +174,18 @@ static void ath_restart_work(struct ath_
+ msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
+
+ ath_start_rx_poll(sc, 3);
+-
+- if (!common->disable_ani)
+- ath_start_ani(common);
++ ath_start_ani(sc);
+ }
+
+ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+- struct ath_common *common = ath9k_hw_common(ah);
+ bool ret = true;
+
+ ieee80211_stop_queues(sc->hw);
+
+ sc->hw_busy_count = 0;
+- del_timer_sync(&common->ani.timer);
++ ath_stop_ani(sc);
+ del_timer_sync(&sc->rx_poll_timer);
+
+ ath9k_debug_samp_bb_mac(sc);
+@@ -1468,6 +1463,11 @@ static void ath9k_bss_info_changed(struc
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changed)
+ {
++#define CHECK_ANI \
++ (BSS_CHANGED_ASSOC | \
++ BSS_CHANGED_IBSS | \
++ BSS_CHANGED_BEACON_ENABLED)
++
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1504,16 +1504,6 @@ static void ath9k_bss_info_changed(struc
+ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+ common->curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc->sc_ah);
+-
+- if (bss_conf->ibss_joined) {
+- if (!common->disable_ani) {
+- set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+- ath_start_ani(common);
+- }
+- } else {
+- clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
+- del_timer_sync(&common->ani.timer);
+- }
+ }
+
+ if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
+@@ -1544,8 +1534,13 @@ static void ath9k_bss_info_changed(struc
+ }
+ }
+
++ if (changed & CHECK_ANI)
++ ath_check_ani(sc);
++
+ mutex_unlock(&sc->mutex);
+ ath9k_ps_restore(sc);
++
++#undef CHECK_ANI
+ }
+
+ static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
diff --git a/linux-next-cherry-picks/0153-ath9k-Reconfigure-VIF-state-properly.patch b/linux-next-cherry-picks/0153-ath9k-Reconfigure-VIF-state-properly.patch
new file mode 100644
index 0000000..5809ea6
--- /dev/null
+++ b/linux-next-cherry-picks/0153-ath9k-Reconfigure-VIF-state-properly.patch
@@ -0,0 +1,73 @@
+From 6dcc344469d60a1f0d72cc638967e8c83c6e166e Mon Sep 17 00:00:00 2001
+From: Sujith Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:16:36 +0530
+Subject: [PATCH] ath9k: Reconfigure VIF state properly
+
+When an interface in AP or P2P-GO mode is removed,
+check whether a station interface is already present and
+reconfigure the beacon timers etc. properly if it's
+associated.
+
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/main.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -19,6 +19,9 @@
+ #include "ath9k.h"
+ #include "btcoex.h"
+
++static void ath9k_set_assoc_state(struct ath_softc *sc,
++ struct ieee80211_vif *vif);
++
+ u8 ath9k_parse_mpdudensity(u8 mpdudensity)
+ {
+ /*
+@@ -866,6 +869,18 @@ static void ath9k_vif_iter(void *data, u
+ }
+ }
+
++static void ath9k_sta_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
++{
++ struct ath_softc *sc = data;
++ struct ath_vif *avp = (void *)vif->drv_priv;
++
++ if (vif->type != NL80211_IFTYPE_STATION)
++ return;
++
++ if (avp->primary_sta_vif)
++ ath9k_set_assoc_state(sc, vif);
++}
++
+ /* Called with sc->mutex held. */
+ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+@@ -899,6 +914,7 @@ static void ath9k_calculate_summary_stat
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_vif_iter_data iter_data;
++ enum nl80211_iftype old_opmode = ah->opmode;
+
+ ath9k_calculate_iter_data(hw, vif, &iter_data);
+
+@@ -929,6 +945,17 @@ static void ath9k_calculate_summary_stat
+ ah->imask &= ~ATH9K_INT_TSFOOR;
+
+ ath9k_hw_set_interrupts(ah);
++
++ /*
++ * If we are changing the opmode to STATION,
++ * a beacon sync needs to be done.
++ */
++ if (ah->opmode == NL80211_IFTYPE_STATION &&
++ old_opmode == NL80211_IFTYPE_AP &&
++ test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
++ ieee80211_iterate_active_interfaces_atomic(sc->hw,
++ ath9k_sta_vif_iter, sc);
++ }
+ }
+
+ static int ath9k_add_interface(struct ieee80211_hw *hw,
diff --git a/linux-next-cherry-picks/0154-ath9k-Fix-race-in-reset-work-usage.patch b/linux-next-cherry-picks/0154-ath9k-Fix-race-in-reset-work-usage.patch
new file mode 100644
index 0000000..4a82e86
--- /dev/null
+++ b/linux-next-cherry-picks/0154-ath9k-Fix-race-in-reset-work-usage.patch
@@ -0,0 +1,256 @@
+From 124b979baeb2d7a0593be8d392f43725578478c1 Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <[email protected]>
+Date: Tue, 17 Jul 2012 17:16:42 +0530
+Subject: [PATCH] ath9k: Fix race in reset-work usage
+
+Using work_pending() to defer certain operations when
+a HW-reset work has been queued is racy since the check
+would return false when the work item is actually in
+execution. Use SC_OP_HW_RESET instead to fix this race.
+Also, unify the reset debug statistics maintenance.
+
+Signed-off-by: Rajkumar Manoharan <[email protected]>
+Signed-off-by: Sujith Manoharan <[email protected]>
+Signed-off-by: John W. Linville <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 1 +
+ drivers/net/wireless/ath/ath9k/beacon.c | 5 +++--
+ drivers/net/wireless/ath/ath9k/debug.h | 24 +++++++++++++-----------
+ drivers/net/wireless/ath/ath9k/link.c | 13 ++++++-------
+ drivers/net/wireless/ath/ath9k/main.c | 17 +++++++++++------
+ drivers/net/wireless/ath/ath9k/mci.c | 2 +-
+ drivers/net/wireless/ath/ath9k/xmit.c | 13 ++++++-------
+ 7 files changed, 41 insertions(+), 34 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -449,6 +449,7 @@ void ath_stop_ani(struct ath_softc *sc);
+ void ath_check_ani(struct ath_softc *sc);
+ int ath_update_survey_stats(struct ath_softc *sc);
+ void ath_update_survey_nf(struct ath_softc *sc, int channel);
++void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
+
+ /**********/
+ /* BTCOEX */
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -317,11 +317,12 @@ void ath9k_beacon_tasklet(unsigned long
+ bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+ int slot;
+
+- if (work_pending(&sc->hw_reset_work)) {
++ if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) {
+ ath_dbg(common, RESET,
+ "reset work is pending, skip beaconing now\n");
+ return;
+ }
++
+ /*
+ * Check if the previous beacon has gone out. If
+ * not don't try to post another, skip this period
+@@ -345,7 +346,7 @@ void ath9k_beacon_tasklet(unsigned long
+ } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
+ ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
+ sc->beacon.bmisscnt = 0;
+- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++ ath9k_queue_reset(sc, RESET_TYPE_BEACON_STUCK);
+ }
+
+ return;
+--- a/drivers/net/wireless/ath/ath9k/debug.h
++++ b/drivers/net/wireless/ath/ath9k/debug.h
+@@ -32,6 +32,19 @@ struct ath_buf;
+ #define RESET_STAT_INC(sc, type) do { } while (0)
+ #endif
+
++enum ath_reset_type {
++ RESET_TYPE_BB_HANG,
++ RESET_TYPE_BB_WATCHDOG,
++ RESET_TYPE_FATAL_INT,
++ RESET_TYPE_TX_ERROR,
++ RESET_TYPE_TX_HANG,
++ RESET_TYPE_PLL_HANG,
++ RESET_TYPE_MAC_HANG,
++ RESET_TYPE_BEACON_STUCK,
++ RESET_TYPE_MCI,
++ __RESET_TYPE_MAX
++};
++
+ #ifdef CONFIG_ATH9K_DEBUGFS
+
+ /**
+@@ -209,17 +222,6 @@ struct ath_rx_stats {
+ u32 rx_frags;
+ };
+
+-enum ath_reset_type {
+- RESET_TYPE_BB_HANG,
+- RESET_TYPE_BB_WATCHDOG,
+- RESET_TYPE_FATAL_INT,
+- RESET_TYPE_TX_ERROR,
+- RESET_TYPE_TX_HANG,
+- RESET_TYPE_PLL_HANG,
+- RESET_TYPE_MAC_HANG,
+- __RESET_TYPE_MAX
+-};
+-
+ struct ath_stats {
+ struct ath_interrupt_stats istats;
+ struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
+--- a/drivers/net/wireless/ath/ath9k/link.c
++++ b/drivers/net/wireless/ath/ath9k/link.c
+@@ -50,8 +50,7 @@ void ath_tx_complete_poll_work(struct wo
+ if (needreset) {
+ ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
+ "tx hung, resetting the chip\n");
+- RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
+- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++ ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
+ return;
+ }
+
+@@ -69,6 +68,7 @@ void ath_hw_check(struct work_struct *wo
+ unsigned long flags;
+ int busy;
+ u8 is_alive, nbeacon = 1;
++ enum ath_reset_type type;
+
+ ath9k_ps_wakeup(sc);
+ is_alive = ath9k_hw_check_alive(sc->sc_ah);
+@@ -78,7 +78,7 @@ void ath_hw_check(struct work_struct *wo
+ else if (!is_alive && AR_SREV_9300(sc->sc_ah)) {
+ ath_dbg(common, RESET,
+ "DCU stuck is detected. Schedule chip reset\n");
+- RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG);
++ type = RESET_TYPE_MAC_HANG;
+ goto sched_reset;
+ }
+
+@@ -90,7 +90,7 @@ void ath_hw_check(struct work_struct *wo
+ busy, sc->hw_busy_count + 1);
+ if (busy >= 99) {
+ if (++sc->hw_busy_count >= 3) {
+- RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);
++ type = RESET_TYPE_BB_HANG;
+ goto sched_reset;
+ }
+ } else if (busy >= 0) {
+@@ -102,7 +102,7 @@ void ath_hw_check(struct work_struct *wo
+ goto out;
+
+ sched_reset:
+- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++ ath9k_queue_reset(sc, type);
+ out:
+ ath9k_ps_restore(sc);
+ }
+@@ -119,8 +119,7 @@ static bool ath_hw_pll_rx_hang_check(str
+ count++;
+ if (count == 3) {
+ ath_dbg(common, RESET, "PLL WAR, resetting the chip\n");
+- RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
+- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++ ath9k_queue_reset(sc, RESET_TYPE_PLL_HANG);
+ count = 0;
+ return true;
+ }
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -362,6 +362,7 @@ void ath9k_tasklet(unsigned long data)
+ struct ath_softc *sc = (struct ath_softc *)data;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
++ enum ath_reset_type type;
+ unsigned long flags;
+ u32 status = sc->intrstatus;
+ u32 rxmask;
+@@ -371,18 +372,13 @@ void ath9k_tasklet(unsigned long data)
+
+ if ((status & ATH9K_INT_FATAL) ||
+ (status & ATH9K_INT_BB_WATCHDOG)) {
+-#ifdef CONFIG_ATH9K_DEBUGFS
+- enum ath_reset_type type;
+
+ if (status & ATH9K_INT_FATAL)
+ type = RESET_TYPE_FATAL_INT;
+ else
+ type = RESET_TYPE_BB_WATCHDOG;
+
+- RESET_STAT_INC(sc, type);
+-#endif
+- set_bit(SC_OP_HW_RESET, &sc->sc_flags);
+- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++ ath9k_queue_reset(sc, type);
+ goto out;
+ }
+
+@@ -572,6 +568,15 @@ static int ath_reset(struct ath_softc *s
+ return r;
+ }
+
++void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type)
++{
++#ifdef CONFIG_ATH9K_DEBUGFS
++ RESET_STAT_INC(sc, type);
++#endif
++ set_bit(SC_OP_HW_RESET, &sc->sc_flags);
++ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++}
++
+ void ath_reset_work(struct work_struct *work)
+ {
+ struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
+--- a/drivers/net/wireless/ath/ath9k/mci.c
++++ b/drivers/net/wireless/ath/ath9k/mci.c
+@@ -202,7 +202,7 @@ static void ath_mci_cal_msg(struct ath_s
+ case MCI_GPM_BT_CAL_REQ:
+ if (mci_hw->bt_state == MCI_BT_AWAKE) {
+ ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START);
+- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++ ath9k_queue_reset(sc, RESET_TYPE_MCI);
+ }
+ ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
+ break;
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -614,10 +614,8 @@ static void ath_tx_complete_aggr(struct
+
+ rcu_read_unlock();
+
+- if (needreset) {
+- RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
+- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+- }
++ if (needreset)
++ ath9k_queue_reset(sc, RESET_TYPE_TX_ERROR);
+ }
+
+ static bool ath_lookup_legacy(struct ath_buf *bf)
+@@ -1576,7 +1574,8 @@ void ath_txq_schedule(struct ath_softc *
+ struct ath_atx_ac *ac, *ac_tmp, *last_ac;
+ struct ath_atx_tid *tid, *last_tid;
+
+- if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
++ if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) ||
++ list_empty(&txq->axq_acq) ||
+ txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+ return;
+
+@@ -2181,7 +2180,7 @@ static void ath_tx_processq(struct ath_s
+
+ ath_txq_lock(sc, txq);
+ for (;;) {
+- if (work_pending(&sc->hw_reset_work))
++ if (test_bit(SC_OP_HW_RESET, &sc->sc_flags))
+ break;
+
+ if (list_empty(&txq->axq_q)) {
+@@ -2264,7 +2263,7 @@ void ath_tx_edma_tasklet(struct ath_soft
+ int status;
+
+ for (;;) {
+- if (work_pending(&sc->hw_reset_work))
++ if (test_bit(SC_OP_HW_RESET, &sc->sc_flags))
+ break;
+
+ status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
--
1.7.11.4



2012-08-07 01:00:08

by Sujith Manoharan

[permalink] [raw]
Subject: Re: [PATCH 3.5.y 2/2] compat-wireless: Add new cherry-picked patches

Luis R. Rodriguez wrote:
> 8 of the hunks were just version of git ouputs at the end of the patch
> files, we gotta find a way to ignore that from git format-patch. I
> didn't find anything yet.

Sorry, I didn't notice the changes were just line noise.

> I'll run a series of tests later and appropriately tag things after
> the test, and push new respective releases then.

Ok.

Sujith

2012-08-06 19:44:55

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 3.5.y 2/2] compat-wireless: Add new cherry-picked patches

On Mon, Aug 6, 2012 at 9:43 AM, Sujith Manoharan
<[email protected]> wrote:
> Signed-off-by: Sujith Manoharan <[email protected]>

8 of the hunks were just version of git ouputs at the end of the patch
files, we gotta find a way to ignore that from git format-patch. I
didn't find anything yet.

Thanks so much for these patches! I've applied them and pushed them,
I'll run a series of tests later and appropriately tag things after
the test, and push new respective releases then.

Luis

2012-08-07 04:56:01

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 3.5.y 2/2] compat-wireless: Add new cherry-picked patches

On Mon, Aug 6, 2012 at 5:56 PM, Sujith Manoharan
<[email protected]> wrote:
> Luis R. Rodriguez wrote:
>> 8 of the hunks were just version of git ouputs at the end of the patch
>> files, we gotta find a way to ignore that from git format-patch. I
>> didn't find anything yet.
>
> Sorry, I didn't notice the changes were just line noise.

No need to be, its part of the scripts, I just happened to notice it :P

>> I'll run a series of tests later and appropriately tag things after
>> the test, and push new respective releases then.
>
> Ok.

I'll let this rip in a second.

Luis