--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -30,9 +30,69 @@ void ar9003_paprd_enable(struct ath_hw *
 }
 EXPORT_SYMBOL(ar9003_paprd_enable);
 
-static void ar9003_paprd_setup_single_table(struct ath_hw *ah)
+static int ar9003_get_training_power_2g(struct ath_hw *ah)
 {
 	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+	struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G;
+	unsigned int power, scale, delta;
+
+	scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1);
+	power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
+			       AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
+
+	delta = abs((int) ah->paprd_target_power - (int) power);
+	if (delta > scale)
+		return -1;
+
+	if (delta < 4)
+		power -= 4 - delta;
+
+	return power;
+}
+
+static int get_streams(int mask)
+{
+	return !!(mask & BIT(0)) + !!(mask & BIT(1)) + !!(mask & BIT(2));
+}
+
+static int ar9003_get_training_power_5g(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+	struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;
+	struct ath9k_channel *chan = ah->curchan;
+	unsigned int power, scale, delta;
+
+	if (chan->channel >= 5700)
+		scale = MS(le32_to_cpu(hdr->papdRateMaskHt20),
+			   AR9300_PAPRD_SCALE_1);
+	else if (chan->channel >= 5400)
+		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
+			   AR9300_PAPRD_SCALE_2);
+	else
+		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
+			   AR9300_PAPRD_SCALE_1);
+
+	if (IS_CHAN_HT40(chan))
+		power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
+			AR_PHY_POWERTX_RATE8_POWERTXHT40_5);
+	else
+		power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6,
+			AR_PHY_POWERTX_RATE6_POWERTXHT20_5);
+
+	power += scale;
+	delta = abs((int) ah->paprd_target_power - (int) power);
+	if (delta > scale)
+		return -1;
+
+	power += 2 * get_streams(common->tx_chainmask);
+	return power;
+}
+
+static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
 	struct ar9300_modal_eep_header *hdr;
 	static const u32 ctrl0[3] = {
 		AR_PHY_PAPRD_CTRL0_B0,
@@ -45,6 +105,7 @@ static void ar9003_paprd_setup_single_ta
 		AR_PHY_PAPRD_CTRL1_B2
 	};
 	u32 am_mask, ht40_mask;
+	int training_power;
 	int i;
 
 	if (ah->curchan && IS_CHAN_5GHZ(ah->curchan))
@@ -55,11 +116,25 @@ static void ar9003_paprd_setup_single_ta
 	am_mask = le32_to_cpu(hdr->papdRateMaskHt20) & AR9300_PAPRD_RATE_MASK;
 	ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40) & AR9300_PAPRD_RATE_MASK;
 
+	if (IS_CHAN_2GHZ(ah->curchan))
+		training_power = ar9003_get_training_power_2g(ah);
+	else
+		training_power = ar9003_get_training_power_5g(ah);
+
+	if (training_power < 0) {
+		ath_dbg(common, ATH_DBG_CALIBRATE,
+			"PAPRD target power delta out of range");
+		return -ERANGE;
+	}
+	ah->paprd_training_power = training_power;
+	ath_dbg(common, ATH_DBG_CALIBRATE,
+		"Training power: %d, Target power: %d\n",
+		ah->paprd_training_power, ah->paprd_target_power);
+
 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask);
 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask);
 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask);
 
-
 	for (i = 0; i < ah->caps.max_txchains; i++) {
 		REG_RMW_FIELD(ah, ctrl0[i],
 			      AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1);
@@ -141,6 +216,7 @@ static void ar9003_paprd_setup_single_ta
 		      AR_PHY_PAPRD_PRE_POST_SCALING, 185706);
 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0,
 		      AR_PHY_PAPRD_PRE_POST_SCALING, 175487);
+	return 0;
 }
 
 static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
@@ -595,15 +671,10 @@ void ar9003_paprd_populate_single_table(
 {
 	u32 *paprd_table_val = caldata->pa_table[chain];
 	u32 small_signal_gain = caldata->small_signal_gain[chain];
-	u32 training_power;
+	u32 training_power = ah->paprd_training_power;
 	u32 reg = 0;
 	int i;
 
-	training_power =
-	    REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
-			   AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
-	training_power -= 4;
-
 	if (chain == 0)
 		reg = AR_PHY_PAPRD_MEM_TAB_B0;
 	else if (chain == 1)
@@ -643,14 +714,8 @@ EXPORT_SYMBOL(ar9003_paprd_populate_sing
 
 int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
 {
-
 	unsigned int i, desired_gain, gain_index;
-	unsigned int train_power;
-
-	train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
-				     AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
-
-	train_power = train_power - 4;
+	unsigned int train_power = ah->paprd_training_power;
 
 	desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
 
@@ -716,7 +781,12 @@ EXPORT_SYMBOL(ar9003_paprd_create_curve)
 
 int ar9003_paprd_init_table(struct ath_hw *ah)
 {
-	ar9003_paprd_setup_single_table(ah);
+	int ret;
+
+	ret = ar9003_paprd_setup_single_table(ah);
+	if (ret < 0)
+	    return ret;
+
 	ar9003_paprd_get_gain_table(ah);
 	return 0;
 }
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -835,6 +835,8 @@ struct ath_hw {
 	u32 bb_watchdog_last_status;
 	u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */
 
+	unsigned int paprd_target_power;
+	unsigned int paprd_training_power;
 	u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
 	u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
 	/*
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -1090,6 +1090,14 @@
 #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0	0x3F
 #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S	0
 
+#define AR_PHY_POWERTX_RATE6			(AR_SM_BASE + 0x1d4)
+#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5	0x3F00
+#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5_S	8
+
+#define AR_PHY_POWERTX_RATE8			(AR_SM_BASE + 0x1dc)
+#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5	0x3F00
+#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S	8
+
 void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
 
 #endif  /* AR9003_PHY_H */
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -4798,6 +4798,19 @@ static void ath9k_hw_ar9300_set_txpower(
 	/* Write target power array to registers */
 	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
 	ar9003_hw_calibration_apply(ah, chan->channel);
+
+	if (IS_CHAN_2GHZ(chan)) {
+		if (IS_CHAN_HT40(chan))
+			i = ALL_TARGET_HT40_0_8_16;
+		else
+			i = ALL_TARGET_HT20_0_8_16;
+	} else {
+		if (IS_CHAN_HT40(chan))
+			i = ALL_TARGET_HT40_7;
+		else
+			i = ALL_TARGET_HT20_7;
+	}
+	ah->paprd_target_power = targetPowerValT2[i];
 }
 
 static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -373,6 +373,9 @@ void ath_paprd_calibrate(struct work_str
 	if (!caldata)
 		return;
 
+	if (ar9003_paprd_init_table(ah) < 0)
+		return;
+
 	skb = alloc_skb(len, GFP_KERNEL);
 	if (!skb)
 		return;
@@ -388,7 +391,6 @@ void ath_paprd_calibrate(struct work_str
 	memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
 
 	ath9k_ps_wakeup(sc);
-	ar9003_paprd_init_table(ah);
 	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
 		if (!(common->tx_chainmask & BIT(chain)))
 			continue;