aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2008-10-05 12:05:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-06 18:14:57 -0400
commit2f7fe87034298d94301315ba4bb65c7284c709d0 (patch)
treee8583ae3686a243405b77d4ef6498bc4199ca3a2 /drivers/net/wireless/ath5k
parent870abdf67170daa9f1022e55a35c469239fcc74c (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')
-rw-r--r--drivers/net/wireless/ath5k/ath5k.h4
-rw-r--r--drivers/net/wireless/ath5k/base.c48
-rw-r--r--drivers/net/wireless/ath5k/desc.c69
3 files changed, 95 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index 7134c40d6a69..53ea439aff48 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -431,7 +431,9 @@ struct ath5k_tx_status {
431 u16 ts_seqnum; 431 u16 ts_seqnum;
432 u16 ts_tstamp; 432 u16 ts_tstamp;
433 u8 ts_status; 433 u8 ts_status;
434 u8 ts_rate; 434 u8 ts_rate[4];
435 u8 ts_retry[4];
436 u8 ts_final_idx;
435 s8 ts_rssi; 437 s8 ts_rssi;
436 u8 ts_shortretry; 438 u8 ts_shortretry;
437 u8 ts_longretry; 439 u8 ts_longretry;
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 47be49acf55e..9b95c4049b31 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,
541 goto err_irq; 541 goto err_irq;
542 } 542 }
543 543
544 /* set up multi-rate retry capabilities */
545 if (sc->ah->ah_version == AR5K_AR5212) {
546 hw->max_altrates = 3;
547 hw->max_altrate_tries = 11;
548 }
549
544 /* Finish private driver data initialization */ 550 /* Finish private driver data initialization */
545 ret = ath5k_attach(pdev, hw); 551 ret = ath5k_attach(pdev, hw);
546 if (ret) 552 if (ret)
@@ -1173,7 +1179,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
1173 struct sk_buff *skb = bf->skb; 1179 struct sk_buff *skb = bf->skb;
1174 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1180 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1175 unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID; 1181 unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
1176 int ret; 1182 struct ieee80211_rate *rate;
1183 unsigned int mrr_rate[3], mrr_tries[3];
1184 int i, ret;
1177 1185
1178 flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; 1186 flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
1179 1187
@@ -1198,6 +1206,22 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
1198 if (ret) 1206 if (ret)
1199 goto err_unmap; 1207 goto err_unmap;
1200 1208
1209 memset(mrr_rate, 0, sizeof(mrr_rate));
1210 memset(mrr_tries, 0, sizeof(mrr_tries));
1211 for (i = 0; i < 3; i++) {
1212 rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
1213 if (!rate)
1214 break;
1215
1216 mrr_rate[i] = rate->hw_value;
1217 mrr_tries[i] = info->control.retries[i].limit;
1218 }
1219
1220 ah->ah_setup_mrr_tx_desc(ah, ds,
1221 mrr_rate[0], mrr_tries[0],
1222 mrr_rate[1], mrr_tries[1],
1223 mrr_rate[2], mrr_tries[2]);
1224
1201 ds->ds_link = 0; 1225 ds->ds_link = 0;
1202 ds->ds_data = bf->skbaddr; 1226 ds->ds_data = bf->skbaddr;
1203 1227
@@ -1814,7 +1838,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
1814 struct ath5k_desc *ds; 1838 struct ath5k_desc *ds;
1815 struct sk_buff *skb; 1839 struct sk_buff *skb;
1816 struct ieee80211_tx_info *info; 1840 struct ieee80211_tx_info *info;
1817 int ret; 1841 int i, ret;
1818 1842
1819 spin_lock(&txq->lock); 1843 spin_lock(&txq->lock);
1820 list_for_each_entry_safe(bf, bf0, &txq->q, list) { 1844 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)
1836 pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, 1860 pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
1837 PCI_DMA_TODEVICE); 1861 PCI_DMA_TODEVICE);
1838 1862
1839 info->status.retry_count = ts.ts_shortretry + ts.ts_longretry / 6; 1863 memset(&info->status, 0, sizeof(info->status));
1864 info->tx_rate_idx = ath5k_hw_to_driver_rix(sc,
1865 ts.ts_rate[ts.ts_final_idx]);
1866 info->status.retry_count = ts.ts_longretry;
1867
1868 for (i = 0; i < 4; i++) {
1869 struct ieee80211_tx_altrate *r =
1870 &info->status.retries[i];
1871
1872 if (ts.ts_rate[i]) {
1873 r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
1874 r->limit = ts.ts_retry[i];
1875 } else {
1876 r->rate_idx = -1;
1877 r->limit = 0;
1878 }
1879 }
1880
1881 info->status.excessive_retries = 0;
1840 if (unlikely(ts.ts_status)) { 1882 if (unlikely(ts.ts_status)) {
1841 sc->ll_stats.dot11ACKFailureCount++; 1883 sc->ll_stats.dot11ACKFailureCount++;
1842 if (ts.ts_status & AR5K_TXERR_XRETRY) 1884 if (ts.ts_status & AR5K_TXERR_XRETRY)
diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c
index d45b90a6e06c..dd1374052ba9 100644
--- a/drivers/net/wireless/ath5k/desc.c
+++ b/drivers/net/wireless/ath5k/desc.c
@@ -318,6 +318,15 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
318 return 0; 318 return 0;
319} 319}
320 320
321/* no mrr support for cards older than 5212 */
322static int
323ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc,
324 unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
325 u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
326{
327 return 0;
328}
329
321/* 330/*
322 * Proccess the tx status descriptor on 5210/5211 331 * Proccess the tx status descriptor on 5210/5211
323 */ 332 */
@@ -352,8 +361,10 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
352 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); 361 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
353 ts->ts_antenna = 1; 362 ts->ts_antenna = 1;
354 ts->ts_status = 0; 363 ts->ts_status = 0;
355 ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0, 364 ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
356 AR5K_2W_TX_DESC_CTL0_XMIT_RATE); 365 AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
366 ts->ts_retry[0] = ts->ts_longretry;
367 ts->ts_final_idx = 0;
357 368
358 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { 369 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
359 if (tx_status->tx_status_0 & 370 if (tx_status->tx_status_0 &
@@ -405,29 +416,43 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
405 AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; 416 AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
406 ts->ts_status = 0; 417 ts->ts_status = 0;
407 418
408 switch (AR5K_REG_MS(tx_status->tx_status_1, 419 ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
409 AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { 420 AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
410 case 0: 421
411 ts->ts_rate = tx_ctl->tx_control_3 & 422 /* The longretry counter has the number of un-acked retries
412 AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; 423 * for the final rate. To get the total number of retries
413 break; 424 * we have to add the retry counters for the other rates
425 * as well
426 */
427 ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
428 switch (ts->ts_final_idx) {
429 case 3:
430 ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
431 AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
432
433 ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
434 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
435 ts->ts_longretry += ts->ts_retry[2];
436 /* fall through */
437 case 2:
438 ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
439 AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
440
441 ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
442 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
443 ts->ts_longretry += ts->ts_retry[1];
444 /* fall through */
414 case 1: 445 case 1:
415 ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, 446 ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
416 AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); 447 AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
417 ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, 448
449 ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
418 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); 450 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
419 break; 451 ts->ts_longretry += ts->ts_retry[0];
420 case 2: 452 /* fall through */
421 ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, 453 case 0:
422 AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); 454 ts->ts_rate[0] = tx_ctl->tx_control_3 &
423 ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, 455 AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
424 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
425 break;
426 case 3:
427 ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
428 AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
429 ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
430 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
431 break; 456 break;
432 } 457 }
433 458
@@ -653,7 +678,7 @@ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
653 } else { 678 } else {
654 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; 679 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
655 ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; 680 ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
656 ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; 681 ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr;
657 ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; 682 ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
658 } 683 }
659 684