diff options
Diffstat (limited to 'drivers/net/wireless/ath9k/xmit.c')
-rw-r--r-- | drivers/net/wireless/ath9k/xmit.c | 78 |
1 files changed, 46 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index e3f376611f85..689bdbf78808 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -64,6 +64,10 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
64 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | 64 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, |
65 | struct list_head *head); | 65 | struct list_head *head); |
66 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); | 66 | 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, | ||
68 | int txok); | ||
69 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | ||
70 | int nbad, int txok, bool update_rc); | ||
67 | 71 | ||
68 | /*********************/ | 72 | /*********************/ |
69 | /* Aggregation logic */ | 73 | /* Aggregation logic */ |
@@ -274,9 +278,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
274 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; | 278 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; |
275 | struct ath_desc *ds = bf_last->bf_desc; | 279 | struct ath_desc *ds = bf_last->bf_desc; |
276 | struct list_head bf_head, bf_pending; | 280 | struct list_head bf_head, bf_pending; |
277 | u16 seq_st = 0; | 281 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; |
278 | u32 ba[WME_BA_BMP_SIZE >> 5]; | 282 | u32 ba[WME_BA_BMP_SIZE >> 5]; |
279 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0; | 283 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; |
284 | bool rc_update = true; | ||
280 | 285 | ||
281 | skb = (struct sk_buff *)bf->bf_mpdu; | 286 | skb = (struct sk_buff *)bf->bf_mpdu; |
282 | hdr = (struct ieee80211_hdr *)skb->data; | 287 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -316,6 +321,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
316 | INIT_LIST_HEAD(&bf_pending); | 321 | INIT_LIST_HEAD(&bf_pending); |
317 | INIT_LIST_HEAD(&bf_head); | 322 | INIT_LIST_HEAD(&bf_head); |
318 | 323 | ||
324 | nbad = ath_tx_num_badfrms(sc, bf, txok); | ||
319 | while (bf) { | 325 | while (bf) { |
320 | txfail = txpending = 0; | 326 | txfail = txpending = 0; |
321 | bf_next = bf->bf_next; | 327 | bf_next = bf->bf_next; |
@@ -323,8 +329,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
323 | if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { | 329 | if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { |
324 | /* transmit completion, subframe is | 330 | /* transmit completion, subframe is |
325 | * acked by block ack */ | 331 | * acked by block ack */ |
332 | acked_cnt++; | ||
326 | } else if (!isaggr && txok) { | 333 | } else if (!isaggr && txok) { |
327 | /* transmit completion */ | 334 | /* transmit completion */ |
335 | acked_cnt++; | ||
328 | } else { | 336 | } else { |
329 | if (!(tid->state & AGGR_CLEANUP) && | 337 | if (!(tid->state & AGGR_CLEANUP) && |
330 | ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { | 338 | ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { |
@@ -335,6 +343,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
335 | bf->bf_state.bf_type |= BUF_XRETRY; | 343 | bf->bf_state.bf_type |= BUF_XRETRY; |
336 | txfail = 1; | 344 | txfail = 1; |
337 | sendbar = 1; | 345 | sendbar = 1; |
346 | txfail_cnt++; | ||
338 | } | 347 | } |
339 | } else { | 348 | } else { |
340 | /* | 349 | /* |
@@ -361,6 +370,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
361 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | 370 | ath_tx_update_baw(sc, tid, bf->bf_seqno); |
362 | spin_unlock_bh(&txq->axq_lock); | 371 | spin_unlock_bh(&txq->axq_lock); |
363 | 372 | ||
373 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { | ||
374 | ath_tx_rc_status(bf, ds, nbad, txok, true); | ||
375 | rc_update = false; | ||
376 | } else { | ||
377 | ath_tx_rc_status(bf, ds, nbad, txok, false); | ||
378 | } | ||
379 | |||
364 | ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); | 380 | ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); |
365 | } else { | 381 | } else { |
366 | /* retry the un-acked ones */ | 382 | /* retry the un-acked ones */ |
@@ -1734,7 +1750,7 @@ exit: | |||
1734 | /*****************/ | 1750 | /*****************/ |
1735 | 1751 | ||
1736 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | 1752 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |
1737 | struct ath_xmit_status *tx_status) | 1753 | int tx_flags) |
1738 | { | 1754 | { |
1739 | struct ieee80211_hw *hw = sc->hw; | 1755 | struct ieee80211_hw *hw = sc->hw; |
1740 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1756 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
@@ -1755,18 +1771,14 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1755 | tx_info->rate_driver_data[0] = NULL; | 1771 | tx_info->rate_driver_data[0] = NULL; |
1756 | } | 1772 | } |
1757 | 1773 | ||
1758 | if (tx_status->flags & ATH_TX_BAR) { | 1774 | if (tx_flags & ATH_TX_BAR) |
1759 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 1775 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
1760 | tx_status->flags &= ~ATH_TX_BAR; | ||
1761 | } | ||
1762 | 1776 | ||
1763 | if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { | 1777 | if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { |
1764 | /* Frame was ACKed */ | 1778 | /* Frame was ACKed */ |
1765 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 1779 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
1766 | } | 1780 | } |
1767 | 1781 | ||
1768 | tx_info->status.rates[0].count = tx_status->retries + 1; | ||
1769 | |||
1770 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1782 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
1771 | padsize = hdrlen & 3; | 1783 | padsize = hdrlen & 3; |
1772 | if (padsize && hdrlen >= 24) { | 1784 | if (padsize && hdrlen >= 24) { |
@@ -1789,29 +1801,22 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1789 | int txok, int sendbar) | 1801 | int txok, int sendbar) |
1790 | { | 1802 | { |
1791 | struct sk_buff *skb = bf->bf_mpdu; | 1803 | struct sk_buff *skb = bf->bf_mpdu; |
1792 | struct ath_xmit_status tx_status; | ||
1793 | unsigned long flags; | 1804 | unsigned long flags; |
1805 | int tx_flags = 0; | ||
1794 | 1806 | ||
1795 | /* | ||
1796 | * Set retry information. | ||
1797 | * NB: Don't use the information in the descriptor, because the frame | ||
1798 | * could be software retried. | ||
1799 | */ | ||
1800 | tx_status.retries = bf->bf_retries; | ||
1801 | tx_status.flags = 0; | ||
1802 | 1807 | ||
1803 | if (sendbar) | 1808 | if (sendbar) |
1804 | tx_status.flags = ATH_TX_BAR; | 1809 | tx_flags = ATH_TX_BAR; |
1805 | 1810 | ||
1806 | if (!txok) { | 1811 | if (!txok) { |
1807 | tx_status.flags |= ATH_TX_ERROR; | 1812 | tx_flags |= ATH_TX_ERROR; |
1808 | 1813 | ||
1809 | if (bf_isxretried(bf)) | 1814 | if (bf_isxretried(bf)) |
1810 | tx_status.flags |= ATH_TX_XRETRY; | 1815 | tx_flags |= ATH_TX_XRETRY; |
1811 | } | 1816 | } |
1812 | 1817 | ||
1813 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); | 1818 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); |
1814 | ath_tx_complete(sc, skb, &tx_status); | 1819 | ath_tx_complete(sc, skb, tx_flags); |
1815 | 1820 | ||
1816 | /* | 1821 | /* |
1817 | * Return the list of ath_buf of this mpdu to free queue | 1822 | * Return the list of ath_buf of this mpdu to free queue |
@@ -1852,27 +1857,40 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | |||
1852 | return nbad; | 1857 | return nbad; |
1853 | } | 1858 | } |
1854 | 1859 | ||
1855 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad) | 1860 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, |
1861 | int nbad, int txok, bool update_rc) | ||
1856 | { | 1862 | { |
1857 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | 1863 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; |
1858 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1864 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1859 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1865 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1860 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | 1866 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); |
1867 | struct ieee80211_hw *hw = tx_info_priv->aphy->hw; | ||
1868 | u8 i, tx_rateindex; | ||
1869 | |||
1870 | if (txok) | ||
1871 | tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; | ||
1861 | 1872 | ||
1862 | tx_info_priv->update_rc = false; | 1873 | tx_rateindex = ds->ds_txstat.ts_rateindex; |
1874 | WARN_ON(tx_rateindex >= hw->max_rates); | ||
1875 | |||
1876 | tx_info_priv->update_rc = update_rc; | ||
1863 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | 1877 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) |
1864 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 1878 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
1865 | 1879 | ||
1866 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | 1880 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && |
1867 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | 1881 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { |
1868 | if (ieee80211_is_data(hdr->frame_control)) { | 1882 | if (ieee80211_is_data(hdr->frame_control)) { |
1869 | memcpy(&tx_info_priv->tx, &ds->ds_txstat, | 1883 | memcpy(&tx_info_priv->tx, &ds->ds_txstat, |
1870 | sizeof(tx_info_priv->tx)); | 1884 | sizeof(tx_info_priv->tx)); |
1871 | tx_info_priv->n_frames = bf->bf_nframes; | 1885 | tx_info_priv->n_frames = bf->bf_nframes; |
1872 | tx_info_priv->n_bad_frames = nbad; | 1886 | tx_info_priv->n_bad_frames = nbad; |
1873 | tx_info_priv->update_rc = true; | ||
1874 | } | 1887 | } |
1875 | } | 1888 | } |
1889 | |||
1890 | for (i = tx_rateindex + 1; i < hw->max_rates; i++) | ||
1891 | tx_info->status.rates[i].count = 0; | ||
1892 | |||
1893 | tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; | ||
1876 | } | 1894 | } |
1877 | 1895 | ||
1878 | static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) | 1896 | static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) |
@@ -1897,7 +1915,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1897 | struct ath_buf *bf, *lastbf, *bf_held = NULL; | 1915 | struct ath_buf *bf, *lastbf, *bf_held = NULL; |
1898 | struct list_head bf_head; | 1916 | struct list_head bf_head; |
1899 | struct ath_desc *ds; | 1917 | struct ath_desc *ds; |
1900 | int txok, nbad = 0; | 1918 | int txok; |
1901 | int status; | 1919 | int status; |
1902 | 1920 | ||
1903 | DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", | 1921 | DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", |
@@ -1991,13 +2009,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1991 | bf->bf_retries = ds->ds_txstat.ts_longretry; | 2009 | bf->bf_retries = ds->ds_txstat.ts_longretry; |
1992 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) | 2010 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) |
1993 | bf->bf_state.bf_type |= BUF_XRETRY; | 2011 | bf->bf_state.bf_type |= BUF_XRETRY; |
1994 | nbad = 0; | 2012 | ath_tx_rc_status(bf, ds, 0, txok, true); |
1995 | } else { | ||
1996 | nbad = ath_tx_num_badfrms(sc, bf, txok); | ||
1997 | } | 2013 | } |
1998 | 2014 | ||
1999 | ath_tx_rc_status(bf, ds, nbad); | ||
2000 | |||
2001 | if (bf_isampdu(bf)) | 2015 | if (bf_isampdu(bf)) |
2002 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); | 2016 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); |
2003 | else | 2017 | else |