channelSel = CHANSEL_5G(freq);
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
-@@ -633,6 +633,8 @@
+@@ -625,6 +625,10 @@
+ #define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0)
+ #define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc)
+
++#define AR_PHY_65NM_CH0_TXRF3 0x16048
++#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G 0x0000001e
++#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S 1
++
+ #define AR_PHY_65NM_CH0_SYNTH4 0x1608c
+ #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)
+ #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1)
+@@ -633,6 +637,8 @@
#define AR_PHY_65NM_CH0_BIAS2 0x160c4
#define AR_PHY_65NM_CH0_BIAS4 0x160cc
#define AR_PHY_65NM_CH0_RXTX4 0x1610c
#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \
((AR_SREV_9462(ah) ? 0x1628c : 0x16280)))
-@@ -876,6 +878,9 @@
+@@ -876,6 +882,9 @@
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -671,10 +671,6 @@ static int __ath9k_hw_init(struct ath_hw
+@@ -463,9 +463,6 @@ static void ath9k_hw_init_config(struct
+ ah->config.spurchans[i][1] = AR_NO_SPUR;
+ }
+
+- /* PAPRD needs some more work to be enabled */
+- ah->config.paprd_disable = 1;
+-
+ ah->config.rx_intr_mitigation = true;
+ ah->config.pcieSerDesWrite = true;
+
+@@ -671,10 +668,6 @@ static int __ath9k_hw_init(struct ath_hw
if (!AR_SREV_9300_20_OR_LATER(ah))
ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
ath9k_hw_init_mode_regs(ah);
if (!ah->is_pciexpress)
+@@ -1781,6 +1774,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ /* Operating channel changed, reset channel calibration data */
+ memset(caldata, 0, sizeof(*caldata));
+ ath9k_init_nfcal_hist_buffer(ah, chan);
++ } else if (caldata) {
++ caldata->paprd_packet_sent = false;
+ }
+ ah->noise = ath9k_hw_getchan_noise(ah, chan);
+
+@@ -2505,7 +2500,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+ pCap->tx_desc_len = sizeof(struct ar9003_txc);
+ pCap->txs_len = sizeof(struct ar9003_txs);
+ if (!ah->config.paprd_disable &&
+- ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
++ ah->eep_ops->get_eeprom(ah, EEP_PAPRD) &&
++ !AR_SREV_9462(ah))
+ pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
+ } else {
+ pCap->tx_desc_len = sizeof(struct ath_desc);
@@ -2916,9 +2912,9 @@ void ath9k_hw_reset_tsf(struct ath_hw *a
}
EXPORT_SYMBOL(ath9k_hw_reset_tsf);
ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -994,7 +994,7 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah)
+@@ -404,6 +404,7 @@ struct ath9k_hw_cal_data {
+ int8_t iCoff;
+ int8_t qCoff;
+ bool rtt_done;
++ bool paprd_packet_sent;
+ bool paprd_done;
+ bool nfcal_pending;
+ bool nfcal_interference;
+@@ -994,7 +995,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);
count = 0;
return true;
}
+@@ -255,8 +254,9 @@ void ath_paprd_calibrate(struct work_str
+ int chain_ok = 0;
+ int chain;
+ int len = 1800;
++ int ret;
+
+- if (!caldata)
++ if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done)
+ return;
+
+ ath9k_ps_wakeup(sc);
+@@ -283,13 +283,6 @@ void ath_paprd_calibrate(struct work_str
+ continue;
+
+ chain_ok = 0;
+-
+- ath_dbg(common, CALIBRATE,
+- "Sending PAPRD frame for thermal measurement on chain %d\n",
+- chain);
+- if (!ath_paprd_send_frame(sc, skb, chain))
+- goto fail_paprd;
+-
+ ar9003_paprd_setup_gain_table(ah, chain);
+
+ ath_dbg(common, CALIBRATE,
+@@ -303,7 +296,13 @@ void ath_paprd_calibrate(struct work_str
+ break;
+ }
+
+- if (ar9003_paprd_create_curve(ah, caldata, chain)) {
++ ret = ar9003_paprd_create_curve(ah, caldata, chain);
++ if (ret == -EINPROGRESS) {
++ ath_dbg(common, CALIBRATE,
++ "PAPRD curve on chain %d needs to be re-trained\n",
++ chain);
++ break;
++ } else if (ret) {
+ ath_dbg(common, CALIBRATE,
+ "PAPRD create curve failed on chain %d\n",
+ chain);
@@ -432,26 +431,69 @@ set_timer:
}
}
goto out;
}
-@@ -586,6 +577,15 @@ static int ath_reset(struct ath_softc *s
+@@ -468,8 +459,10 @@ irqreturn_t ath_isr(int irq, void *dev)
+ if (!ath9k_hw_intrpend(ah))
+ return IRQ_NONE;
+
+- if(test_bit(SC_OP_HW_RESET, &sc->sc_flags))
++ if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) {
++ ath9k_hw_kill_interrupts(ah);
+ return IRQ_HANDLED;
++ }
+
+ /*
+ * Figure out the reason(s) for the interrupt. Note
+@@ -586,6 +579,15 @@ static int ath_reset(struct ath_softc *s
return r;
}
void ath_reset_work(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
-@@ -852,16 +852,6 @@ bool ath9k_uses_beacons(int type)
+@@ -852,16 +854,6 @@ bool ath9k_uses_beacons(int type)
}
}
static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct ath9k_vif_iter_data *iter_data = data;
-@@ -929,18 +919,14 @@ static void ath9k_calculate_summary_stat
+@@ -929,18 +921,14 @@ static void ath9k_calculate_summary_stat
ath9k_calculate_iter_data(hw, vif, &iter_data);
if (iter_data.nmeshes)
ah->opmode = NL80211_IFTYPE_MESH_POINT;
-@@ -952,45 +938,14 @@ static void ath9k_calculate_summary_stat
+@@ -952,45 +940,14 @@ static void ath9k_calculate_summary_stat
ah->opmode = NL80211_IFTYPE_STATION;
}
}
static int ath9k_add_interface(struct ieee80211_hw *hw,
-@@ -1032,7 +987,10 @@ static int ath9k_add_interface(struct ie
+@@ -1032,7 +989,10 @@ static int ath9k_add_interface(struct ie
sc->nvifs++;
out:
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
-@@ -1049,6 +1007,7 @@ static int ath9k_change_interface(struct
+@@ -1049,6 +1009,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);
-@@ -1061,15 +1020,16 @@ static int ath9k_change_interface(struct
+@@ -1061,15 +1022,16 @@ static int ath9k_change_interface(struct
}
}
out:
ath9k_ps_restore(sc);
mutex_unlock(&sc->mutex);
-@@ -1089,9 +1049,8 @@ static void ath9k_remove_interface(struc
+@@ -1089,9 +1051,8 @@ static void ath9k_remove_interface(struc
sc->nvifs--;
ath9k_calculate_summary_state(hw, NULL);
-@@ -1388,21 +1347,18 @@ static int ath9k_conf_tx(struct ieee8021
+@@ -1388,21 +1349,18 @@ static int ath9k_conf_tx(struct ieee8021
qi.tqi_aifs = params->aifs;
qi.tqi_cwmin = params->cw_min;
qi.tqi_cwmax = params->cw_max;
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
-@@ -1471,85 +1427,36 @@ static int ath9k_set_key(struct ieee8021
+@@ -1471,85 +1429,36 @@ static int ath9k_set_key(struct ieee8021
return ret;
}
}
}
-@@ -1558,6 +1465,11 @@ static void ath9k_bss_info_changed(struc
+@@ -1558,6 +1467,11 @@ static void ath9k_bss_info_changed(struc
struct ieee80211_bss_conf *bss_conf,
u32 changed)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
-@@ -1568,53 +1480,43 @@ static void ath9k_bss_info_changed(struc
+@@ -1568,53 +1482,43 @@ static void ath9k_bss_info_changed(struc
mutex_lock(&sc->mutex);
if (changed & BSS_CHANGED_ASSOC) {
}
if (changed & BSS_CHANGED_ERP_SLOT) {
-@@ -1636,8 +1538,13 @@ static void ath9k_bss_info_changed(struc
+@@ -1636,8 +1540,13 @@ static void ath9k_bss_info_changed(struc
}
}
}
static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-@@ -1866,10 +1773,11 @@ static int ath9k_tx_last_beacon(struct i
+@@ -1866,10 +1775,11 @@ static int ath9k_tx_last_beacon(struct i
if (!vif)
return 0;
if (!sc->beacon.tx_processed && !edma) {
tasklet_disable(&sc->bcon_tasklet);
-@@ -1923,12 +1831,29 @@ static u32 fill_chainmask(u32 cap, u32 n
+@@ -1923,12 +1833,29 @@ static u32 fill_chainmask(u32 cap, u32 n
return filled;
}
ieee80211_stop_queue(sc->hw, q);
txq->stopped = true;
}
-@@ -2047,7 +2060,8 @@ static void ath_tx_complete(struct ath_s
+@@ -2015,6 +2028,9 @@ static void ath_tx_complete(struct ath_s
+
+ ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
+
++ if (sc->sc_ah->caldata)
++ sc->sc_ah->caldata->paprd_packet_sent = true;
++
+ if (!(tx_flags & ATH_TX_ERROR))
+ /* Frame was ACKed */
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+@@ -2047,7 +2063,8 @@ static void ath_tx_complete(struct ath_s
if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0;
ieee80211_wake_queue(sc->hw, q);
txq->stopped = false;
}
-@@ -2191,7 +2205,7 @@ static void ath_tx_processq(struct ath_s
+@@ -2191,7 +2208,7 @@ static void ath_tx_processq(struct ath_s
ath_txq_lock(sc, txq);
for (;;) {
break;
if (list_empty(&txq->axq_q)) {
-@@ -2274,7 +2288,7 @@ void ath_tx_edma_tasklet(struct ath_soft
+@@ -2274,7 +2291,7 @@ void ath_tx_edma_tasklet(struct ath_soft
int status;
for (;;) {
#define AR5K_EEPROM_N_2GHZ_CHAN 3
#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4
#define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4
+--- 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;
+ }
+
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-@@ -786,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)
- {
-@@ -821,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/ar9003_phy.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
-@@ -625,6 +625,10 @@
- #define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0)
- #define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc)
-
-+#define AR_PHY_65NM_CH0_TXRF3 0x16048
-+#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G 0x0000001e
-+#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S 1
-+
- #define AR_PHY_65NM_CH0_SYNTH4 0x1608c
- #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)
- #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1)
---- a/drivers/net/wireless/ath/ath9k/link.c
-+++ b/drivers/net/wireless/ath/ath9k/link.c
-@@ -254,6 +254,7 @@ void ath_paprd_calibrate(struct work_str
- int chain_ok = 0;
- int chain;
- int len = 1800;
-+ int ret;
-
- if (!caldata)
- return;
-@@ -302,7 +303,13 @@ void ath_paprd_calibrate(struct work_str
- break;
- }
-
-- if (ar9003_paprd_create_curve(ah, caldata, chain)) {
-+ ret = ar9003_paprd_create_curve(ah, caldata, chain);
-+ if (ret == -EINPROGRESS) {
-+ ath_dbg(common, CALIBRATE,
-+ "PAPRD curve on chain %d needs to be re-trained\n",
-+ chain);
-+ break;
-+ } else if (ret) {
- ath_dbg(common, CALIBRATE,
- "PAPRD create curve failed on chain %d\n",
- chain);