diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/xmit.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 137 |
1 files changed, 73 insertions, 64 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 89a64411b82e..eab0fcb7ded6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -157,6 +157,13 @@ static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) | |||
157 | seqno << IEEE80211_SEQ_SEQ_SHIFT); | 157 | seqno << IEEE80211_SEQ_SEQ_SHIFT); |
158 | } | 158 | } |
159 | 159 | ||
160 | static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta, | ||
161 | struct ath_buf *bf) | ||
162 | { | ||
163 | ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates, | ||
164 | ARRAY_SIZE(bf->rates)); | ||
165 | } | ||
166 | |||
160 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 167 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
161 | { | 168 | { |
162 | struct ath_txq *txq = tid->ac->txq; | 169 | struct ath_txq *txq = tid->ac->txq; |
@@ -189,6 +196,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
189 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | 196 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
190 | sendbar = true; | 197 | sendbar = true; |
191 | } else { | 198 | } else { |
199 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | ||
192 | ath_tx_send_normal(sc, txq, NULL, skb); | 200 | ath_tx_send_normal(sc, txq, NULL, skb); |
193 | } | 201 | } |
194 | } | 202 | } |
@@ -407,7 +415,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
407 | 415 | ||
408 | tx_info = IEEE80211_SKB_CB(skb); | 416 | tx_info = IEEE80211_SKB_CB(skb); |
409 | 417 | ||
410 | memcpy(rates, tx_info->control.rates, sizeof(rates)); | 418 | memcpy(rates, bf->rates, sizeof(rates)); |
411 | 419 | ||
412 | retries = ts->ts_longretry + 1; | 420 | retries = ts->ts_longretry + 1; |
413 | for (i = 0; i < ts->ts_rateindex; i++) | 421 | for (i = 0; i < ts->ts_rateindex; i++) |
@@ -516,8 +524,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
516 | * not a holding desc. | 524 | * not a holding desc. |
517 | */ | 525 | */ |
518 | INIT_LIST_HEAD(&bf_head); | 526 | INIT_LIST_HEAD(&bf_head); |
519 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) || | 527 | if (bf_next != NULL || !bf_last->bf_stale) |
520 | bf_next != NULL || !bf_last->bf_stale) | ||
521 | list_move_tail(&bf->list, &bf_head); | 528 | list_move_tail(&bf->list, &bf_head); |
522 | 529 | ||
523 | if (!txpending || (tid->state & AGGR_CLEANUP)) { | 530 | if (!txpending || (tid->state & AGGR_CLEANUP)) { |
@@ -537,8 +544,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
537 | !txfail); | 544 | !txfail); |
538 | } else { | 545 | } else { |
539 | /* retry the un-acked ones */ | 546 | /* retry the un-acked ones */ |
540 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && | 547 | if (bf->bf_next == NULL && bf_last->bf_stale) { |
541 | bf->bf_next == NULL && bf_last->bf_stale) { | ||
542 | struct ath_buf *tbf; | 548 | struct ath_buf *tbf; |
543 | 549 | ||
544 | tbf = ath_clone_txbuf(sc, bf_last); | 550 | tbf = ath_clone_txbuf(sc, bf_last); |
@@ -738,8 +744,6 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
738 | bool first_subfrm) | 744 | bool first_subfrm) |
739 | { | 745 | { |
740 | #define FIRST_DESC_NDELIMS 60 | 746 | #define FIRST_DESC_NDELIMS 60 |
741 | struct sk_buff *skb = bf->bf_mpdu; | ||
742 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
743 | u32 nsymbits, nsymbols; | 747 | u32 nsymbits, nsymbols; |
744 | u16 minlen; | 748 | u16 minlen; |
745 | u8 flags, rix; | 749 | u8 flags, rix; |
@@ -780,8 +784,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
780 | if (tid->an->mpdudensity == 0) | 784 | if (tid->an->mpdudensity == 0) |
781 | return ndelim; | 785 | return ndelim; |
782 | 786 | ||
783 | rix = tx_info->control.rates[0].idx; | 787 | rix = bf->rates[0].idx; |
784 | flags = tx_info->control.rates[0].flags; | 788 | flags = bf->rates[0].flags; |
785 | width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; | 789 | width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; |
786 | half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; | 790 | half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; |
787 | 791 | ||
@@ -860,6 +864,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
860 | bf_first = bf; | 864 | bf_first = bf; |
861 | 865 | ||
862 | if (!rl) { | 866 | if (!rl) { |
867 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | ||
863 | aggr_limit = ath_lookup_rate(sc, bf, tid); | 868 | aggr_limit = ath_lookup_rate(sc, bf, tid); |
864 | rl = 1; | 869 | rl = 1; |
865 | } | 870 | } |
@@ -1000,14 +1005,14 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
1000 | 1005 | ||
1001 | skb = bf->bf_mpdu; | 1006 | skb = bf->bf_mpdu; |
1002 | tx_info = IEEE80211_SKB_CB(skb); | 1007 | tx_info = IEEE80211_SKB_CB(skb); |
1003 | rates = tx_info->control.rates; | 1008 | rates = bf->rates; |
1004 | hdr = (struct ieee80211_hdr *)skb->data; | 1009 | hdr = (struct ieee80211_hdr *)skb->data; |
1005 | 1010 | ||
1006 | /* set dur_update_en for l-sig computation except for PS-Poll frames */ | 1011 | /* set dur_update_en for l-sig computation except for PS-Poll frames */ |
1007 | info->dur_update = !ieee80211_is_pspoll(hdr->frame_control); | 1012 | info->dur_update = !ieee80211_is_pspoll(hdr->frame_control); |
1008 | info->rtscts_rate = fi->rtscts_rate; | 1013 | info->rtscts_rate = fi->rtscts_rate; |
1009 | 1014 | ||
1010 | for (i = 0; i < 4; i++) { | 1015 | for (i = 0; i < ARRAY_SIZE(bf->rates); i++) { |
1011 | bool is_40, is_sgi, is_sp; | 1016 | bool is_40, is_sgi, is_sp; |
1012 | int phy; | 1017 | int phy; |
1013 | 1018 | ||
@@ -1745,6 +1750,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
1745 | return; | 1750 | return; |
1746 | } | 1751 | } |
1747 | 1752 | ||
1753 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | ||
1748 | bf->bf_state.bf_type = BUF_AMPDU; | 1754 | bf->bf_state.bf_type = BUF_AMPDU; |
1749 | INIT_LIST_HEAD(&bf_head); | 1755 | INIT_LIST_HEAD(&bf_head); |
1750 | list_add(&bf->list, &bf_head); | 1756 | list_add(&bf->list, &bf_head); |
@@ -1894,49 +1900,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, | |||
1894 | return bf; | 1900 | return bf; |
1895 | } | 1901 | } |
1896 | 1902 | ||
1897 | /* FIXME: tx power */ | ||
1898 | static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, | ||
1899 | struct ath_tx_control *txctl) | ||
1900 | { | ||
1901 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1902 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1903 | struct ath_atx_tid *tid = NULL; | ||
1904 | struct ath_buf *bf; | ||
1905 | u8 tidno; | ||
1906 | |||
1907 | if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) { | ||
1908 | tidno = ieee80211_get_qos_ctl(hdr)[0] & | ||
1909 | IEEE80211_QOS_CTL_TID_MASK; | ||
1910 | tid = ATH_AN_2_TID(txctl->an, tidno); | ||
1911 | |||
1912 | WARN_ON(tid->ac->txq != txctl->txq); | ||
1913 | } | ||
1914 | |||
1915 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) { | ||
1916 | /* | ||
1917 | * Try aggregation if it's a unicast data frame | ||
1918 | * and the destination is HT capable. | ||
1919 | */ | ||
1920 | ath_tx_send_ampdu(sc, tid, skb, txctl); | ||
1921 | } else { | ||
1922 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); | ||
1923 | if (!bf) { | ||
1924 | if (txctl->paprd) | ||
1925 | dev_kfree_skb_any(skb); | ||
1926 | else | ||
1927 | ieee80211_free_txskb(sc->hw, skb); | ||
1928 | return; | ||
1929 | } | ||
1930 | |||
1931 | bf->bf_state.bfs_paprd = txctl->paprd; | ||
1932 | |||
1933 | if (txctl->paprd) | ||
1934 | bf->bf_state.bfs_paprd_timestamp = jiffies; | ||
1935 | |||
1936 | ath_tx_send_normal(sc, txctl->txq, tid, skb); | ||
1937 | } | ||
1938 | } | ||
1939 | |||
1940 | /* Upon failure caller should free skb */ | 1903 | /* Upon failure caller should free skb */ |
1941 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | 1904 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, |
1942 | struct ath_tx_control *txctl) | 1905 | struct ath_tx_control *txctl) |
@@ -1947,8 +1910,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1947 | struct ieee80211_vif *vif = info->control.vif; | 1910 | struct ieee80211_vif *vif = info->control.vif; |
1948 | struct ath_softc *sc = hw->priv; | 1911 | struct ath_softc *sc = hw->priv; |
1949 | struct ath_txq *txq = txctl->txq; | 1912 | struct ath_txq *txq = txctl->txq; |
1913 | struct ath_atx_tid *tid = NULL; | ||
1914 | struct ath_buf *bf; | ||
1950 | int padpos, padsize; | 1915 | int padpos, padsize; |
1951 | int frmlen = skb->len + FCS_LEN; | 1916 | int frmlen = skb->len + FCS_LEN; |
1917 | u8 tidno; | ||
1952 | int q; | 1918 | int q; |
1953 | 1919 | ||
1954 | /* NOTE: sta can be NULL according to net/mac80211.h */ | 1920 | /* NOTE: sta can be NULL according to net/mac80211.h */ |
@@ -1971,7 +1937,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1971 | } | 1937 | } |
1972 | 1938 | ||
1973 | /* Add the padding after the header if this is not already done */ | 1939 | /* Add the padding after the header if this is not already done */ |
1974 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 1940 | padpos = ieee80211_hdrlen(hdr->frame_control); |
1975 | padsize = padpos & 3; | 1941 | padsize = padpos & 3; |
1976 | if (padsize && skb->len > padpos) { | 1942 | if (padsize && skb->len > padpos) { |
1977 | if (skb_headroom(skb) < padsize) | 1943 | if (skb_headroom(skb) < padsize) |
@@ -2004,8 +1970,41 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2004 | txq->stopped = true; | 1970 | txq->stopped = true; |
2005 | } | 1971 | } |
2006 | 1972 | ||
2007 | ath_tx_start_dma(sc, skb, txctl); | 1973 | if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) { |
1974 | tidno = ieee80211_get_qos_ctl(hdr)[0] & | ||
1975 | IEEE80211_QOS_CTL_TID_MASK; | ||
1976 | tid = ATH_AN_2_TID(txctl->an, tidno); | ||
1977 | |||
1978 | WARN_ON(tid->ac->txq != txctl->txq); | ||
1979 | } | ||
1980 | |||
1981 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) { | ||
1982 | /* | ||
1983 | * Try aggregation if it's a unicast data frame | ||
1984 | * and the destination is HT capable. | ||
1985 | */ | ||
1986 | ath_tx_send_ampdu(sc, tid, skb, txctl); | ||
1987 | goto out; | ||
1988 | } | ||
2008 | 1989 | ||
1990 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); | ||
1991 | if (!bf) { | ||
1992 | if (txctl->paprd) | ||
1993 | dev_kfree_skb_any(skb); | ||
1994 | else | ||
1995 | ieee80211_free_txskb(sc->hw, skb); | ||
1996 | goto out; | ||
1997 | } | ||
1998 | |||
1999 | bf->bf_state.bfs_paprd = txctl->paprd; | ||
2000 | |||
2001 | if (txctl->paprd) | ||
2002 | bf->bf_state.bfs_paprd_timestamp = jiffies; | ||
2003 | |||
2004 | ath_set_rates(vif, sta, bf); | ||
2005 | ath_tx_send_normal(sc, txctl->txq, tid, skb); | ||
2006 | |||
2007 | out: | ||
2009 | ath_txq_unlock(sc, txq); | 2008 | ath_txq_unlock(sc, txq); |
2010 | 2009 | ||
2011 | return 0; | 2010 | return 0; |
@@ -2033,7 +2032,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
2033 | /* Frame was ACKed */ | 2032 | /* Frame was ACKed */ |
2034 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 2033 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
2035 | 2034 | ||
2036 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 2035 | padpos = ieee80211_hdrlen(hdr->frame_control); |
2037 | padsize = padpos & 3; | 2036 | padsize = padpos & 3; |
2038 | if (padsize && skb->len>padpos+padsize) { | 2037 | if (padsize && skb->len>padpos+padsize) { |
2039 | /* | 2038 | /* |
@@ -2264,6 +2263,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2264 | struct ath_txq *txq; | 2263 | struct ath_txq *txq; |
2265 | struct ath_buf *bf, *lastbf; | 2264 | struct ath_buf *bf, *lastbf; |
2266 | struct list_head bf_head; | 2265 | struct list_head bf_head; |
2266 | struct list_head *fifo_list; | ||
2267 | int status; | 2267 | int status; |
2268 | 2268 | ||
2269 | for (;;) { | 2269 | for (;;) { |
@@ -2291,20 +2291,24 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2291 | 2291 | ||
2292 | TX_STAT_INC(txq->axq_qnum, txprocdesc); | 2292 | TX_STAT_INC(txq->axq_qnum, txprocdesc); |
2293 | 2293 | ||
2294 | if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { | 2294 | fifo_list = &txq->txq_fifo[txq->txq_tailidx]; |
2295 | if (list_empty(fifo_list)) { | ||
2295 | ath_txq_unlock(sc, txq); | 2296 | ath_txq_unlock(sc, txq); |
2296 | return; | 2297 | return; |
2297 | } | 2298 | } |
2298 | 2299 | ||
2299 | bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx], | 2300 | bf = list_first_entry(fifo_list, struct ath_buf, list); |
2300 | struct ath_buf, list); | 2301 | if (bf->bf_stale) { |
2302 | list_del(&bf->list); | ||
2303 | ath_tx_return_buffer(sc, bf); | ||
2304 | bf = list_first_entry(fifo_list, struct ath_buf, list); | ||
2305 | } | ||
2306 | |||
2301 | lastbf = bf->bf_lastbf; | 2307 | lastbf = bf->bf_lastbf; |
2302 | 2308 | ||
2303 | INIT_LIST_HEAD(&bf_head); | 2309 | INIT_LIST_HEAD(&bf_head); |
2304 | list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx], | 2310 | if (list_is_last(&lastbf->list, fifo_list)) { |
2305 | &lastbf->list); | 2311 | list_splice_tail_init(fifo_list, &bf_head); |
2306 | |||
2307 | if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { | ||
2308 | INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); | 2312 | INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); |
2309 | 2313 | ||
2310 | if (!list_empty(&txq->axq_q)) { | 2314 | if (!list_empty(&txq->axq_q)) { |
@@ -2315,6 +2319,11 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2315 | list_splice_tail_init(&txq->axq_q, &bf_q); | 2319 | list_splice_tail_init(&txq->axq_q, &bf_q); |
2316 | ath_tx_txqaddbuf(sc, txq, &bf_q, true); | 2320 | ath_tx_txqaddbuf(sc, txq, &bf_q, true); |
2317 | } | 2321 | } |
2322 | } else { | ||
2323 | lastbf->bf_stale = true; | ||
2324 | if (bf != lastbf) | ||
2325 | list_cut_position(&bf_head, fifo_list, | ||
2326 | lastbf->list.prev); | ||
2318 | } | 2327 | } |
2319 | 2328 | ||
2320 | ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head); | 2329 | ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head); |