Skip to content

Commit

Permalink
ath9k: fix PA predistortion thermal measurement handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Felix Fietkau authored and John W. Linville committed Dec 13, 2010
1 parent caabf2b commit 7607cbe
Showing 1 changed file with 44 additions and 30 deletions.
74 changes: 44 additions & 30 deletions drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,25 +320,55 @@ 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);
struct ieee80211_hw *hw = sc->hw;
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;
Expand All @@ -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;
Expand All @@ -359,40 +387,26 @@ 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++) {
if (!(common->tx_chainmask & BIT(chain)))
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;
}
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;

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 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;
Expand Down

0 comments on commit 7607cbe

Please sign in to comment.