diff options
author | Felix Fietkau <nbd@openwrt.org> | 2008-10-05 18:05:48 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-10-06 18:14:57 -0400 |
commit | 2f7fe87034298d94301315ba4bb65c7284c709d0 (patch) | |
tree | e8583ae3686a243405b77d4ef6498bc4199ca3a2 /drivers/net/wireless/ath5k/base.c | |
parent | 870abdf67170daa9f1022e55a35c469239fcc74c (diff) |
ath5k: implement multi-rate retry support, fix tx status reporting
Clean up the tx status reporting, fix retry counters (short retries are
virtual collisions, not actual retries). Implement multi-rate retry
support.
This also fixes strong throughput fluctuations with rc80211_pid
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k/base.c')
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 47be49acf55..9b95c4049b3 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -541,6 +541,12 @@ ath5k_pci_probe(struct pci_dev *pdev, goto err_irq; } + /* set up multi-rate retry capabilities */ + if (sc->ah->ah_version == AR5K_AR5212) { + hw->max_altrates = 3; + hw->max_altrate_tries = 11; + } + /* Finish private driver data initialization */ ret = ath5k_attach(pdev, hw); if (ret) @@ -1173,7 +1179,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) struct sk_buff *skb = bf->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID; - int ret; + struct ieee80211_rate *rate; + unsigned int mrr_rate[3], mrr_tries[3]; + int i, ret; flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; @@ -1198,6 +1206,22 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) if (ret) goto err_unmap; + memset(mrr_rate, 0, sizeof(mrr_rate)); + memset(mrr_tries, 0, sizeof(mrr_tries)); + for (i = 0; i < 3; i++) { + rate = ieee80211_get_alt_retry_rate(sc->hw, info, i); + if (!rate) + break; + + mrr_rate[i] = rate->hw_value; + mrr_tries[i] = info->control.retries[i].limit; + } + + ah->ah_setup_mrr_tx_desc(ah, ds, + mrr_rate[0], mrr_tries[0], + mrr_rate[1], mrr_tries[1], + mrr_rate[2], mrr_tries[2]); + ds->ds_link = 0; ds->ds_data = bf->skbaddr; @@ -1814,7 +1838,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) struct ath5k_desc *ds; struct sk_buff *skb; struct ieee80211_tx_info *info; - int ret; + int i, ret; spin_lock(&txq->lock); list_for_each_entry_safe(bf, bf0, &txq->q, list) { @@ -1836,7 +1860,25 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); - info->status.retry_count = ts.ts_shortretry + ts.ts_longretry / 6; + memset(&info->status, 0, sizeof(info->status)); + info->tx_rate_idx = ath5k_hw_to_driver_rix(sc, + ts.ts_rate[ts.ts_final_idx]); + info->status.retry_count = ts.ts_longretry; + + for (i = 0; i < 4; i++) { + struct ieee80211_tx_altrate *r = + &info->status.retries[i]; + + if (ts.ts_rate[i]) { + r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); + r->limit = ts.ts_retry[i]; + } else { + r->rate_idx = -1; + r->limit = 0; + } + } + + info->status.excessive_retries = 0; if (unlikely(ts.ts_status)) { sc->ll_stats.dot11ACKFailureCount++; if (ts.ts_status & AR5K_TXERR_XRETRY) |