Deleted Added
full compact
if_ath_tx.c (240946) if_ath_tx.c (241170)
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 240946 2012-09-26 03:45:42Z adrian $");
32__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx.c 241170 2012-10-03 23:23:45Z 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

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

106 */
107#define SWMAX_RETRIES 10
108
109/*
110 * What queue to throw the non-QoS TID traffic into
111 */
112#define ATH_NONQOS_TID_AC WME_AC_VO
113
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

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

106 */
107#define SWMAX_RETRIES 10
108
109/*
110 * What queue to throw the non-QoS TID traffic into
111 */
112#define ATH_NONQOS_TID_AC WME_AC_VO
113
114#if 0
115static int ath_tx_node_is_asleep(struct ath_softc *sc, struct ath_node *an);
116#endif
114static int ath_tx_ampdu_pending(struct ath_softc *sc, struct ath_node *an,
115 int tid);
116static int ath_tx_ampdu_running(struct ath_softc *sc, struct ath_node *an,
117 int tid);
118static ieee80211_seq ath_tx_tid_seqno_assign(struct ath_softc *sc,
119 struct ieee80211_node *ni, struct ath_buf *bf, struct mbuf *m0);
120static int ath_tx_action_frame_override_queue(struct ath_softc *sc,
121 struct ieee80211_node *ni, struct mbuf *m0, int *tid);

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

2897{
2898 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
2899
2900 tid->paused--;
2901
2902 DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: unpaused = %d\n",
2903 __func__, tid->paused);
2904
117static int ath_tx_ampdu_pending(struct ath_softc *sc, struct ath_node *an,
118 int tid);
119static int ath_tx_ampdu_running(struct ath_softc *sc, struct ath_node *an,
120 int tid);
121static ieee80211_seq ath_tx_tid_seqno_assign(struct ath_softc *sc,
122 struct ieee80211_node *ni, struct ath_buf *bf, struct mbuf *m0);
123static int ath_tx_action_frame_override_queue(struct ath_softc *sc,
124 struct ieee80211_node *ni, struct mbuf *m0, int *tid);

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

2900{
2901 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
2902
2903 tid->paused--;
2904
2905 DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: unpaused = %d\n",
2906 __func__, tid->paused);
2907
2905 if (tid->paused || tid->axq_depth == 0) {
2908 if (tid->paused)
2906 return;
2909 return;
2907 }
2908
2910
2911 /*
2912 * Override the clrdmask configuration for the next frame
2913 * from this TID, just to get the ball rolling.
2914 */
2915 tid->clrdmask = 1;
2916
2917 if (tid->axq_depth == 0)
2918 return;
2919
2909 /* XXX isfiltered shouldn't ever be 0 at this point */
2910 if (tid->isfiltered == 1) {
2911 device_printf(sc->sc_dev, "%s: filtered?!\n", __func__);
2912 return;
2913 }
2914
2920 /* XXX isfiltered shouldn't ever be 0 at this point */
2921 if (tid->isfiltered == 1) {
2922 device_printf(sc->sc_dev, "%s: filtered?!\n", __func__);
2923 return;
2924 }
2925
2915 /*
2916 * Override the clrdmask configuration for the next frame,
2917 * just to get the ball rolling.
2918 */
2919 tid->clrdmask = 1;
2920
2921 ath_tx_tid_sched(sc, tid);
2922 /* Punt some frames to the hardware if needed */
2923 //ath_txq_sched(sc, sc->sc_ac2q[tid->ac]);
2924 taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask);
2925}
2926
2927/*
2928 * Add the given ath_buf to the TID filtered frame list.

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

3016 int retval;
3017
3018 ATH_TID_LOCK_ASSERT(sc, tid);
3019
3020 /*
3021 * Don't allow a filtered frame to live forever.
3022 */
3023 if (bf->bf_state.bfs_retries > SWMAX_RETRIES) {
2926 ath_tx_tid_sched(sc, tid);
2927 /* Punt some frames to the hardware if needed */
2928 //ath_txq_sched(sc, sc->sc_ac2q[tid->ac]);
2929 taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask);
2930}
2931
2932/*
2933 * Add the given ath_buf to the TID filtered frame list.

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

3021 int retval;
3022
3023 ATH_TID_LOCK_ASSERT(sc, tid);
3024
3025 /*
3026 * Don't allow a filtered frame to live forever.
3027 */
3028 if (bf->bf_state.bfs_retries > SWMAX_RETRIES) {
3029 sc->sc_stats.ast_tx_swretrymax++;
3024 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
3025 "%s: bf=%p, seqno=%d, exceeded retries\n",
3026 __func__,
3027 bf,
3028 bf->bf_state.bfs_seqno);
3029 return (0);
3030 }
3031

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

