Deleted Added
sdiff udiff text old ( 232794 ) new ( 233227 )
full compact
1/*-
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

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

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

104 * How many retries to perform in software
105 */
106#define SWMAX_RETRIES 10
107
108static int ath_tx_ampdu_pending(struct ath_softc *sc, struct ath_node *an,
109 int tid);
110static int ath_tx_ampdu_running(struct ath_softc *sc, struct ath_node *an,
111 int tid);
112static ieee80211_seq ath_tx_tid_seqno_assign(struct ath_softc *sc,
113 struct ieee80211_node *ni, struct ath_buf *bf, struct mbuf *m0);
114static int ath_tx_action_frame_override_queue(struct ath_softc *sc,
115 struct ieee80211_node *ni, struct mbuf *m0, int *tid);
116
117/*
118 * Whether to use the 11n rate scenario functions or not
119 */
120static inline int
121ath_tx_is_11n(struct ath_softc *sc)
122{
123 return (sc->sc_ah->ah_magic == 0x20065416);

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

1371 struct ath_vap *avp = ATH_VAP(vap);
1372 int r = 0;
1373 u_int pri;
1374 int tid;
1375 struct ath_txq *txq;
1376 int ismcast;
1377 const struct ieee80211_frame *wh;
1378 int is_ampdu, is_ampdu_tx, is_ampdu_pending;
1379 ieee80211_seq seqno;
1380 uint8_t type, subtype;
1381
1382 /*
1383 * Determine the target hardware queue.
1384 *
1385 * For multicast frames, the txq gets overridden to be the
1386 * software TXQ and it's done via direct-dispatch.
1387 *

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

1423 }
1424 }
1425
1426 /* A-MPDU TX */
1427 is_ampdu_tx = ath_tx_ampdu_running(sc, ATH_NODE(ni), tid);
1428 is_ampdu_pending = ath_tx_ampdu_pending(sc, ATH_NODE(ni), tid);
1429 is_ampdu = is_ampdu_tx | is_ampdu_pending;
1430
1431 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: tid=%d, ac=%d, is_ampdu=%d\n",
1432 __func__, tid, pri, is_ampdu);
1433
1434 /* Multicast frames go onto the software multicast queue */
1435 if (ismcast)
1436 txq = &avp->av_mcastq;
1437
1438 /*
1439 * XXX This likely means that if there's a station in power
1440 * save mode, we won't be doing any kind of aggregation towards
1441 * anyone. This is likely a very suboptimal way of dealing
1442 * with things.
1443 */
1444 if ((! is_ampdu) && (vap->iv_ps_sta || avp->av_mcastq.axq_depth))
1445 txq = &avp->av_mcastq;
1446
1447 /* Do the generic frame setup */
1448 /* XXX should just bzero the bf_state? */
1449 bf->bf_state.bfs_dobaw = 0;
1450
1451 /* A-MPDU TX? Manually set sequence number */
1452 /* Don't do it whilst pending; the net80211 layer still assigns them */
1453 /* XXX do we need locking here? */
1454 if (is_ampdu_tx) {
1455 ATH_TXQ_LOCK(txq);
1456 /*
1457 * Always call; this function will
1458 * handle making sure that null data frames
1459 * don't get a sequence number from the current
1460 * TID and thus mess with the BAW.
1461 */
1462 seqno = ath_tx_tid_seqno_assign(sc, ni, bf, m0);
1463 if (IEEE80211_QOS_HAS_SEQ(wh) &&
1464 subtype != IEEE80211_FC0_SUBTYPE_QOS_NULL) {
1465 bf->bf_state.bfs_dobaw = 1;
1466 }
1467 ATH_TXQ_UNLOCK(txq);
1468 }
1469
1470 /*
1471 * If needed, the sequence number has been assigned.
1472 * Squirrel it away somewhere easy to get to.
1473 */
1474 bf->bf_state.bfs_seqno = M_SEQNO_GET(m0) << IEEE80211_SEQ_SEQ_SHIFT;
1475
1476 /* Is ampdu pending? fetch the seqno and print it out */
1477 if (is_ampdu_pending)
1478 DPRINTF(sc, ATH_DEBUG_SW_TX,
1479 "%s: tid %d: ampdu pending, seqno %d\n",
1480 __func__, tid, M_SEQNO_GET(m0));
1481
1482 /* This also sets up the DMA map */
1483 r = ath_tx_normal_setup(sc, ni, bf, m0);
1484
1485 if (r != 0)
1486 return r;
1487
1488 /* At this point m0 could have changed! */
1489 m0 = bf->bf_m;
1490
1491#if 1
1492 /*
1493 * If it's a multicast frame, do a direct-dispatch to the
1494 * destination hardware queue. Don't bother software
1495 * queuing it.
1496 */
1497 /*
1498 * If it's a BAR frame, do a direct dispatch to the
1499 * destination hardware queue. Don't bother software
1500 * queuing it, as the TID will now be paused.
1501 * Sending a BAR frame can occur from the net80211 txa timer
1502 * (ie, retries) or from the ath txtask (completion call.)
1503 * It queues directly to hardware because the TID is paused
1504 * at this point (and won't be unpaused until the BAR has
1505 * either been TXed successfully or max retries has been
1506 * reached.)
1507 */
1508 if (txq == &avp->av_mcastq) {
1509 ATH_TXQ_LOCK(txq);
1510 ath_tx_xmit_normal(sc, txq, bf);
1511 ATH_TXQ_UNLOCK(txq);
1512 } else if (type == IEEE80211_FC0_TYPE_CTL &&
1513 subtype == IEEE80211_FC0_SUBTYPE_BAR) {
1514 DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
1515 "%s: BAR: TX'ing direct\n", __func__);
1516 ATH_TXQ_LOCK(txq);
1517 ath_tx_xmit_normal(sc, txq, bf);
1518 ATH_TXQ_UNLOCK(txq);
1519 } else {
1520 /* add to software queue */
1521 ath_tx_swq(sc, ni, txq, bf);
1522 }
1523#else
1524 /*
1525 * For now, since there's no software queue,
1526 * direct-dispatch to the hardware.
1527 */
1528 ATH_TXQ_LOCK(txq);

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

