mirror of
https://github.com/torvalds/linux.git
synced 2024-12-24 11:51:27 +00:00
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: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
caabf2bf22
commit
7607cbe2ad
@ -320,6 +320,42 @@ static void ath_paprd_activate(struct ath_softc *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)
|
||||
{
|
||||
struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work);
|
||||
@ -327,18 +363,12 @@ void ath_paprd_calibrate(struct work_struct *work)
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ieee80211_hdr *hdr;
|
||||
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 ath_common *common = ath9k_hw_common(ah);
|
||||
int ftype;
|
||||
int chain_ok = 0;
|
||||
int chain;
|
||||
int len = 1800;
|
||||
int time_left;
|
||||
int i;
|
||||
|
||||
if (!caldata)
|
||||
return;
|
||||
@ -347,8 +377,6 @@ void ath_paprd_calibrate(struct work_struct *work)
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
skb_put(skb, len);
|
||||
memset(skb->data, 0, len);
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
@ -359,9 +387,6 @@ void ath_paprd_calibrate(struct work_struct *work)
|
||||
memcpy(hdr->addr2, 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);
|
||||
ar9003_paprd_init_table(ah);
|
||||
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
|
||||
@ -369,30 +394,19 @@ void ath_paprd_calibrate(struct work_struct *work)
|
||||
continue;
|
||||
|
||||
chain_ok = 0;
|
||||
memset(tx_info, 0, sizeof(*tx_info));
|
||||
tx_info->band = band;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
tx_info->control.rates[i].idx = sband->n_bitrates - 1;
|
||||
tx_info->control.rates[i].count = 6;
|
||||
}
|
||||
|
||||
init_completion(&sc->paprd_complete);
|
||||
sc->paprd_pending = true;
|
||||
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,
|
||||
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
|
||||
sc->paprd_pending = false;
|
||||
if (!time_left) {
|
||||
ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
|
||||
"Timeout waiting for paprd training on TX chain %d\n",
|
||||
chain);
|
||||
ath_dbg(common, ATH_DBG_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, ATH_DBG_CALIBRATE,
|
||||
"Sending PAPRD training frame on chain %d\n", chain);
|
||||
if (!ath_paprd_send_frame(sc, skb, chain))
|
||||
goto fail_paprd;
|
||||
}
|
||||
|
||||
if (!ar9003_paprd_is_done(ah))
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user