Deleted Added
full compact
if_ath_tx.c (240592) if_ath_tx.c (240639)
1/*-
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * Copyright (c) 2010-2012 Adrian Chadd, Xenion Pty Ltd
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 15 unchanged lines hidden (view full) ---

24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGES.
29 */
30
31#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * Copyright (c) 2010-2012 Adrian Chadd, Xenion Pty Ltd
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 15 unchanged lines hidden (view full) ---

24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGES.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx.c 240592 2012-09-17 03:17:42Z adrian $");
32__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx.c 240639 2012-09-18 10:14:17Z adrian $");
33
34/*
35 * Driver for the Atheros Wireless LAN controller.
36 *
37 * This software is derived from work of Atsushi Onoe; his contribution
38 * is greatly appreciated.
39 */
40

--- 68 unchanged lines hidden (view full) ---

109static int ath_tx_ampdu_pending(struct ath_softc *sc, struct ath_node *an,
110 int tid);
111static int ath_tx_ampdu_running(struct ath_softc *sc, struct ath_node *an,
112 int tid);
113static ieee80211_seq ath_tx_tid_seqno_assign(struct ath_softc *sc,
114 struct ieee80211_node *ni, struct ath_buf *bf, struct mbuf *m0);
115static int ath_tx_action_frame_override_queue(struct ath_softc *sc,
116 struct ieee80211_node *ni, struct mbuf *m0, int *tid);
33
34/*
35 * Driver for the Atheros Wireless LAN controller.
36 *
37 * This software is derived from work of Atsushi Onoe; his contribution
38 * is greatly appreciated.
39 */
40

--- 68 unchanged lines hidden (view full) ---

