diff options
author | Vasanthakumar Thiagarajan <vasanth@atheros.com> | 2009-03-20 05:57:49 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:13:03 -0400 |
commit | 8a92e2ee02dee127d309c73969aeb2a56567c9a0 (patch) | |
tree | 41b86c20c44424b35185319ee55881a22bd16736 /drivers | |
parent | 827b1fb44b7e41377a5498b9d070a11dfae2c283 (diff) |
ath9k: Fix bug in reporting status of tx rate
This patch updates count of every hw tried rate with
appropriate tries before reporting tx status of a frame.
Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath9k/xmit.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index f2877193e958..21e90bca3501 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -67,7 +67,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); | |||
67 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | 67 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, |
68 | int txok); | 68 | int txok); |
69 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | 69 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, |
70 | int nbad, int txok); | 70 | int nbad, int txok, bool update_rc); |
71 | 71 | ||
72 | /*********************/ | 72 | /*********************/ |
73 | /* Aggregation logic */ | 73 | /* Aggregation logic */ |
@@ -370,11 +370,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
370 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | 370 | ath_tx_update_baw(sc, tid, bf->bf_seqno); |
371 | spin_unlock_bh(&txq->axq_lock); | 371 | spin_unlock_bh(&txq->axq_lock); |
372 | 372 | ||
373 | if (rc_update) | 373 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { |
374 | if (acked_cnt == 1 || txfail_cnt == 1) { | 374 | ath_tx_rc_status(bf, ds, nbad, txok, true); |
375 | ath_tx_rc_status(bf, ds, nbad, txok); | 375 | rc_update = false; |
376 | rc_update = false; | 376 | } else { |
377 | } | 377 | ath_tx_rc_status(bf, ds, nbad, txok, false); |
378 | } | ||
379 | |||
378 | ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); | 380 | ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); |
379 | } else { | 381 | } else { |
380 | /* retry the un-acked ones */ | 382 | /* retry the un-acked ones */ |
@@ -1779,8 +1781,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1779 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 1781 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
1780 | } | 1782 | } |
1781 | 1783 | ||
1782 | tx_info->status.rates[0].count = tx_status->retries + 1; | ||
1783 | |||
1784 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1784 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
1785 | padsize = hdrlen & 3; | 1785 | padsize = hdrlen & 3; |
1786 | if (padsize && hdrlen >= 24) { | 1786 | if (padsize && hdrlen >= 24) { |
@@ -1867,30 +1867,39 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | |||
1867 | } | 1867 | } |
1868 | 1868 | ||
1869 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | 1869 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, |
1870 | int nbad, int txok) | 1870 | int nbad, int txok, bool update_rc) |
1871 | { | 1871 | { |
1872 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | 1872 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; |
1873 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1873 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1874 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1874 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1875 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | 1875 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); |
1876 | struct ieee80211_hw *hw = tx_info_priv->aphy->hw; | ||
1877 | u8 i, tx_rateindex; | ||
1876 | 1878 | ||
1877 | if (txok) | 1879 | if (txok) |
1878 | tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; | 1880 | tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; |
1879 | 1881 | ||
1880 | tx_info_priv->update_rc = false; | 1882 | tx_rateindex = ds->ds_txstat.ts_rateindex; |
1883 | WARN_ON(tx_rateindex >= hw->max_rates); | ||
1884 | |||
1885 | tx_info_priv->update_rc = update_rc; | ||
1881 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | 1886 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) |
1882 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 1887 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
1883 | 1888 | ||
1884 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | 1889 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && |
1885 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | 1890 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { |
1886 | if (ieee80211_is_data(hdr->frame_control)) { | 1891 | if (ieee80211_is_data(hdr->frame_control)) { |
1887 | memcpy(&tx_info_priv->tx, &ds->ds_txstat, | 1892 | memcpy(&tx_info_priv->tx, &ds->ds_txstat, |
1888 | sizeof(tx_info_priv->tx)); | 1893 | sizeof(tx_info_priv->tx)); |
1889 | tx_info_priv->n_frames = bf->bf_nframes; | 1894 | tx_info_priv->n_frames = bf->bf_nframes; |
1890 | tx_info_priv->n_bad_frames = nbad; | 1895 | tx_info_priv->n_bad_frames = nbad; |
1891 | tx_info_priv->update_rc = true; | ||
1892 | } | 1896 | } |
1893 | } | 1897 | } |
1898 | |||
1899 | for (i = tx_rateindex + 1; i < hw->max_rates; i++) | ||
1900 | tx_info->status.rates[i].count = 0; | ||
1901 | |||
1902 | tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; | ||
1894 | } | 1903 | } |
1895 | 1904 | ||
1896 | static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) | 1905 | static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) |
@@ -2009,7 +2018,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2009 | bf->bf_retries = ds->ds_txstat.ts_longretry; | 2018 | bf->bf_retries = ds->ds_txstat.ts_longretry; |
2010 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) | 2019 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) |
2011 | bf->bf_state.bf_type |= BUF_XRETRY; | 2020 | bf->bf_state.bf_type |= BUF_XRETRY; |
2012 | ath_tx_rc_status(bf, ds, 0, txok); | 2021 | ath_tx_rc_status(bf, ds, 0, txok, true); |
2013 | } | 2022 | } |
2014 | 2023 | ||
2015 | if (bf_isampdu(bf)) | 2024 | if (bf_isampdu(bf)) |