1961 int index, cindex;
1962 struct ieee80211_tx_ampdu *tap;
1963
1964 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
1965
1966 if (bf->bf_state.bfs_isretried)
1967 return;
1968
1969 tap = ath_tx_get_tx_tid(an, tid->tid);
1970
1971 if (bf->bf_state.bfs_addedbaw)
1972 device_printf(sc->sc_dev,
1973 "%s: re-added? tid=%d, seqno %d; window %d:%d; "
1974 "baw head=%d tail=%d\n",
1975 __func__, tid->tid, SEQNO(bf->bf_state.bfs_seqno),
1976 tap->txa_start, tap->txa_wnd, tid->baw_head,
1977 tid->baw_tail);
1978
1979 /*
1980 * ni->ni_txseqs[] is the currently allocated seqno.
1981 * the txa state contains the current baw start.
1982 */
1983 index = ATH_BA_INDEX(tap->txa_start, SEQNO(bf->bf_state.bfs_seqno));
1984 cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
1985 DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
1986 "%s: tid=%d, seqno %d; window %d:%d; index=%d cindex=%d "
1987 "baw head=%d tail=%d\n",
1988 __func__, tid->tid, SEQNO(bf->bf_state.bfs_seqno),
1989 tap->txa_start, tap->txa_wnd, index, cindex, tid->baw_head,
1990 tid->baw_tail);
1991
1992
1993#if 0
1994 assert(tid->tx_buf[cindex] == NULL);
1995#endif
1996 if (tid->tx_buf[cindex] != NULL) {

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

2083
2084 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
2085
2086 tap = ath_tx_get_tx_tid(an, tid->tid);
2087 index = ATH_BA_INDEX(tap->txa_start, seqno);
2088 cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
2089
2090 DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
2091 "%s: tid=%d, baw=%d:%d, seqno=%d, index=%d, cindex=%d, "
2092 "baw head=%d, tail=%d\n",
2093 __func__, tid->tid, tap->txa_start, tap->txa_wnd, seqno, index,
2094 cindex, tid->baw_head, tid->baw_tail);
2095
2096 /*
2097 * If this occurs then we have a big problem - something else
2098 * has slid tap->txa_start along without updating the BAW
2099 * tracking start/end pointers. Thus the TX BAW state is now
2100 * completely busted.
2101 *

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

2166 if (tid->sched == 0)
2167 return;
2168
2169 tid->sched = 0;
2170 TAILQ_REMOVE(&txq->axq_tidq, tid, axq_qelem);
2171}
2172
2173/*
2174 * Assign a sequence number manually to the given frame.
2175 *
2176 * This should only be called for A-MPDU TX frames.
2177 */
2178static ieee80211_seq
2179ath_tx_tid_seqno_assign(struct ath_softc *sc, struct ieee80211_node *ni,
2180 struct ath_buf *bf, struct mbuf *m0)
2181{
2182 struct ieee80211_frame *wh;
2183 int tid, pri;
2184 ieee80211_seq seqno;
2185 uint8_t subtype;
2186
2187 /* TID lookup */
2188 wh = mtod(m0, struct ieee80211_frame *);
2189 pri = M_WME_GETAC(m0); /* honor classification */
2190 tid = WME_AC_TO_TID(pri);
2191 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: pri=%d, tid=%d, qos has seq=%d\n",
2192 __func__, pri, tid, IEEE80211_QOS_HAS_SEQ(wh));
2193
2194 /* XXX Is it a control frame? Ignore */
2195
2196 /* Does the packet require a sequence number? */
2197 if (! IEEE80211_QOS_HAS_SEQ(wh))
2198 return -1;
2199
2200 /*
2201 * Is it a QOS NULL Data frame? Give it a sequence number from

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

2212 INCR(ni->ni_txseqs[IEEE80211_NONQOS_TID], IEEE80211_SEQ_RANGE);
2213 } else {
2214 /* Manually assign sequence number */
2215 seqno = ni->ni_txseqs[tid];
2216 INCR(ni->ni_txseqs[tid], IEEE80211_SEQ_RANGE);
2217 }
2218 *(uint16_t *)&wh->i_seq[0] = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
2219 M_SEQNO_SET(m0, seqno);
2220
2221 /* Return so caller can do something with it if needed */
2222 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: -> seqno=%d\n", __func__, seqno);
2223 return seqno;
2224}
2225
2226/*
2227 * Attempt to direct dispatch an aggregate frame to hardware.
2228 * If the frame is out of BAW, queue.
2229 * Otherwise, schedule it as a single frame.
2230 */
2231static void
2232ath_tx_xmit_aggr(struct ath_softc *sc, struct ath_node *an, struct ath_buf *bf)
2233{
2234 struct ath_tid *tid = &an->an_tid[bf->bf_state.bfs_tid];
2235 struct ath_txq *txq = bf->bf_state.bfs_txq;
2236 struct ieee80211_tx_ampdu *tap;
2237
2238 ATH_TXQ_LOCK_ASSERT(txq);
2239
2240 tap = ath_tx_get_tx_tid(an, tid->tid);
2241
2242 /* paused? queue */
2243 if (tid->paused) {
2244 ATH_TXQ_INSERT_TAIL(tid, bf, bf_list);
2245 return;
2246 }
2247
2248 /* outside baw? queue */
2249 if (bf->bf_state.bfs_dobaw &&
2250 (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
2251 SEQNO(bf->bf_state.bfs_seqno)))) {
2252 ATH_TXQ_INSERT_TAIL(tid, bf, bf_list);
2253 ath_tx_tid_sched(sc, tid);
2254 return;
2255 }
2256
2257 /* Direct dispatch to hardware */
2258 ath_tx_do_ratelookup(sc, bf);
2259 ath_tx_rate_fill_rcflags(sc, bf);

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