109static int ath_tx_ampdu_pending(struct ath_softc *sc, struct ath_node *an,
110 int tid);
111static int ath_tx_ampdu_running(struct ath_softc *sc, struct ath_node *an,
112 int tid);
113static ieee80211_seq ath_tx_tid_seqno_assign(struct ath_softc *sc,
114 struct ieee80211_node *ni, struct ath_buf *bf, struct mbuf *m0);
115static int ath_tx_action_frame_override_queue(struct ath_softc *sc,
116 struct ieee80211_node *ni, struct mbuf *m0, int *tid);
117static struct ath_buf *
118ath_tx_retry_clone(struct ath_softc *sc, struct ath_node *an,
119 struct ath_tid *tid, struct ath_buf *bf);
117
118/*
119 * Whether to use the 11n rate scenario functions or not
120 */
121static inline int
122ath_tx_is_11n(struct ath_softc *sc)
123{
124 return ((sc->sc_ah->ah_magic == 0x20065416) ||

--- 15 unchanged lines hidden (view full) ---

140
141 wh = mtod(m0, const struct ieee80211_frame *);
142 if (! IEEE80211_QOS_HAS_SEQ(wh))
143 return IEEE80211_NONQOS_TID;
144 else
145 return WME_AC_TO_TID(pri);
146}
147
120
121/*
122 * Whether to use the 11n rate scenario functions or not
123 */
124static inline int
125ath_tx_is_11n(struct ath_softc *sc)
126{
127 return ((sc->sc_ah->ah_magic == 0x20065416) ||

--- 15 unchanged lines hidden (view full) ---

143
144 wh = mtod(m0, const struct ieee80211_frame *);
145 if (! IEEE80211_QOS_HAS_SEQ(wh))
146 return IEEE80211_NONQOS_TID;
147 else
148 return WME_AC_TO_TID(pri);
149}
150
151static void
152ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
153{
154 struct ieee80211_frame *wh;
155
156 wh = mtod(bf->bf_m, struct ieee80211_frame *);
157 /* Only update/resync if needed */
158 if (bf->bf_state.bfs_isretried == 0) {
159 wh->i_fc[1] |= IEEE80211_FC1_RETRY;
160 bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
161 BUS_DMASYNC_PREWRITE);
162 }
163 bf->bf_state.bfs_isretried = 1;
164 bf->bf_state.bfs_retries ++;
165}
166
148/*
149 * Determine what the correct AC queue for the given frame
150 * should be.
151 *
152 * This code assumes that the TIDs map consistently to
153 * the underlying hardware (or software) ath_txq.
154 * Since the sender may try to set an AC which is
155 * arbitrary, non-QoS TIDs may end up being put on

--- 2550 unchanged lines hidden (view full) ---

2706void
2707ath_tx_tid_init(struct ath_softc *sc, struct ath_node *an)
2708{
2709 int i, j;
2710 struct ath_tid *atid;
2711
2712 for (i = 0; i < IEEE80211_TID_SIZE; i++) {
2713 atid = &an->an_tid[i];
167/*
168 * Determine what the correct AC queue for the given frame
169 * should be.
170 *
171 * This code assumes that the TIDs map consistently to
172 * the underlying hardware (or software) ath_txq.
173 * Since the sender may try to set an AC which is
174 * arbitrary, non-QoS TIDs may end up being put on

--- 2550 unchanged lines hidden (view full) ---

2725void
2726ath_tx_tid_init(struct ath_softc *sc, struct ath_node *an)
2727{
2728 int i, j;
2729 struct ath_tid *atid;
2730
2731 for (i = 0; i < IEEE80211_TID_SIZE; i++) {
2732 atid = &an->an_tid[i];
2733
2734 /* XXX now with this bzer(), is the field 0'ing needed? */
2735 bzero(atid, sizeof(*atid));
2736
2714 TAILQ_INIT(&atid->axq_q);
2737 TAILQ_INIT(&atid->axq_q);
2738 TAILQ_INIT(&atid->filtq.axq_q);
2715 atid->tid = i;
2716 atid->an = an;
2717 for (j = 0; j < ATH_TID_MAX_BUFS; j++)
2718 atid->tx_buf[j] = NULL;
2719 atid->baw_head = atid->baw_tail = 0;
2720 atid->paused = 0;
2721 atid->sched = 0;
2722 atid->hwq_depth = 0;
2723 atid->cleanup_inprogress = 0;
2739 atid->tid = i;
2740 atid->an = an;
2741 for (j = 0; j < ATH_TID_MAX_BUFS; j++)
2742 atid->tx_buf[j] = NULL;
2743 atid->baw_head = atid->baw_tail = 0;
2744 atid->paused = 0;
2745 atid->sched = 0;
2746 atid->hwq_depth = 0;
2747 atid->cleanup_inprogress = 0;
2748 atid->clrdmask = 1; /* Always start by setting this bit */
2724 if (i == IEEE80211_NONQOS_TID)
2725 atid->ac = WME_AC_BE;
2726 else
2727 atid->ac = TID_TO_WME_AC(i);
2728 }
2729}
2730
2731/*

--- 25 unchanged lines hidden (view full) ---

2757
2758 DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: unpaused = %d\n",
2759 __func__, tid->paused);
2760
2761 if (tid->paused || tid->axq_depth == 0) {
2762 return;
2763 }
2764
2749 if (i == IEEE80211_NONQOS_TID)
2750 atid->ac = WME_AC_BE;
2751 else
2752 atid->ac = TID_TO_WME_AC(i);
2753 }
2754}
2755
2756/*

--- 25 unchanged lines hidden (view full) ---

2782
2783 DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: unpaused = %d\n",
2784 __func__, tid->paused);
2785
2786 if (tid->paused || tid->axq_depth == 0) {
2787 return;
2788 }
2789
2790 /* XXX isfiltered shouldn't ever be 0 at this point */
2791 if (tid->isfiltered == 1) {
2792 device_printf(sc->sc_dev, "%s: filtered?!\n", __func__);
2793 return;
2794 }
2795
2765 ath_tx_tid_sched(sc, tid);
2766 /* Punt some frames to the hardware if needed */
2767 //ath_txq_sched(sc, sc->sc_ac2q[tid->ac]);
2768 taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask);
2769}
2770
2771/*
2796 ath_tx_tid_sched(sc, tid);
2797 /* Punt some frames to the hardware if needed */
2798 //ath_txq_sched(sc, sc->sc_ac2q[tid->ac]);
2799 taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask);
2800}
2801
2802/*
2803 * Add the given ath_buf to the TID filtered frame list.
2804 * This requires the TID be filtered.
2805 */
2806static void
2807ath_tx_tid_filt_addbuf(struct ath_softc *sc, struct ath_tid *tid,
2808 struct ath_buf *bf)
2809{
2810
2811 ATH_TID_LOCK_ASSERT(sc, tid);
2812 if (! tid->isfiltered)
2813 device_printf(sc->sc_dev, "%s: not filtered?!\n", __func__);
2814
2815 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: bf=%p\n", __func__, bf);
2816
2817 /* Set the retry bit and bump the retry counter */
2818 ath_tx_set_retry(sc, bf);
2819 sc->sc_stats.ast_tx_swfiltered++;
2820
2821 ATH_TXQ_INSERT_TAIL(&tid->filtq, bf, bf_list);
2822}
2823
2824/*
2825 * Handle a completed filtered frame from the given TID.
2826 * This just enables/pauses the filtered frame state if required
2827 * and appends the filtered frame to the filtered queue.
2828 */
2829static void
2830ath_tx_tid_filt_comp_buf(struct ath_softc *sc, struct ath_tid *tid,
2831 struct ath_buf *bf)
2832{
2833
2834 ATH_TID_LOCK_ASSERT(sc, tid);
2835
2836 if (! tid->isfiltered) {
2837 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: filter transition\n",
2838 __func__);
2839 tid->isfiltered = 1;
2840 ath_tx_tid_pause(sc, tid);
2841 }
2842
2843 /* Add the frame to the filter queue */
2844 ath_tx_tid_filt_addbuf(sc, tid, bf);
2845}
2846
2847/*
2848 * Complete the filtered frame TX completion.
2849 *
2850 * If there are no more frames in the hardware queue, unpause/unfilter
2851 * the TID if applicable. Otherwise we will wait for a node PS transition
2852 * to unfilter.
2853 */
2854static void
2855ath_tx_tid_filt_comp_complete(struct ath_softc *sc, struct ath_tid *tid)
2856{
2857 struct ath_buf *bf;
2858
2859 ATH_TID_LOCK_ASSERT(sc, tid);
2860
2861 if (tid->hwq_depth != 0)
2862 return;
2863
2864 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: hwq=0, transition back\n",
2865 __func__);
2866 tid->isfiltered = 0;
2867 tid->clrdmask = 1;
2868
2869 /* XXX this is really quite inefficient */
2870 while ((bf = TAILQ_LAST(&tid->filtq.axq_q, ath_bufhead_s)) != NULL) {
2871 ATH_TXQ_REMOVE(&tid->filtq, bf, bf_list);
2872 ATH_TXQ_INSERT_HEAD(tid, bf, bf_list);
2873 }
2874
2875 ath_tx_tid_resume(sc, tid);
2876}
2877
2878/*
2879 * Called when a single (aggregate or otherwise) frame is completed.
2880 *
2881 * Returns 1 if the buffer could be added to the filtered list
2882 * (cloned or otherwise), 0 if the buffer couldn't be added to the
2883 * filtered list (failed clone; expired retry) and the caller should
2884 * free it and handle it like a failure (eg by sending a BAR.)
2885 */
2886static int
2887ath_tx_tid_filt_comp_single(struct ath_softc *sc, struct ath_tid *tid,
2888 struct ath_buf *bf)
2889{
2890 struct ath_buf *nbf;
2891 int retval;
2892
2893 ATH_TID_LOCK_ASSERT(sc, tid);
2894
2895 /*
2896 * Don't allow a filtered frame to live forever.
2897 */
2898 if (bf->bf_state.bfs_retries > SWMAX_RETRIES) {
2899 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
2900 "%s: bf=%p, seqno=%d, exceeded retries\n",
2901 __func__,
2902 bf,
2903 bf->bf_state.bfs_seqno);
2904 return (0);
2905 }
2906
2907 /*
2908 * A busy buffer can't be added to the retry list.
2909 * It needs to be cloned.
2910 */
2911 if (bf->bf_flags & ATH_BUF_BUSY) {
2912 nbf = ath_tx_retry_clone(sc, tid->an, tid, bf);
2913 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
2914 "%s: busy buffer clone: %p -> %p\n",
2915 __func__, bf, nbf);
2916 } else {
2917 nbf = bf;
2918 }
2919
2920 if (nbf == NULL) {
2921 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
2922 "%s: busy buffer couldn't be cloned (%p)!\n",
2923 __func__, bf);
2924 retval = 1;
2925 } else {
2926 ath_tx_tid_filt_comp_buf(sc, tid, nbf);
2927 retval = 0;
2928 }
2929 ath_tx_tid_filt_comp_complete(sc, tid);
2930
2931 return (retval);
2932}
2933
2934static void
2935ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid,
2936 struct ath_buf *bf_first, ath_bufhead *bf_q)
2937{
2938 struct ath_buf *bf, *bf_next, *nbf;
2939
2940 ATH_TID_LOCK_ASSERT(sc, tid);
2941
2942 bf = bf_first;
2943 while (bf) {
2944 bf_next = bf->bf_next;
2945 bf->bf_next = NULL; /* Remove it from the aggr list */
2946
2947 /*
2948 * Don't allow a filtered frame to live forever.
2949 */
2950 if (bf->bf_state.bfs_retries > SWMAX_RETRIES) {
2951 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
2952 "%s: bf=%p, seqno=%d, exceeded retries\n",
2953 __func__,
2954 bf,
2955 bf->bf_state.bfs_seqno);
2956 TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
2957 goto next;
2958 }
2959
2960 if (bf->bf_flags & ATH_BUF_BUSY) {
2961 nbf = ath_tx_retry_clone(sc, tid->an, tid, bf);
2962 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
2963 "%s: busy buffer cloned: %p -> %p",
2964 __func__, bf, nbf);
2965 } else {
2966 nbf = bf;
2967 }
2968
2969 /*
2970 * If the buffer couldn't be cloned, add it to bf_q;
2971 * the caller will free the buffer(s) as required.
2972 */
2973 if (nbf == NULL) {
2974 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
2975 "%s: buffer couldn't be cloned! (%p)\n",
2976 __func__, bf);
2977 TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
2978 } else {
2979 ath_tx_tid_filt_comp_buf(sc, tid, nbf);
2980 }
2981next:
2982 bf = bf_next;
2983 }
2984
2985 ath_tx_tid_filt_comp_complete(sc, tid);
2986}
2987
2988/*
2772 * Suspend the queue because we need to TX a BAR.
2773 */
2774static void
2775ath_tx_tid_bar_suspend(struct ath_softc *sc, struct ath_tid *tid)
2776{
2777 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
2778
2779 DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,

--- 139 unchanged lines hidden (view full) ---

2919
2920 /* Failure? For now, warn loudly and continue */
2921 ATH_TXQ_LOCK(sc->sc_ac2q[tid->ac]);
2922 device_printf(sc->sc_dev, "%s: tid=%p, failed to TX BAR, continue!\n",
2923 __func__, tid);
2924 ath_tx_tid_bar_unsuspend(sc, tid);
2925}
2926
2989 * Suspend the queue because we need to TX a BAR.
2990 */
2991static void
2992ath_tx_tid_bar_suspend(struct ath_softc *sc, struct ath_tid *tid)
2993{
2994 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
2995
2996 DPRINTF(sc, ATH_DEBUG_SW_TX_BAR,

--- 139 unchanged lines hidden (view full) ---

3136
3137 /* Failure? For now, warn loudly and continue */
3138 ATH_TXQ_LOCK(sc->sc_ac2q[tid->ac]);
3139 device_printf(sc->sc_dev, "%s: tid=%p, failed to TX BAR, continue!\n",
3140 __func__, tid);
3141 ath_tx_tid_bar_unsuspend(sc, tid);
3142}
3143
3144static void
3145ath_tx_tid_drain_pkt(struct ath_softc *sc, struct ath_node *an,
3146 struct ath_tid *tid, ath_bufhead *bf_cq, struct ath_buf *bf)
3147{
2927
3148
3149 ATH_TID_LOCK_ASSERT(sc, tid);
3150
3151 /*
3152 * If the current TID is running AMPDU, update
3153 * the BAW.
3154 */
3155 if (ath_tx_ampdu_running(sc, an, tid->tid) &&
3156 bf->bf_state.bfs_dobaw) {
3157 /*
3158 * Only remove the frame from the BAW if it's
3159 * been transmitted at least once; this means
3160 * the frame was in the BAW to begin with.
3161 */
3162 if (bf->bf_state.bfs_retries > 0) {
3163 ath_tx_update_baw(sc, an, tid, bf);
3164 bf->bf_state.bfs_dobaw = 0;
3165 }
3166 /*
3167 * This has become a non-fatal error now
3168 */
3169 if (! bf->bf_state.bfs_addedbaw)
3170 device_printf(sc->sc_dev,
3171 "%s: wasn't added: seqno %d\n",
3172 __func__, SEQNO(bf->bf_state.bfs_seqno));
3173 }
3174 TAILQ_INSERT_TAIL(bf_cq, bf, bf_list);
3175}
3176
3177static void
3178ath_tx_tid_drain_print(struct ath_softc *sc, struct ath_node *an,
3179 struct ath_tid *tid, struct ath_buf *bf)
3180{
3181 struct ieee80211_node *ni = &an->an_node;
3182 struct ath_txq *txq = sc->sc_ac2q[tid->ac];
3183 struct ieee80211_tx_ampdu *tap;
3184
3185 tap = ath_tx_get_tx_tid(an, tid->tid);
3186
3187 device_printf(sc->sc_dev,
3188 "%s: node %p: bf=%p: addbaw=%d, dobaw=%d, "
3189 "seqno=%d, retry=%d\n",
3190 __func__, ni, bf,
3191 bf->bf_state.bfs_addedbaw,
3192 bf->bf_state.bfs_dobaw,
3193 SEQNO(bf->bf_state.bfs_seqno),
3194 bf->bf_state.bfs_retries);
3195 device_printf(sc->sc_dev,
3196 "%s: node %p: bf=%p: tid txq_depth=%d hwq_depth=%d, bar_wait=%d, isfiltered=%d\n",
3197 __func__, ni, bf,
3198 tid->axq_depth,
3199 tid->hwq_depth,
3200 tid->bar_wait,
3201 tid->isfiltered);
3202 device_printf(sc->sc_dev,
3203 "%s: node %p: tid %d: txq_depth=%d, "
3204 "txq_aggr_depth=%d, sched=%d, paused=%d, "
3205 "hwq_depth=%d, incomp=%d, baw_head=%d, "
3206 "baw_tail=%d txa_start=%d, ni_txseqs=%d\n",
3207 __func__, ni, tid->tid, txq->axq_depth,
3208 txq->axq_aggr_depth, tid->sched, tid->paused,
3209 tid->hwq_depth, tid->incomp, tid->baw_head,
3210 tid->baw_tail, tap == NULL ? -1 : tap->txa_start,
3211 ni->ni_txseqs[tid->tid]);
3212
3213 /* XXX Dump the frame, see what it is? */
3214 ieee80211_dump_pkt(ni->ni_ic,
3215 mtod(bf->bf_m, const uint8_t *),
3216 bf->bf_m->m_len, 0, -1);
3217}
3218
2928/*
2929 * Free any packets currently pending in the software TX queue.
2930 *
2931 * This will be called when a node is being deleted.
2932 *
2933 * It can also be called on an active node during an interface
2934 * reset or state transition.
2935 *

--- 6 unchanged lines hidden (view full) ---

2942 */
2943static void
2944ath_tx_tid_drain(struct ath_softc *sc, struct ath_node *an,
2945 struct ath_tid *tid, ath_bufhead *bf_cq)
2946{
2947 struct ath_buf *bf;
2948 struct ieee80211_tx_ampdu *tap;
2949 struct ieee80211_node *ni = &an->an_node;
3219/*
3220 * Free any packets currently pending in the software TX queue.
3221 *
3222 * This will be called when a node is being deleted.
3223 *
3224 * It can also be called on an active node during an interface
3225 * reset or state transition.
3226 *

--- 6 unchanged lines hidden (view full) ---

3233 */
3234static void
3235ath_tx_tid_drain(struct ath_softc *sc, struct ath_node *an,
3236 struct ath_tid *tid, ath_bufhead *bf_cq)
3237{
3238 struct ath_buf *bf;
3239 struct ieee80211_tx_ampdu *tap;
3240 struct ieee80211_node *ni = &an->an_node;
2950 int t = 0;
2951 struct ath_txq *txq = sc->sc_ac2q[tid->ac];
3241 int t;
2952
2953 tap = ath_tx_get_tx_tid(an, tid->tid);
2954
3242
3243 tap = ath_tx_get_tx_tid(an, tid->tid);
3244
2955 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
3245 ATH_TID_LOCK_ASSERT(sc, tid);
2956
2957 /* Walk the queue, free frames */
3246
3247 /* Walk the queue, free frames */
3248 t = 0;
2958 for (;;) {
2959 bf = TAILQ_FIRST(&tid->axq_q);
2960 if (bf == NULL) {
2961 break;
2962 }
2963
2964 if (t == 0) {
3249 for (;;) {
3250 bf = TAILQ_FIRST(&tid->axq_q);
3251 if (bf == NULL) {
3252 break;
3253 }
3254
3255 if (t == 0) {
2965 device_printf(sc->sc_dev,
2966 "%s: node %p: bf=%p: addbaw=%d, dobaw=%d, "
2967 "seqno=%d, retry=%d\n",
2968 __func__, ni, bf,
2969 bf->bf_state.bfs_addedbaw,
2970 bf->bf_state.bfs_dobaw,
2971 SEQNO(bf->bf_state.bfs_seqno),
2972 bf->bf_state.bfs_retries);
2973 device_printf(sc->sc_dev,
2974 "%s: node %p: bf=%p: tid txq_depth=%d hwq_depth=%d, bar_wait=%d\n",
2975 __func__, ni, bf,
2976 tid->axq_depth,
2977 tid->hwq_depth,
2978 tid->bar_wait);
2979 device_printf(sc->sc_dev,
2980 "%s: node %p: tid %d: txq_depth=%d, "
2981 "txq_aggr_depth=%d, sched=%d, paused=%d, "
2982 "hwq_depth=%d, incomp=%d, baw_head=%d, "
2983 "baw_tail=%d txa_start=%d, ni_txseqs=%d\n",
2984 __func__, ni, tid->tid, txq->axq_depth,
2985 txq->axq_aggr_depth, tid->sched, tid->paused,
2986 tid->hwq_depth, tid->incomp, tid->baw_head,
2987 tid->baw_tail, tap == NULL ? -1 : tap->txa_start,
2988 ni->ni_txseqs[tid->tid]);
2989
2990 /* XXX Dump the frame, see what it is? */
2991 ieee80211_dump_pkt(ni->ni_ic,
2992 mtod(bf->bf_m, const uint8_t *),
2993 bf->bf_m->m_len, 0, -1);
2994
3256 ath_tx_tid_drain_print(sc, an, tid, bf);
2995 t = 1;
2996 }
2997
3257 t = 1;
3258 }
3259
3260 ATH_TXQ_REMOVE(tid, bf, bf_list);
3261 ath_tx_tid_drain_pkt(sc, an, tid, bf_cq, bf);
3262 }
2998
3263
2999 /*
3000 * If the current TID is running AMPDU, update
3001 * the BAW.
3002 */
3003 if (ath_tx_ampdu_running(sc, an, tid->tid) &&
3004 bf->bf_state.bfs_dobaw) {
3005 /*
3006 * Only remove the frame from the BAW if it's
3007 * been transmitted at least once; this means
3008 * the frame was in the BAW to begin with.
3009 */
3010 if (bf->bf_state.bfs_retries > 0) {
3011 ath_tx_update_baw(sc, an, tid, bf);
3012 bf->bf_state.bfs_dobaw = 0;
3013 }
3014 /*
3015 * This has become a non-fatal error now
3016 */
3017 if (! bf->bf_state.bfs_addedbaw)
3018 device_printf(sc->sc_dev,
3019 "%s: wasn't added: seqno %d\n",
3020 __func__, SEQNO(bf->bf_state.bfs_seqno));
3264 /* And now, drain the filtered frame queue */
3265 t = 0;
3266 for (;;) {
3267 bf = TAILQ_FIRST(&tid->filtq.axq_q);
3268 if (bf == NULL)
3269 break;
3270
3271 if (t == 0) {
3272 ath_tx_tid_drain_print(sc, an, tid, bf);
3273 t = 1;
3021 }
3274 }
3022 ATH_TXQ_REMOVE(tid, bf, bf_list);
3023 TAILQ_INSERT_TAIL(bf_cq, bf, bf_list);
3275
3276 ATH_TXQ_REMOVE(&tid->filtq, bf, bf_list);
3277 ath_tx_tid_drain_pkt(sc, an, tid, bf_cq, bf);
3024 }
3025
3026 /*
3027 * Now that it's completed, grab the TID lock and update
3028 * the sequence number and BAW window.
3029 * Because sequence numbers have been assigned to frames
3030 * that haven't been sent yet, it's entirely possible
3031 * we'll be called with some pending frames that have not

--- 97 unchanged lines hidden (view full) ---

3129
3130 /* The TID state is protected behind the TXQ lock */
3131 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
3132
3133 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p: fail=%d, hwq_depth now %d\n",
3134 __func__, bf, fail, atid->hwq_depth - 1);
3135
3136 atid->hwq_depth--;
3278 }
3279
3280 /*
3281 * Now that it's completed, grab the TID lock and update
3282 * the sequence number and BAW window.
3283 * Because sequence numbers have been assigned to frames
3284 * that haven't been sent yet, it's entirely possible
3285 * we'll be called with some pending frames that have not

--- 97 unchanged lines hidden (view full) ---

3383
3384 /* The TID state is protected behind the TXQ lock */
3385 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
3386
3387 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p: fail=%d, hwq_depth now %d\n",
3388 __func__, bf, fail, atid->hwq_depth - 1);
3389
3390 atid->hwq_depth--;
3391
3392 if (atid->isfiltered)
3393 device_printf(sc->sc_dev, "%s: isfiltered=1, normal_comp?\n",
3394 __func__);
3395
3137 if (atid->hwq_depth < 0)
3138 device_printf(sc->sc_dev, "%s: hwq_depth < 0: %d\n",
3139 __func__, atid->hwq_depth);
3396 if (atid->hwq_depth < 0)
3397 device_printf(sc->sc_dev, "%s: hwq_depth < 0: %d\n",
3398 __func__, atid->hwq_depth);
3399
3400 /*
3401 * If the queue is filtered, potentially mark it as complete
3402 * and reschedule it as needed.
3403 *
3404 * This is required as there may be a subsequent TX descriptor
3405 * for this end-node that has CLRDMASK set, so it's quite possible
3406 * that a filtered frame will be followed by a non-filtered
3407 * (complete or otherwise) frame.
3408 *
3409 * XXX should we do this before we complete the frame?
3410 */
3411 if (atid->isfiltered)
3412 ath_tx_tid_filt_comp_complete(sc, atid);
3413
3140 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3141
3142 /*
3143 * punt to rate control if we're not being cleaned up
3144 * during a hw queue drain and the frame wanted an ACK.
3145 */
3146 if (fail == 0 && ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0))
3147 ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc,

