diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2008-11-17 22:39:30 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-26 09:47:32 -0500 |
commit | c428839008f6638317a0db102d4e65d631c288a6 (patch) | |
tree | 64decdccf35485d1a40ec54bf00c379cd1f0fa01 /drivers/net/wireless/ath9k/xmit.c | |
parent | 2c5a744d43a6a08666930906742fbe704739ba6f (diff) |
ath9k: Move TX completion routine to xmit.c
Also, use a helper function to setup RC status data
when processing completed TX descriptors.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k/xmit.c')
-rw-r--r-- | drivers/net/wireless/ath9k/xmit.c | 88 |
1 files changed, 56 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 93317ce9ac8a..4c9a03ed8382 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -102,6 +102,37 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
102 | ath9k_hw_txstart(ah, txq->axq_qnum); | 102 | ath9k_hw_txstart(ah, txq->axq_qnum); |
103 | } | 103 | } |
104 | 104 | ||
105 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | ||
106 | struct ath_xmit_status *tx_status) | ||
107 | { | ||
108 | struct ieee80211_hw *hw = sc->hw; | ||
109 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
110 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
111 | |||
112 | DPRINTF(sc, ATH_DBG_XMIT, | ||
113 | "%s: TX complete: skb: %p\n", __func__, skb); | ||
114 | |||
115 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || | ||
116 | tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | ||
117 | kfree(tx_info_priv); | ||
118 | tx_info->rate_driver_data[0] = NULL; | ||
119 | } | ||
120 | |||
121 | if (tx_status->flags & ATH_TX_BAR) { | ||
122 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
123 | tx_status->flags &= ~ATH_TX_BAR; | ||
124 | } | ||
125 | |||
126 | if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { | ||
127 | /* Frame was ACKed */ | ||
128 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | ||
129 | } | ||
130 | |||
131 | tx_info->status.rates[0].count = tx_status->retries + 1; | ||
132 | |||
133 | ieee80211_tx_status(hw, skb); | ||
134 | } | ||
135 | |||
105 | /* Check if it's okay to send out aggregates */ | 136 | /* Check if it's okay to send out aggregates */ |
106 | 137 | ||
107 | static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno) | 138 | static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno) |
@@ -913,18 +944,35 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
913 | return; | 944 | return; |
914 | } | 945 | } |
915 | 946 | ||
947 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad) | ||
948 | { | ||
949 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | ||
950 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
951 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
952 | |||
953 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | ||
954 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
955 | |||
956 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | ||
957 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | ||
958 | if (bf_isdata(bf)) { | ||
959 | memcpy(&tx_info_priv->tx, &ds->ds_txstat, | ||
960 | sizeof(tx_info_priv->tx)); | ||
961 | tx_info_priv->n_frames = bf->bf_nframes; | ||
962 | tx_info_priv->n_bad_frames = nbad; | ||
963 | } | ||
964 | } | ||
965 | } | ||
966 | |||
916 | /* Process completed xmit descriptors from the specified queue */ | 967 | /* Process completed xmit descriptors from the specified queue */ |
917 | 968 | ||
918 | static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | 969 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) |
919 | { | 970 | { |
920 | struct ath_hal *ah = sc->sc_ah; | 971 | struct ath_hal *ah = sc->sc_ah; |
921 | struct ath_buf *bf, *lastbf, *bf_held = NULL; | 972 | struct ath_buf *bf, *lastbf, *bf_held = NULL; |
922 | struct list_head bf_head; | 973 | struct list_head bf_head; |
923 | struct ath_desc *ds, *tmp_ds; | 974 | struct ath_desc *ds; |
924 | struct sk_buff *skb; | 975 | int txok, nbad = 0; |
925 | struct ieee80211_tx_info *tx_info; | ||
926 | struct ath_tx_info_priv *tx_info_priv; | ||
927 | int nacked, txok, nbad = 0, isrifs = 0; | ||
928 | int status; | 976 | int status; |
929 | 977 | ||
930 | DPRINTF(sc, ATH_DBG_QUEUE, | 978 | DPRINTF(sc, ATH_DBG_QUEUE, |
@@ -932,7 +980,6 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
932 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), | 980 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), |
933 | txq->axq_link); | 981 | txq->axq_link); |
934 | 982 | ||
935 | nacked = 0; | ||
936 | for (;;) { | 983 | for (;;) { |
937 | spin_lock_bh(&txq->axq_lock); | 984 | spin_lock_bh(&txq->axq_lock); |
938 | if (list_empty(&txq->axq_q)) { | 985 | if (list_empty(&txq->axq_q)) { |
@@ -1022,30 +1069,8 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1022 | } else { | 1069 | } else { |
1023 | nbad = ath_tx_num_badfrms(sc, bf, txok); | 1070 | nbad = ath_tx_num_badfrms(sc, bf, txok); |
1024 | } | 1071 | } |
1025 | skb = bf->bf_mpdu; | 1072 | |
1026 | tx_info = IEEE80211_SKB_CB(skb); | 1073 | ath_tx_rc_status(bf, ds, nbad); |
1027 | |||
1028 | tx_info_priv = | ||
1029 | (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; | ||
1030 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | ||
1031 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
1032 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | ||
1033 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | ||
1034 | if (ds->ds_txstat.ts_status == 0) | ||
1035 | nacked++; | ||
1036 | |||
1037 | if (bf_isdata(bf)) { | ||
1038 | if (isrifs) | ||
1039 | tmp_ds = bf->bf_rifslast->bf_desc; | ||
1040 | else | ||
1041 | tmp_ds = ds; | ||
1042 | memcpy(&tx_info_priv->tx, | ||
1043 | &tmp_ds->ds_txstat, | ||
1044 | sizeof(tx_info_priv->tx)); | ||
1045 | tx_info_priv->n_frames = bf->bf_nframes; | ||
1046 | tx_info_priv->n_bad_frames = nbad; | ||
1047 | } | ||
1048 | } | ||
1049 | 1074 | ||
1050 | /* | 1075 | /* |
1051 | * Complete this transmit unit | 1076 | * Complete this transmit unit |
@@ -1076,7 +1101,6 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1076 | ath_txq_schedule(sc, txq); | 1101 | ath_txq_schedule(sc, txq); |
1077 | spin_unlock_bh(&txq->axq_lock); | 1102 | spin_unlock_bh(&txq->axq_lock); |
1078 | } | 1103 | } |
1079 | return nacked; | ||
1080 | } | 1104 | } |
1081 | 1105 | ||
1082 | static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq) | 1106 | static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq) |