2298 struct mbuf *m0 = bf->bf_m;
2299
2300 /* Fetch the TID - non-QoS frames get assigned to TID 16 */
2301 wh = mtod(m0, struct ieee80211_frame *);
2302 pri = ath_tx_getac(sc, m0);
2303 tid = ath_tx_gettid(sc, m0);
2304 atid = &an->an_tid[tid];
2305
2306 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: bf=%p, pri=%d, tid=%d, qos=%d\n",
2307 __func__, bf, pri, tid, IEEE80211_QOS_HAS_SEQ(wh));
2308
2309 /* Set local packet state, used to queue packets to hardware */
2310 bf->bf_state.bfs_tid = tid;
2311 bf->bf_state.bfs_txq = txq;
2312 bf->bf_state.bfs_pri = pri;
2313
2314 /*
2315 * If the hardware queue isn't busy, queue it directly.
2316 * If the hardware queue is busy, queue it.
2317 * If the TID is paused or the traffic it outside BAW, software
2318 * queue it.
2319 */
2320 ATH_TXQ_LOCK(txq);
2321 if (atid->paused) {
2322 /* TID is paused, queue */
2323 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: paused\n", __func__);
2324 ATH_TXQ_INSERT_TAIL(atid, bf, bf_list);
2325 } else if (ath_tx_ampdu_pending(sc, an, tid)) {
2326 /* AMPDU pending; queue */
2327 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: pending\n", __func__);
2328 ATH_TXQ_INSERT_TAIL(atid, bf, bf_list);
2329 /* XXX sched? */
2330 } else if (ath_tx_ampdu_running(sc, an, tid)) {
2331 /* AMPDU running, attempt direct dispatch if possible */
2332 if (txq->axq_depth < sc->sc_hwq_limit) {
2333 ath_tx_xmit_aggr(sc, an, bf);
2334 DPRINTF(sc, ATH_DEBUG_SW_TX,
2335 "%s: xmit_aggr\n",
2336 __func__);
2337 } else {
2338 DPRINTF(sc, ATH_DEBUG_SW_TX,
2339 "%s: ampdu; swq'ing\n",
2340 __func__);
2341 ATH_TXQ_INSERT_TAIL(atid, bf, bf_list);
2342 ath_tx_tid_sched(sc, atid);
2343 }
2344 } else if (txq->axq_depth < sc->sc_hwq_limit) {
2345 /* AMPDU not running, attempt direct dispatch */
2346 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: xmit_normal\n", __func__);
2347 ath_tx_xmit_normal(sc, txq, bf);
2348 } else {
2349 /* Busy; queue */
2350 DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: swq'ing\n", __func__);
2351 ATH_TXQ_INSERT_TAIL(atid, bf, bf_list);
2352 ath_tx_tid_sched(sc, atid);
2353 }
2354 ATH_TXQ_UNLOCK(txq);
2355}
2356
2357/*
2358 * Do the basic frame setup stuff that's required before the frame

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

2473 for (;;) {
2474 bf = TAILQ_FIRST(&tid->axq_q);
2475 if (bf == NULL) {
2476 break;
2477 }
2478
2479 if (t == 0) {
2480 device_printf(sc->sc_dev,
2481 "%s: node %p: tid %d: txq_depth=%d, "
2482 "txq_aggr_depth=%d, sched=%d, paused=%d, "
2483 "hwq_depth=%d, incomp=%d, baw_head=%d, "
2484 "baw_tail=%d txa_start=%d, ni_txseqs=%d\n",
2485 __func__, ni, tid->tid, txq->axq_depth,
2486 txq->axq_aggr_depth, tid->sched, tid->paused,
2487 tid->hwq_depth, tid->incomp, tid->baw_head,
2488 tid->baw_tail, tap == NULL ? -1 : tap->txa_start,
2489 ni->ni_txseqs[tid->tid]);
2490
2491 /* XXX Dump the frame, see what it is? */
2492 ieee80211_dump_pkt(ni->ni_ic,
2493 mtod(bf->bf_m, const uint8_t *),
2494 bf->bf_m->m_len, 0, -1);
2495
2496 t = 1;
2497 }
2498
2499
2500 /*
2501 * If the current TID is running AMPDU, update
2502 * the BAW.
2503 */
2504 if (ath_tx_ampdu_running(sc, an, tid->tid) &&

--- 1537 unchanged lines hidden ---