--- 56 unchanged lines hidden (view full) ---

3204
3205 DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
3206 "%s: TID %d: called\n", __func__, tid);
3207
3208 TAILQ_INIT(&bf_cq);
3209 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
3210
3211 /*
3414 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3415
3416 /*
3417 * punt to rate control if we're not being cleaned up
3418 * during a hw queue drain and the frame wanted an ACK.
3419 */
3420 if (fail == 0 && ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0))
3421 ath_tx_update_ratectrl(sc, ni, bf->bf_state.bfs_rc,

--- 56 unchanged lines hidden (view full) ---

3478
3479 DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
3480 "%s: TID %d: called\n", __func__, tid);
3481
3482 TAILQ_INIT(&bf_cq);
3483 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
3484
3485 /*
3486 * Move the filtered frames to the TX queue, before
3487 * we run off and discard/process things.
3488 */
3489 /* XXX this is really quite inefficient */
3490 while ((bf = TAILQ_LAST(&atid->filtq.axq_q, ath_bufhead_s)) != NULL) {
3491 ATH_TXQ_REMOVE(&atid->filtq, bf, bf_list);
3492 ATH_TXQ_INSERT_HEAD(atid, bf, bf_list);
3493 }
3494
3495 /*
3212 * Update the frames in the software TX queue:
3213 *
3214 * + Discard retry frames in the queue
3215 * + Fix the completion function to be non-aggregate
3216 */
3217 bf = TAILQ_FIRST(&atid->axq_q);
3218 while (bf) {
3219 if (bf->bf_state.bfs_isretried) {

--- 62 unchanged lines hidden (view full) ---

3282
3283 /* Handle completing frames and fail them */
3284 while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) {
3285 TAILQ_REMOVE(&bf_cq, bf, bf_list);
3286 ath_tx_default_comp(sc, bf, 1);
3287 }
3288}
3289
3496 * Update the frames in the software TX queue:
3497 *
3498 * + Discard retry frames in the queue
3499 * + Fix the completion function to be non-aggregate
3500 */
3501 bf = TAILQ_FIRST(&atid->axq_q);
3502 while (bf) {
3503 if (bf->bf_state.bfs_isretried) {

--- 62 unchanged lines hidden (view full) ---

3566
3567 /* Handle completing frames and fail them */
3568 while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) {
3569 TAILQ_REMOVE(&bf_cq, bf, bf_list);
3570 ath_tx_default_comp(sc, bf, 1);
3571 }
3572}
3573
3290static void
3291ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
3292{
3293 struct ieee80211_frame *wh;
3294
3295 wh = mtod(bf->bf_m, struct ieee80211_frame *);
3296 /* Only update/resync if needed */
3297 if (bf->bf_state.bfs_isretried == 0) {
3298 wh->i_fc[1] |= IEEE80211_FC1_RETRY;
3299 bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
3300 BUS_DMASYNC_PREWRITE);
3301 }
3302 sc->sc_stats.ast_tx_swretries++;
3303 bf->bf_state.bfs_isretried = 1;
3304 bf->bf_state.bfs_retries ++;
3305}
3306
3307static struct ath_buf *
3308ath_tx_retry_clone(struct ath_softc *sc, struct ath_node *an,
3309 struct ath_tid *tid, struct ath_buf *bf)
3310{
3311 struct ath_buf *nbf;
3312 int error;
3313
3314 nbf = ath_buf_clone(sc, bf);

--- 32 unchanged lines hidden (view full) ---

3347 /* Update BAW if required, before we free the original buf */
3348 if (bf->bf_state.bfs_dobaw)
3349 ath_tx_switch_baw_buf(sc, an, tid, bf, nbf);
3350
3351 /* Free current buffer; return the older buffer */
3352 bf->bf_m = NULL;
3353 bf->bf_node = NULL;
3354 ath_freebuf(sc, bf);
3574static struct ath_buf *
3575ath_tx_retry_clone(struct ath_softc *sc, struct ath_node *an,
3576 struct ath_tid *tid, struct ath_buf *bf)
3577{
3578 struct ath_buf *nbf;
3579 int error;
3580
3581 nbf = ath_buf_clone(sc, bf);

--- 32 unchanged lines hidden (view full) ---

3614 /* Update BAW if required, before we free the original buf */
3615 if (bf->bf_state.bfs_dobaw)
3616 ath_tx_switch_baw_buf(sc, an, tid, bf, nbf);
3617
3618 /* Free current buffer; return the older buffer */
3619 bf->bf_m = NULL;
3620 bf->bf_node = NULL;
3621 ath_freebuf(sc, bf);
3622
3355 return nbf;
3356}
3357
3358/*
3359 * Handle retrying an unaggregate frame in an aggregate
3360 * session.
3361 *
3362 * If too many retries occur, pause the TID, wait for

--- 65 unchanged lines hidden (view full) ---

3428 }
3429
3430 /*
3431 * This increments the retry counter as well as
3432 * sets the retry flag in the ath_buf and packet
3433 * body.
3434 */
3435 ath_tx_set_retry(sc, bf);
3623 return nbf;
3624}
3625
3626/*
3627 * Handle retrying an unaggregate frame in an aggregate
3628 * session.
3629 *
3630 * If too many retries occur, pause the TID, wait for

--- 65 unchanged lines hidden (view full) ---

3696 }
3697
3698 /*
3699 * This increments the retry counter as well as
3700 * sets the retry flag in the ath_buf and packet
3701 * body.
3702 */
3703 ath_tx_set_retry(sc, bf);
3704 sc->sc_stats.ast_tx_swretries++;
3436
3437 /*
3438 * Insert this at the head of the queue, so it's
3439 * retried before any current/subsequent frames.
3440 */
3441 ATH_TXQ_INSERT_HEAD(atid, bf, bf_list);
3442 ath_tx_tid_sched(sc, atid);
3443 /* Send the BAR if there are no other frames waiting */