3068 while (bf) {
3069 bf_next = bf->bf_next;
3070 bf->bf_next = NULL; /* Remove it from the aggr list */
3071
3072 /*
3073 * Don't allow a filtered frame to live forever.
3074 */
3075 if (bf->bf_state.bfs_retries > SWMAX_RETRIES) {
3030 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
3031 "%s: bf=%p, seqno=%d, exceeded retries\n",
3032 __func__,
3033 bf,
3034 bf->bf_state.bfs_seqno);
3035 return (0);
3036 }
3037

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

3074 while (bf) {
3075 bf_next = bf->bf_next;
3076 bf->bf_next = NULL; /* Remove it from the aggr list */
3077
3078 /*
3079 * Don't allow a filtered frame to live forever.
3080 */
3081 if (bf->bf_state.bfs_retries > SWMAX_RETRIES) {
3082 sc->sc_stats.ast_tx_swretrymax++;
3076 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
3077 "%s: bf=%p, seqno=%d, exceeded retries\n",
3078 __func__,
3079 bf,
3080 bf->bf_state.bfs_seqno);
3081 TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
3082 goto next;
3083 }

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

5277 sc->sc_addba_response_timeout(ni, tap);
5278
5279 /* Unpause the TID; which reschedules it */
5280 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
5281 ath_tx_tid_resume(sc, atid);
5282 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
5283}
5284
3083 DPRINTF(sc, ATH_DEBUG_SW_TX_FILT,
3084 "%s: bf=%p, seqno=%d, exceeded retries\n",
3085 __func__,
3086 bf,
3087 bf->bf_state.bfs_seqno);
3088 TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
3089 goto next;
3090 }

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

