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 --- |