--- 19 unchanged lines hidden (view full) ---

3463 int tid = bf->bf_state.bfs_tid;
3464 struct ath_tid *atid = &an->an_tid[tid];
3465
3466 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[atid->ac]);
3467
3468 /* XXX clr11naggr should be done for all subframes */
3469 ath_hal_clr11n_aggr(sc->sc_ah, bf->bf_desc);
3470 ath_hal_set11nburstduration(sc->sc_ah, bf->bf_desc, 0);
3705
3706 /*
3707 * Insert this at the head of the queue, so it's
3708 * retried before any current/subsequent frames.
3709 */
3710 ATH_TXQ_INSERT_HEAD(atid, bf, bf_list);
3711 ath_tx_tid_sched(sc, atid);
3712 /* Send the BAR if there are no other frames waiting */

--- 19 unchanged lines hidden (view full) ---

3732 int tid = bf->bf_state.bfs_tid;
3733 struct ath_tid *atid = &an->an_tid[tid];
3734
3735 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[atid->ac]);
3736
3737 /* XXX clr11naggr should be done for all subframes */
3738 ath_hal_clr11n_aggr(sc->sc_ah, bf->bf_desc);
3739 ath_hal_set11nburstduration(sc->sc_ah, bf->bf_desc, 0);
3740
3471 /* ath_hal_set11n_virtualmorefrag(sc->sc_ah, bf->bf_desc, 0); */
3472
3473 /*
3474 * If the buffer is marked as busy, we can't directly
3475 * reuse it. Instead, try to clone the buffer.
3476 * If the clone is successful, recycle the old buffer.
3477 * If the clone is unsuccessful, set bfs_retries to max
3478 * to force the next bit of code to free the buffer

--- 20 unchanged lines hidden (view full) ---

3499 device_printf(sc->sc_dev,
3500 "%s: wasn't added: seqno %d\n",
3501 __func__, SEQNO(bf->bf_state.bfs_seqno));
3502 bf->bf_state.bfs_dobaw = 0;
3503 return 1;
3504 }
3505
3506 ath_tx_set_retry(sc, bf);
3741 /* ath_hal_set11n_virtualmorefrag(sc->sc_ah, bf->bf_desc, 0); */
3742
3743 /*
3744 * If the buffer is marked as busy, we can't directly
3745 * reuse it. Instead, try to clone the buffer.
3746 * If the clone is successful, recycle the old buffer.
3747 * If the clone is unsuccessful, set bfs_retries to max
3748 * to force the next bit of code to free the buffer

--- 20 unchanged lines hidden (view full) ---

3769 device_printf(sc->sc_dev,
3770 "%s: wasn't added: seqno %d\n",
3771 __func__, SEQNO(bf->bf_state.bfs_seqno));
3772 bf->bf_state.bfs_dobaw = 0;
3773 return 1;
3774 }
3775
3776 ath_tx_set_retry(sc, bf);
3777 sc->sc_stats.ast_tx_swretries++;
3507 bf->bf_next = NULL; /* Just to make sure */
3508
3509 /* Clear the aggregate state */
3510 bf->bf_state.bfs_aggr = 0;
3511 bf->bf_state.bfs_ndelim = 0; /* ??? needed? */
3512 bf->bf_state.bfs_nframes = 1;
3513
3514 TAILQ_INSERT_TAIL(bf_q, bf, bf_list);

--- 70 unchanged lines hidden (view full) ---

3585 ath_tx_tid_bar_suspend(sc, tid);
3586 }
3587
3588 /*
3589 * Send BAR if required
3590 */
3591 if (ath_tx_tid_bar_tx_ready(sc, tid))
3592 ath_tx_tid_bar_tx(sc, tid);
3778 bf->bf_next = NULL; /* Just to make sure */
3779
3780 /* Clear the aggregate state */
3781 bf->bf_state.bfs_aggr = 0;
3782 bf->bf_state.bfs_ndelim = 0; /* ??? needed? */
3783 bf->bf_state.bfs_nframes = 1;
3784
3785 TAILQ_INSERT_TAIL(bf_q, bf, bf_list);

--- 70 unchanged lines hidden (view full) ---

3856 ath_tx_tid_bar_suspend(sc, tid);
3857 }
3858
3859 /*
3860 * Send BAR if required
3861 */
3862 if (ath_tx_tid_bar_tx_ready(sc, tid))
3863 ath_tx_tid_bar_tx(sc, tid);
3864
3593 ATH_TXQ_UNLOCK(sc->sc_ac2q[tid->ac]);
3594
3595 /* Complete frames which errored out */
3596 while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) {
3597 TAILQ_REMOVE(&bf_cq, bf, bf_list);
3598 ath_tx_default_comp(sc, bf, 0);
3599 }
3600}