5284 sc->sc_addba_response_timeout(ni, tap);
5285
5286 /* Unpause the TID; which reschedules it */
5287 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
5288 ath_tx_tid_resume(sc, atid);
5289 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
5290}
5291
5292#if 0
5293/*
5294 * Check if a node is asleep or not.
5295 */
5285static int
5296static int
5297ath_tx_node_is_asleep(struct ath_softc *sc, struct ath_node *an)
5298{
5299
5300 ATH_NODE_LOCK_ASSERT(an);
5301
5302 return (an->an_is_powersave);
5303}
5304#endif
5305
5306/*
5307 * Mark a node as currently "in powersaving."
5308 * This suspends all traffic on the node.
5309 *
5310 * This must be called with the node/tx locks free.
5311 *
5312 * XXX TODO: the locking silliness below is due to how the node
5313 * locking currently works. Right now, the node lock is grabbed
5314 * to do rate control lookups and these are done with the TX
5315 * queue lock held. This means the node lock can't be grabbed
5316 * first here or a LOR will occur.
5317 *
5318 * Eventually (hopefully!) the TX path code will only grab
5319 * the TXQ lock when transmitting and the ath_node lock when
5320 * doing node/TID operations. There are other complications -
5321 * the sched/unsched operations involve walking the per-txq
5322 * 'active tid' list and this requires both locks to be held.
5323 */
5324void
5325ath_tx_node_sleep(struct ath_softc *sc, struct ath_node *an)
5326{
5327 struct ath_tid *atid;
5328 struct ath_txq *txq;
5329 int tid;
5330
5331 ATH_NODE_UNLOCK_ASSERT(an);
5332
5333 /*
5334 * It's possible that a parallel call to ath_tx_node_wakeup()
5335 * will unpause these queues.
5336 *
5337 * The node lock can't just be grabbed here, as there's places
5338 * in the driver where the node lock is grabbed _within_ a
5339 * TXQ lock.
5340 * So, we do this delicately and unwind state if needed.
5341 *
5342 * + Pause all the queues
5343 * + Grab the node lock
5344 * + If the queue is already asleep, unpause and quit
5345 * + else just mark as asleep.
5346 *
5347 * A parallel sleep() call will just pause and then
5348 * find they're already paused, so undo it.
5349 *
5350 * A parallel wakeup() call will check if asleep is 1
5351 * and if it's not (ie, it's 0), it'll treat it as already
5352 * being awake. If it's 1, it'll mark it as 0 and then
5353 * unpause everything.
5354 *
5355 * (Talk about a delicate hack.)
5356 */
5357
5358 /* Suspend all traffic on the node */
5359 for (tid = 0; tid < IEEE80211_TID_SIZE; tid++) {
5360 atid = &an->an_tid[tid];
5361 txq = sc->sc_ac2q[atid->ac];
5362
5363 ATH_TXQ_LOCK(txq);
5364 ath_tx_tid_pause(sc, atid);
5365 ATH_TXQ_UNLOCK(txq);
5366 }
5367
5368 ATH_NODE_LOCK(an);
5369
5370 /* In case of concurrency races from net80211.. */
5371 if (an->an_is_powersave == 1) {
5372 ATH_NODE_UNLOCK(an);
5373 device_printf(sc->sc_dev,
5374 "%s: an=%p: node was already asleep\n",
5375 __func__, an);
5376 for (tid = 0; tid < IEEE80211_TID_SIZE; tid++) {
5377 atid = &an->an_tid[tid];
5378 txq = sc->sc_ac2q[atid->ac];
5379
5380 ATH_TXQ_LOCK(txq);
5381 ath_tx_tid_resume(sc, atid);
5382 ATH_TXQ_UNLOCK(txq);
5383 }
5384 return;
5385 }
5386
5387 /* Mark node as in powersaving */
5388 an->an_is_powersave = 1;
5389
5390 ATH_NODE_UNLOCK(an);
5391}
5392
5393/*
5394 * Mark a node as currently "awake."
5395 * This resumes all traffic to the node.
5396 */
5397void
5398ath_tx_node_wakeup(struct ath_softc *sc, struct ath_node *an)
5399{
5400 struct ath_tid *atid;
5401 struct ath_txq *txq;
5402 int tid;
5403
5404 ATH_NODE_UNLOCK_ASSERT(an);
5405 ATH_NODE_LOCK(an);
5406
5407 /* In case of concurrency races from net80211.. */
5408 if (an->an_is_powersave == 0) {
5409 ATH_NODE_UNLOCK(an);
5410 device_printf(sc->sc_dev,
5411 "%s: an=%p: node was already awake\n",
5412 __func__, an);
5413 return;
5414 }
5415
5416 /* Mark node as awake */
5417 an->an_is_powersave = 0;
5418
5419 ATH_NODE_UNLOCK(an);
5420
5421 for (tid = 0; tid < IEEE80211_TID_SIZE; tid++) {
5422 atid = &an->an_tid[tid];
5423 txq = sc->sc_ac2q[atid->ac];
5424
5425 ATH_TXQ_LOCK(txq);
5426 ath_tx_tid_resume(sc, atid);
5427 ATH_TXQ_UNLOCK(txq);
5428 }
5429}
5430
5431static int
5286ath_legacy_dma_txsetup(struct ath_softc *sc)
5287{
5288
5289 /* nothing new needed */
5290 return (0);
5291}
5292
5293static int

--- 27 unchanged lines hidden ---
5432ath_legacy_dma_txsetup(struct ath_softc *sc)
5433{
5434
5435 /* nothing new needed */
5436 return (0);
5437}
5438
5439static int

--- 27 unchanged lines hidden ---