+--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+@@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_tab
+ };
+ int training_power;
+ int i, val;
++ u32 am2pm_mask = ah->paprd_ratemask;
+
+ if (IS_CHAN_2GHZ(ah->curchan))
+ training_power = ar9003_get_training_power_2g(ah);
+@@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_tab
+ }
+ ah->paprd_training_power = training_power;
+
++ if (AR_SREV_9330(ah))
++ am2pm_mask = 0;
++
+ REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
+ ah->paprd_ratemask);
+ REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,
+- ah->paprd_ratemask);
++ am2pm_mask);
+ REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
+ ah->paprd_ratemask_ht40);
+
+@@ -782,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct
+ }
+ EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
+
++static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah,
++ struct ath9k_hw_cal_data *caldata,
++ int chain)
++{
++ u32 *pa_in = caldata->pa_table[chain];
++ int capdiv_offset, quick_drop_offset;
++ int capdiv2g, quick_drop;
++ int count = 0;
++ int i;
++
++ if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah))
++ return false;
++
++ capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
++ AR_PHY_65NM_CH0_TXRF3_CAPDIV2G);
++
++ quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
++ AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);
++
++ if (quick_drop)
++ quick_drop -= 0x40;
++
++ for (i = 0; i < NUM_BIN + 1; i++) {
++ if (pa_in[i] == 1400)
++ count++;
++ }
++
++ if (AR_SREV_9485(ah)) {
++ if (pa_in[23] < 800) {
++ capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150);
++ capdiv2g += capdiv_offset;
++ if (capdiv2g > 7) {
++ capdiv2g = 7;
++ if (pa_in[23] < 600) {
++ quick_drop++;
++ if (quick_drop > 0)
++ quick_drop = 0;
++ }
++ }
++ } else if (pa_in[23] == 1400) {
++ quick_drop_offset = min_t(int, count / 3, 2);
++ quick_drop += quick_drop_offset;
++ capdiv2g += quick_drop_offset / 2;
++
++ if (capdiv2g > 7)
++ capdiv2g = 7;
++
++ if (quick_drop > 0) {
++ quick_drop = 0;
++ capdiv2g -= quick_drop_offset;
++ if (capdiv2g < 0)
++ capdiv2g = 0;
++ }
++ } else {
++ return false;
++ }
++ } else if (AR_SREV_9330(ah)) {
++ if (pa_in[23] < 1000) {
++ capdiv_offset = (1000 - pa_in[23]) / 100;
++ capdiv2g += capdiv_offset;
++ if (capdiv_offset > 3) {
++ capdiv_offset = 1;
++ quick_drop--;
++ }
++
++ capdiv2g += capdiv_offset;
++ if (capdiv2g > 6)
++ capdiv2g = 6;
++ if (quick_drop < -4)
++ quick_drop = -4;
++ } else if (pa_in[23] == 1400) {
++ if (count > 3) {
++ quick_drop++;
++ capdiv2g -= count / 4;
++ if (quick_drop > -2)
++ quick_drop = -2;
++ } else {
++ capdiv2g--;
++ }
++
++ if (capdiv2g < 0)
++ capdiv2g = 0;
++ } else {
++ return false;
++ }
++ }
++
++ REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
++ AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g);
++ REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
++ AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
++ quick_drop);
++
++ return true;
++}
++
+ int ar9003_paprd_create_curve(struct ath_hw *ah,
+ struct ath9k_hw_cal_data *caldata, int chain)
+ {
+@@ -817,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath
+ if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))
+ status = -2;
+
++ if (ar9003_paprd_retrain_pa_in(ah, caldata, chain))
++ status = -EINPROGRESS;
++
+ REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+ AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -773,15 +773,10 @@ bool ath9k_hw_intrpend(struct ath_hw *ah
+ }
+ EXPORT_SYMBOL(ath9k_hw_intrpend);
+
+-void ath9k_hw_disable_interrupts(struct ath_hw *ah)
++void ath9k_hw_kill_interrupts(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+
+- if (!(ah->imask & ATH9K_INT_GLOBAL))
+- atomic_set(&ah->intr_ref_cnt, -1);
+- else
+- atomic_dec(&ah->intr_ref_cnt);
+-
+ ath_dbg(common, INTERRUPT, "disable IER\n");
+ REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+ (void) REG_READ(ah, AR_IER);
+@@ -793,6 +788,17 @@ void ath9k_hw_disable_interrupts(struct
+ (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
+ }
+ }
++EXPORT_SYMBOL(ath9k_hw_kill_interrupts);
++
++void ath9k_hw_disable_interrupts(struct ath_hw *ah)
++{
++ if (!(ah->imask & ATH9K_INT_GLOBAL))
++ atomic_set(&ah->intr_ref_cnt, -1);
++ else
++ atomic_dec(&ah->intr_ref_cnt);
++
++ ath9k_hw_kill_interrupts(ah);
++}
+ EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
+
+ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -738,6 +738,7 @@ bool ath9k_hw_intrpend(struct ath_hw *ah
+ void ath9k_hw_set_interrupts(struct ath_hw *ah);
+ void ath9k_hw_enable_interrupts(struct ath_hw *ah);
+ void ath9k_hw_disable_interrupts(struct ath_hw *ah);
++void ath9k_hw_kill_interrupts(struct ath_hw *ah);
+
+ void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
+
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -331,6 +331,9 @@ static int ath_pci_suspend(struct device
+ static int ath_pci_resume(struct device *device)
+ {
+ struct pci_dev *pdev = to_pci_dev(device);
++ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
++ struct ath_softc *sc = hw->priv;
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ u32 val;
+
+ /*
+@@ -342,6 +345,8 @@ static int ath_pci_resume(struct device
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
++ ath_pci_aspm_init(common);
++
+ return 0;
+ }
+