--- 27 unchanged lines hidden (view full) ---

3628 DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
3629 "%s: TID %d: cleaned up! resume!\n",
3630 __func__, tid);
3631 atid->cleanup_inprogress = 0;
3632 ath_tx_tid_resume(sc, atid);
3633 }
3634
3635 /* Send BAR if required */
3865 ATH_TXQ_UNLOCK(sc->sc_ac2q[tid->ac]);
3866
3867 /* Complete frames which errored out */
3868 while ((bf = TAILQ_FIRST(&bf_cq)) != NULL) {
3869 TAILQ_REMOVE(&bf_cq, bf, bf_list);
3870 ath_tx_default_comp(sc, bf, 0);
3871 }
3872}

--- 27 unchanged lines hidden (view full) ---

3900 DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
3901 "%s: TID %d: cleaned up! resume!\n",
3902 __func__, tid);
3903 atid->cleanup_inprogress = 0;
3904 ath_tx_tid_resume(sc, atid);
3905 }
3906
3907 /* Send BAR if required */
3908 /* XXX why would we send a BAR when transitioning to non-aggregation? */
3636 if (ath_tx_tid_bar_tx_ready(sc, atid))
3637 ath_tx_tid_bar_tx(sc, atid);
3909 if (ath_tx_tid_bar_tx_ready(sc, atid))
3910 ath_tx_tid_bar_tx(sc, atid);
3911
3638 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3639
3640 /* Handle frame completion */
3641 while (bf) {
3642 bf_next = bf->bf_next;
3643 ath_tx_default_comp(sc, bf, 1);
3644 bf = bf_next;
3645 }

--- 30 unchanged lines hidden (view full) ---

3676 int pktlen;
3677 /* XXX there's too much on the stack? */
3678 struct ath_rc_series rc[ATH_RC_NUM];
3679 int txseq;
3680
3681 DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: called; hwq_depth=%d\n",
3682 __func__, atid->hwq_depth);
3683
3912 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3913
3914 /* Handle frame completion */
3915 while (bf) {
3916 bf_next = bf->bf_next;
3917 ath_tx_default_comp(sc, bf, 1);
3918 bf = bf_next;
3919 }

--- 30 unchanged lines hidden (view full) ---

