Commit 7607cbe2 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

ath9k: fix PA predistortion thermal measurement handling

To be able to measure the thermal values correctly for PAPRD, we need
to send training frames before setting up the gain table for the measurement,
and then again afterwards for the actual training.

For further improvement, send training frames at MCS0 instead of 54 MBit/s
legacy. That way we can use the No-ACK flag for the transmission, which
speeds up PAPRD training in general, as the hardware won't have to
retransmit and wait for ACK timeout (was previously set to 4 * 6
transmission attempts).
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent caabf2bf
...@@ -320,6 +320,42 @@ static void ath_paprd_activate(struct ath_softc *sc) ...@@ -320,6 +320,42 @@ static void ath_paprd_activate(struct ath_softc *sc)
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
} }
static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain)
{
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath_tx_control txctl;
int time_left;
memset(&txctl, 0, sizeof(txctl));
txctl.txq = sc->tx.txq_map[WME_AC_BE];
memset(tx_info, 0, sizeof(*tx_info));
tx_info->band = hw->conf.channel->band;
tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
tx_info->control.rates[0].idx = 0;
tx_info->control.rates[0].count = 1;
tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
tx_info->control.rates[1].idx = -1;
init_completion(&sc->paprd_complete);
sc->paprd_pending = true;
txctl.paprd = BIT(chain);
if (ath_tx_start(hw, skb, &txctl) != 0)
return false;
time_left = wait_for_completion_timeout(&sc->paprd_complete,
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
sc->paprd_pending = false;
if (!time_left)
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on TX chain %d\n",
chain);
return !!time_left;
}
void ath_paprd_calibrate(struct work_struct *work) void ath_paprd_calibrate(struct work_struct *work)
{ {
struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work);
...@@ -327,18 +363,12 @@ void ath_paprd_calibrate(struct work_struct *work) ...@@ -327,18 +363,12 @@ void ath_paprd_calibrate(struct work_struct *work)
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
struct ieee80211_tx_info *tx_info;
int band = hw->conf.channel->band;
struct ieee80211_supported_band *sband = &sc->sbands[band];
struct ath_tx_control txctl;
struct ath9k_hw_cal_data *caldata = ah->caldata; struct ath9k_hw_cal_data *caldata = ah->caldata;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
int ftype; int ftype;
int chain_ok = 0; int chain_ok = 0;
int chain; int chain;
int len = 1800; int len = 1800;
int time_left;
int i;
if (!caldata) if (!caldata)
return; return;
...@@ -347,8 +377,6 @@ void ath_paprd_calibrate(struct work_struct *work) ...@@ -347,8 +377,6 @@ void ath_paprd_calibrate(struct work_struct *work)
if (!skb) if (!skb)
return; return;
tx_info = IEEE80211_SKB_CB(skb);
skb_put(skb, len); skb_put(skb, len);
memset(skb->data, 0, len); memset(skb->data, 0, len);
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
...@@ -359,9 +387,6 @@ void ath_paprd_calibrate(struct work_struct *work) ...@@ -359,9 +387,6 @@ void ath_paprd_calibrate(struct work_struct *work)
memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
memset(&txctl, 0, sizeof(txctl));
txctl.txq = sc->tx.txq_map[WME_AC_BE];
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
ar9003_paprd_init_table(ah); ar9003_paprd_init_table(ah);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
...@@ -369,30 +394,19 @@ void ath_paprd_calibrate(struct work_struct *work) ...@@ -369,30 +394,19 @@ void ath_paprd_calibrate(struct work_struct *work)
continue; continue;
chain_ok = 0; chain_ok = 0;
memset(tx_info, 0, sizeof(*tx_info));
tx_info->band = band;
for (i = 0; i < 4; i++) { ath_dbg(common, ATH_DBG_CALIBRATE,
tx_info->control.rates[i].idx = sband->n_bitrates - 1; "Sending PAPRD frame for thermal measurement "
tx_info->control.rates[i].count = 6; "on chain %d\n", chain);
} if (!ath_paprd_send_frame(sc, skb, chain))
goto fail_paprd;
init_completion(&sc->paprd_complete);
sc->paprd_pending = true;
ar9003_paprd_setup_gain_table(ah, chain); ar9003_paprd_setup_gain_table(ah, chain);
txctl.paprd = BIT(chain);
if (ath_tx_start(hw, skb, &txctl) != 0)
break;
time_left = wait_for_completion_timeout(&sc->paprd_complete, ath_dbg(common, ATH_DBG_CALIBRATE,
msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); "Sending PAPRD training frame on chain %d\n", chain);
sc->paprd_pending = false; if (!ath_paprd_send_frame(sc, skb, chain))
if (!time_left) {
ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on TX chain %d\n",
chain);
goto fail_paprd; goto fail_paprd;
}
if (!ar9003_paprd_is_done(ah)) if (!ar9003_paprd_is_done(ah))
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment