diff options
Diffstat (limited to 'package/mac80211/patches/250-ath5k_mrr.patch')
-rw-r--r-- | package/mac80211/patches/250-ath5k_mrr.patch | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/package/mac80211/patches/250-ath5k_mrr.patch b/package/mac80211/patches/250-ath5k_mrr.patch new file mode 100644 index 0000000..ff15fd4 --- /dev/null +++ b/package/mac80211/patches/250-ath5k_mrr.patch @@ -0,0 +1,208 @@ +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> + +--- a/drivers/net/wireless/ath5k/base.c ++++ b/drivers/net/wireless/ath5k/base.c +@@ -530,6 +530,12 @@ + 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) +@@ -1149,7 +1155,9 @@ + 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; + +@@ -1174,6 +1182,22 @@ + 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; + +@@ -1790,7 +1814,7 @@ + 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) { +@@ -1812,7 +1836,25 @@ + 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) +--- a/drivers/net/wireless/ath5k/desc.c ++++ b/drivers/net/wireless/ath5k/desc.c +@@ -318,6 +318,15 @@ + return 0; + } + ++/* no mrr support for cards older than 5212 */ ++static int ++ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc, ++ unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, ++ u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) ++{ ++ return 0; ++} ++ + /* + * Proccess the tx status descriptor on 5210/5211 + */ +@@ -352,8 +361,10 @@ + AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); + ts->ts_antenna = 1; + ts->ts_status = 0; +- ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0, ++ ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, + AR5K_2W_TX_DESC_CTL0_XMIT_RATE); ++ ts->ts_retry[0] = ts->ts_longretry; ++ ts->ts_final_idx = 0; + + if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { + if (tx_status->tx_status_0 & +@@ -405,29 +416,43 @@ + AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; + ts->ts_status = 0; + +- switch (AR5K_REG_MS(tx_status->tx_status_1, +- AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { +- case 0: +- ts->ts_rate = tx_ctl->tx_control_3 & +- AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; +- break; ++ ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, ++ AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX); ++ ++ /* The longretry counter has the number of un-acked retries ++ * for the final rate. To get the total number of retries ++ * we have to add the retry counters for the other rates ++ * as well ++ */ ++ ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; ++ switch (ts->ts_final_idx) { ++ case 3: ++ ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, ++ AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); ++ ++ ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, ++ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); ++ ts->ts_longretry += ts->ts_retry[2]; ++ /* fall through */ ++ case 2: ++ ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, ++ AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); ++ ++ ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, ++ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); ++ ts->ts_longretry += ts->ts_retry[1]; ++ /* fall through */ + case 1: +- ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, ++ ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, + AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); +- ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, ++ ++ ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, + AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); +- break; +- case 2: +- ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, +- AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); +- ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, +- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); +- break; +- case 3: +- ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, +- AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); +- ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, +- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3); ++ ts->ts_longretry += ts->ts_retry[0]; ++ /* fall through */ ++ case 0: ++ ts->ts_rate[0] = tx_ctl->tx_control_3 & ++ AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; + break; + } + +@@ -653,7 +678,7 @@ + } else { + ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; + ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; +- ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; ++ ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr; + ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; + } + +--- a/drivers/net/wireless/ath5k/ath5k.h ++++ b/drivers/net/wireless/ath5k/ath5k.h +@@ -418,7 +418,9 @@ + u16 ts_seqnum; + u16 ts_tstamp; + u8 ts_status; +- u8 ts_rate; ++ u8 ts_rate[4]; ++ u8 ts_retry[4]; ++ u8 ts_final_idx; + s8 ts_rssi; + u8 ts_shortretry; + u8 ts_longretry; |