3950 int pktlen;
3951 /* XXX there's too much on the stack? */
3952 struct ath_rc_series rc[ATH_RC_NUM];
3953 int txseq;
3954
3955 DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: called; hwq_depth=%d\n",
3956 __func__, atid->hwq_depth);
3957
3958 TAILQ_INIT(&bf_q);
3959 TAILQ_INIT(&bf_cq);
3960
3684 /* The TID state is kept behind the TXQ lock */
3685 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
3686
3687 atid->hwq_depth--;
3688 if (atid->hwq_depth < 0)
3689 device_printf(sc->sc_dev, "%s: hwq_depth < 0: %d\n",
3690 __func__, atid->hwq_depth);
3691
3692 /*
3961 /* The TID state is kept behind the TXQ lock */
3962 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
3963
3964 atid->hwq_depth--;
3965 if (atid->hwq_depth < 0)
3966 device_printf(sc->sc_dev, "%s: hwq_depth < 0: %d\n",
3967 __func__, atid->hwq_depth);
3968
3969 /*
3970 * If the TID is filtered, handle completing the filter
3971 * transition before potentially kicking it to the cleanup
3972 * function.
3973 */
3974 if (atid->isfiltered)
3975 ath_tx_tid_filt_comp_complete(sc, atid);
3976
3977 /*
3693 * Punt cleanup to the relevant function, not our problem now
3694 */
3695 if (atid->cleanup_inprogress) {
3978 * Punt cleanup to the relevant function, not our problem now
3979 */
3980 if (atid->cleanup_inprogress) {
3981 if (atid->isfiltered)
3982 device_printf(sc->sc_dev,
3983 "%s: isfiltered=1, normal_comp?\n",
3984 __func__);
3696 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3697 ath_tx_comp_cleanup_aggr(sc, bf_first);
3698 return;
3699 }
3700
3701 /*
3985 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3986 ath_tx_comp_cleanup_aggr(sc, bf_first);
3987 return;
3988 }
3989
3990 /*
3991 * If the frame is filtered, transition to filtered frame
3992 * mode and add this to the filtered frame list.
3993 *
3994 * XXX TODO: figure out how this interoperates with
3995 * BAR, pause and cleanup states.
3996 */
3997 if ((ts.ts_status & HAL_TXERR_FILT) ||
3998 (ts.ts_status != 0 && atid->isfiltered)) {
3999 if (fail != 0)
4000 device_printf(sc->sc_dev,
4001 "%s: isfiltered=1, fail=%d\n", __func__, fail);
4002 ath_tx_tid_filt_comp_aggr(sc, atid, bf_first, &bf_cq);
4003
4004 /* Remove from BAW */
4005 TAILQ_FOREACH_SAFE(bf, &bf_cq, bf_list, bf_next) {
4006 if (bf->bf_state.bfs_addedbaw)
4007 drops++;
4008 if (bf->bf_state.bfs_dobaw) {
4009 ath_tx_update_baw(sc, an, atid, bf);
4010 if (! bf->bf_state.bfs_addedbaw)
4011 device_printf(sc->sc_dev,
4012 "%s: wasn't added: seqno %d\n",
4013 __func__,
4014 SEQNO(bf->bf_state.bfs_seqno));
4015 }
4016 bf->bf_state.bfs_dobaw = 0;
4017 }
4018 /*
4019 * If any intermediate frames in the BAW were dropped when
4020 * handling filtering things, send a BAR.
4021 */
4022 if (drops)
4023 ath_tx_tid_bar_suspend(sc, atid);
4024
4025 /*
4026 * Finish up by sending a BAR if required and freeing
4027 * the frames outside of the TX lock.
4028 */
4029 goto finish_send_bar;
4030 }
4031
4032 /*
3702 * Take a copy; this may be needed -after- bf_first
3703 * has been completed and freed.
3704 */
3705 ts = bf_first->bf_status.ds_txstat;
3706 /*
3707 * XXX for now, use the first frame in the aggregate for
3708 * XXX rate control completion; it's at least consistent.
3709 */

--- 10 unchanged lines hidden (view full) ---

3720 if (ts.ts_status & HAL_TXERR_XRETRY) {
3721#endif
3722 if (ts.ts_status != 0) {
3723 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3724 ath_tx_comp_aggr_error(sc, bf_first, atid);
3725 return;
3726 }
3727
4033 * Take a copy; this may be needed -after- bf_first
4034 * has been completed and freed.
4035 */
4036 ts = bf_first->bf_status.ds_txstat;
4037 /*
4038 * XXX for now, use the first frame in the aggregate for
4039 * XXX rate control completion; it's at least consistent.
4040 */

--- 10 unchanged lines hidden (view full) ---

4051 if (ts.ts_status & HAL_TXERR_XRETRY) {
4052#endif
4053 if (ts.ts_status != 0) {
4054 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
4055 ath_tx_comp_aggr_error(sc, bf_first, atid);
4056 return;
4057 }
4058
3728 TAILQ_INIT(&bf_q);
3729 TAILQ_INIT(&bf_cq);
3730 tap = ath_tx_get_tx_tid(an, tid);
3731
3732 /*
3733 * extract starting sequence and block-ack bitmap
3734 */
3735 /* XXX endian-ness of seq_st, ba? */
3736 seq_st = ts.ts_seqnum;
3737 hasba = !! (ts.ts_flags & HAL_TX_BA);

--- 140 unchanged lines hidden (view full) ---

3878 }
3879
3880 /*
3881 * Reschedule to grab some further frames.
3882 */
3883 ath_tx_tid_sched(sc, atid);
3884
3885 /*
4059 tap = ath_tx_get_tx_tid(an, tid);
4060
4061 /*
4062 * extract starting sequence and block-ack bitmap
4063 */
4064 /* XXX endian-ness of seq_st, ba? */
4065 seq_st = ts.ts_seqnum;
4066 hasba = !! (ts.ts_flags & HAL_TX_BA);

--- 140 unchanged lines hidden (view full) ---

4207 }
4208
4209 /*
4210 * Reschedule to grab some further frames.
4211 */
4212 ath_tx_tid_sched(sc, atid);
4213
4214 /*
4215 * If the queue is filtered, re-schedule as required.
4216 *
4217 * This is required as there may be a subsequent TX descriptor
4218 * for this end-node that has CLRDMASK set, so it's quite possible
4219 * that a filtered frame will be followed by a non-filtered
4220 * (complete or otherwise) frame.
4221 *
4222 * XXX should we do this before we complete the frame?
4223 */
4224 if (atid->isfiltered)
4225 ath_tx_tid_filt_comp_complete(sc, atid);
4226
4227finish_send_bar:
4228
4229 /*
3886 * Send BAR if required
3887 */
3888 if (ath_tx_tid_bar_tx_ready(sc, atid))
3889 ath_tx_tid_bar_tx(sc, atid);
3890
3891 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3892
3893 /* Do deferred completion */

--- 13 unchanged lines hidden (view full) ---

3907static void
3908ath_tx_aggr_comp_unaggr(struct ath_softc *sc, struct ath_buf *bf, int fail)
3909{
3910 struct ieee80211_node *ni = bf->bf_node;
3911 struct ath_node *an = ATH_NODE(ni);
3912 int tid = bf->bf_state.bfs_tid;
3913 struct ath_tid *atid = &an->an_tid[tid];
3914 struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
4230 * Send BAR if required
4231 */
4232 if (ath_tx_tid_bar_tx_ready(sc, atid))
4233 ath_tx_tid_bar_tx(sc, atid);
4234
4235 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
4236
4237 /* Do deferred completion */

--- 13 unchanged lines hidden (view full) ---

4251static void
4252ath_tx_aggr_comp_unaggr(struct ath_softc *sc, struct ath_buf *bf, int fail)
4253{
4254 struct ieee80211_node *ni = bf->bf_node;
4255 struct ath_node *an = ATH_NODE(ni);
4256 int tid = bf->bf_state.bfs_tid;
4257 struct ath_tid *atid = &an->an_tid[tid];
4258 struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
4259 int drops = 0;
3915
3916 /*
3917 * Update rate control status here, before we possibly
3918 * punt to retry or cleanup.
3919 *
3920 * Do it outside of the TXQ lock.
3921 */
3922 if (fail == 0 && ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0))

--- 18 unchanged lines hidden (view full) ---

3941 SEQNO(bf->bf_state.bfs_seqno));
3942
3943 atid->hwq_depth--;
3944 if (atid->hwq_depth < 0)
3945 device_printf(sc->sc_dev, "%s: hwq_depth < 0: %d\n",
3946 __func__, atid->hwq_depth);
3947
3948 /*
4260
4261 /*
4262 * Update rate control status here, before we possibly
4263 * punt to retry or cleanup.
4264 *
4265 * Do it outside of the TXQ lock.
4266 */
4267 if (fail == 0 && ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0))

--- 18 unchanged lines hidden (view full) ---

4286 SEQNO(bf->bf_state.bfs_seqno));
4287
4288 atid->hwq_depth--;
4289 if (atid->hwq_depth < 0)
4290 device_printf(sc->sc_dev, "%s: hwq_depth < 0: %d\n",
4291 __func__, atid->hwq_depth);
4292
4293 /*
4294 * If the TID is filtered, handle completing the filter
4295 * transition before potentially kicking it to the cleanup
4296 * function.
4297 */
4298 if (atid->isfiltered)
4299 ath_tx_tid_filt_comp_complete(sc, atid);
4300
4301 /*
3949 * If a cleanup is in progress, punt to comp_cleanup;
3950 * rather than handling it here. It's thus their
3951 * responsibility to clean up, call the completion
3952 * function in net80211, etc.
3953 */
3954 if (atid->cleanup_inprogress) {
4302 * If a cleanup is in progress, punt to comp_cleanup;
4303 * rather than handling it here. It's thus their
4304 * responsibility to clean up, call the completion
4305 * function in net80211, etc.
4306 */
4307 if (atid->cleanup_inprogress) {
4308 if (atid->isfiltered)
4309 device_printf(sc->sc_dev,
4310 "%s: isfiltered=1, normal_comp?\n",
4311 __func__);
3955 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3956 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: cleanup_unaggr\n",
3957 __func__);
3958 ath_tx_comp_cleanup_unaggr(sc, bf);
3959 return;
3960 }
3961
3962 /*
4312 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
4313 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: cleanup_unaggr\n",
4314 __func__);
4315 ath_tx_comp_cleanup_unaggr(sc, bf);
4316 return;
4317 }
4318
4319 /*
4320 * XXX TODO: how does cleanup, BAR and filtered frame handling
4321 * overlap?
4322 *
4323 * If the frame is filtered OR if it's any failure but
4324 * the TID is filtered, the frame must be added to the
4325 * filtered frame list.
4326 *
4327 * However - a busy buffer can't be added to the filtered
4328 * list as it will end up being recycled without having
4329 * been made available for the hardware.
4330 */
4331 if ((ts->ts_status & HAL_TXERR_FILT) ||
4332 (ts->ts_status != 0 && atid->isfiltered)) {
4333 int freeframe;
4334
4335 if (fail != 0)
4336 device_printf(sc->sc_dev,
4337 "%s: isfiltered=1, fail=%d\n",
4338 __func__,
4339 fail);
4340 freeframe = ath_tx_tid_filt_comp_single(sc, atid, bf);
4341 if (freeframe) {
4342 /* Remove from BAW */
4343 if (bf->bf_state.bfs_addedbaw)
4344 drops++;
4345 if (bf->bf_state.bfs_dobaw) {
4346 ath_tx_update_baw(sc, an, atid, bf);
4347 if (! bf->bf_state.bfs_addedbaw)
4348 device_printf(sc->sc_dev,
4349 "%s: wasn't added: seqno %d\n",
4350 __func__, SEQNO(bf->bf_state.bfs_seqno));
4351 }
4352 bf->bf_state.bfs_dobaw = 0;
4353 }
4354
4355 /*
4356 * If the frame couldn't be filtered, treat it as a drop and
4357 * prepare to send a BAR.
4358 */
4359 if (freeframe && drops)
4360 ath_tx_tid_bar_suspend(sc, atid);
4361
4362 /*
4363 * Send BAR if required
4364 */
4365 if (ath_tx_tid_bar_tx_ready(sc, atid))
4366 ath_tx_tid_bar_tx(sc, atid);
4367
4368 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
4369 /*
4370 * If freeframe is set, then the frame couldn't be
4371 * cloned and bf is still valid. Just complete/free it.
4372 */
4373 if (freeframe)
4374 ath_tx_default_comp(sc, bf, fail);
4375
4376
4377 return;
4378 }
4379 /*
3963 * Don't bother with the retry check if all frames
3964 * are being failed (eg during queue deletion.)
3965 */
3966#if 0
3967 if (fail == 0 && ts->ts_status & HAL_TXERR_XRETRY) {
3968#endif
3969 if (fail == 0 && ts->ts_status != 0) {
3970 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);

--- 11 unchanged lines hidden (view full) ---

3982 bf->bf_state.bfs_dobaw = 0;
3983 if (! bf->bf_state.bfs_addedbaw)
3984 device_printf(sc->sc_dev,
3985 "%s: wasn't added: seqno %d\n",
3986 __func__, SEQNO(bf->bf_state.bfs_seqno));
3987 }
3988
3989 /*
4380 * Don't bother with the retry check if all frames
4381 * are being failed (eg during queue deletion.)
4382 */
4383#if 0
4384 if (fail == 0 && ts->ts_status & HAL_TXERR_XRETRY) {
4385#endif
4386 if (fail == 0 && ts->ts_status != 0) {
4387 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);

--- 11 unchanged lines hidden (view full) ---

4399 bf->bf_state.bfs_dobaw = 0;
4400 if (! bf->bf_state.bfs_addedbaw)
4401 device_printf(sc->sc_dev,
4402 "%s: wasn't added: seqno %d\n",
4403 __func__, SEQNO(bf->bf_state.bfs_seqno));
4404 }
4405
4406 /*
4407 * If the queue is filtered, re-schedule as required.
4408 *
4409 * This is required as there may be a subsequent TX descriptor
4410 * for this end-node that has CLRDMASK set, so it's quite possible
4411 * that a filtered frame will be followed by a non-filtered
4412 * (complete or otherwise) frame.
4413 *
4414 * XXX should we do this before we complete the frame?
4415 */
4416 if (atid->isfiltered)
4417 ath_tx_tid_filt_comp_complete(sc, atid);
4418
4419 /*
3990 * Send BAR if required
3991 */
3992 if (ath_tx_tid_bar_tx_ready(sc, atid))
3993 ath_tx_tid_bar_tx(sc, atid);
3994
3995 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
3996
3997 ath_tx_default_comp(sc, bf, fail);

--- 682 unchanged lines hidden ---
4420 * Send BAR if required
4421 */
4422 if (ath_tx_tid_bar_tx_ready(sc, atid))
4423 ath_tx_tid_bar_tx(sc, atid);
4424
4425 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
4426
4427 ath_tx_default_comp(sc, bf, fail);

--- 682 unchanged lines hidden ---