From owner-svn-src-all@FreeBSD.ORG Tue Nov 8 02:12:11 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B002A1065670; Tue, 8 Nov 2011 02:12:11 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 9EC5E8FC08; Tue, 8 Nov 2011 02:12:11 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id pA82CBlj007629; Tue, 8 Nov 2011 02:12:11 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id pA82CBCN007623; Tue, 8 Nov 2011 02:12:11 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201111080212.pA82CBCN007623@svn.freebsd.org> From: Adrian Chadd Date: Tue, 8 Nov 2011 02:12:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r227328 - head/sys/dev/ath X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Nov 2011 02:12:11 -0000 Author: adrian Date: Tue Nov 8 02:12:11 2011 New Revision: 227328 URL: http://svn.freebsd.org/changeset/base/227328 Log: Begin merging in some of my 802.11n TX aggregation driver changes. * Add a PCU lock, which isn't currently used but will eventually be used to serialise some of the driver access. * Add in all the software TX aggregation state, that's kept per-node and per-TID. * Add in the software and aggregation state to ath_buf. * Add in hooks to ath_softc for aggregation state and the (upcoming) aggregation TX state calls. * Add / fix the HAL access macros. Obtained from: Linux, ath9k Sponsored by: Hobnob, Inc. Modified: head/sys/dev/ath/if_ath.c head/sys/dev/ath/if_ath_ahb.c head/sys/dev/ath/if_ath_pci.c head/sys/dev/ath/if_ath_sysctl.c head/sys/dev/ath/if_athvar.h Modified: head/sys/dev/ath/if_ath.c ============================================================================== --- head/sys/dev/ath/if_ath.c Tue Nov 8 01:35:44 2011 (r227327) +++ head/sys/dev/ath/if_ath.c Tue Nov 8 02:12:11 2011 (r227328) @@ -3162,6 +3162,11 @@ ath_node_alloc(struct ieee80211vap *vap, } ath_rate_node_init(sc, an); + /* Setup the mutex - there's no associd yet so set the name to NULL */ + snprintf(an->an_name, sizeof(an->an_name), "%s: node %p", + device_get_nameunit(sc->sc_dev), an); + mtx_init(&an->an_mtx, an->an_name, NULL, MTX_DEF); + DPRINTF(sc, ATH_DEBUG_NODE, "%s: an %p\n", __func__, an); return &an->an_node; } @@ -3173,7 +3178,7 @@ ath_node_free(struct ieee80211_node *ni) struct ath_softc *sc = ic->ic_ifp->if_softc; DPRINTF(sc, ATH_DEBUG_NODE, "%s: ni %p\n", __func__, ni); - + mtx_destroy(&ATH_NODE(ni)->an_mtx); ath_rate_node_cleanup(sc, ATH_NODE(ni)); sc->sc_node_free(ni); } Modified: head/sys/dev/ath/if_ath_ahb.c ============================================================================== --- head/sys/dev/ath/if_ath_ahb.c Tue Nov 8 01:35:44 2011 (r227327) +++ head/sys/dev/ath/if_ath_ahb.c Tue Nov 8 02:12:11 2011 (r227328) @@ -190,11 +190,13 @@ ath_ahb_attach(device_t dev) } ATH_LOCK_INIT(sc); + ATH_PCU_LOCK_INIT(sc); error = ath_attach(AR9130_DEVID, sc); if (error == 0) /* success */ return 0; + ATH_PCU_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); bad3: @@ -234,6 +236,7 @@ ath_ahb_detach(device_t dev) if (sc->sc_eepromdata) free(sc->sc_eepromdata, M_TEMP); + ATH_PCU_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); return (0); Modified: head/sys/dev/ath/if_ath_pci.c ============================================================================== --- head/sys/dev/ath/if_ath_pci.c Tue Nov 8 01:35:44 2011 (r227327) +++ head/sys/dev/ath/if_ath_pci.c Tue Nov 8 02:12:11 2011 (r227328) @@ -190,11 +190,13 @@ ath_pci_attach(device_t dev) } ATH_LOCK_INIT(sc); + ATH_PCU_LOCK_INIT(sc); error = ath_attach(pci_get_device(dev), sc); if (error == 0) /* success */ return 0; + ATH_PCU_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); bad3: @@ -230,6 +232,7 @@ ath_pci_detach(device_t dev) bus_dma_tag_destroy(sc->sc_dmat); bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, psc->sc_sr); + ATH_PCU_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); return (0); Modified: head/sys/dev/ath/if_ath_sysctl.c ============================================================================== --- head/sys/dev/ath/if_ath_sysctl.c Tue Nov 8 01:35:44 2011 (r227327) +++ head/sys/dev/ath/if_ath_sysctl.c Tue Nov 8 02:12:11 2011 (r227328) @@ -299,6 +299,68 @@ ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS) } static int +ath_sysctl_txagg(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int i, t, param = 0; + int error; + struct ath_buf *bf; + + error = sysctl_handle_int(oidp, ¶m, 0, req); + if (error || !req->newptr) + return error; + + if (param != 1) + return 0; + + printf("no tx bufs (empty list): %d\n", sc->sc_stats.ast_tx_getnobuf); + printf("no tx bufs (was busy): %d\n", sc->sc_stats.ast_tx_getbusybuf); + + printf("aggr single packet: %d\n", + sc->sc_aggr_stats.aggr_single_pkt); + printf("aggr single packet w/ BAW closed: %d\n", + sc->sc_aggr_stats.aggr_baw_closed_single_pkt); + printf("aggr non-baw packet: %d\n", + sc->sc_aggr_stats.aggr_nonbaw_pkt); + printf("aggr aggregate packet: %d\n", + sc->sc_aggr_stats.aggr_aggr_pkt); + printf("aggr single packet low hwq: %d\n", + sc->sc_aggr_stats.aggr_low_hwq_single_pkt); + printf("aggr sched, no work: %d\n", + sc->sc_aggr_stats.aggr_sched_nopkt); + for (i = 0; i < 64; i++) { + printf("%2d: %10d ", i, sc->sc_aggr_stats.aggr_pkts[i]); + if (i % 4 == 3) + printf("\n"); + } + printf("\n"); + + for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { + if (ATH_TXQ_SETUP(sc, i)) { + printf("HW TXQ %d: axq_depth=%d, axq_aggr_depth=%d\n", + i, + sc->sc_txq[i].axq_depth, + sc->sc_txq[i].axq_aggr_depth); + } + } + + i = t = 0; + ATH_TXBUF_LOCK(sc); + STAILQ_FOREACH(bf, &sc->sc_txbuf, bf_list) { + if (bf->bf_flags & ATH_BUF_BUSY) { + printf("Busy: %d\n", t); + i++; + } + t++; + } + ATH_TXBUF_UNLOCK(sc); + printf("Total TX buffers: %d; Total TX buffers busy: %d\n", + t, i); + + return 0; +} + +static int ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; @@ -387,6 +449,24 @@ ath_sysctl_setcca(SYSCTL_HANDLER_ARGS) } #endif /* IEEE80211_SUPPORT_TDMA */ +static int +ath_sysctl_forcebstuck(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int val = 0; + int error; + + error = sysctl_handle_int(oidp, &val, 0, req); + if (error || !req->newptr) + return error; + if (val == 0) + return 0; + + taskqueue_enqueue_fast(sc->sc_tq, &sc->sc_bstucktask); + val = 0; + return 0; +} + void ath_sysctlattach(struct ath_softc *sc) { @@ -465,6 +545,15 @@ ath_sysctlattach(struct ath_softc *sc) "rfkill", CTLTYPE_INT | CTLFLAG_RW, sc, 0, ath_sysctl_rfkill, "I", "enable/disable RF kill switch"); } + + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "txagg", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_txagg, "I", ""); + + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "forcebstuck", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_sysctl_forcebstuck, "I", ""); + if (ath_hal_hasintmit(ah)) { SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "intmit", CTLTYPE_INT | CTLFLAG_RW, sc, 0, @@ -474,6 +563,17 @@ ath_sysctlattach(struct ath_softc *sc) SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "monpass", CTLFLAG_RW, &sc->sc_monpass, 0, "mask of error frames to pass when monitoring"); + + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "hwq_limit", CTLFLAG_RW, &sc->sc_hwq_limit, 0, + ""); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "tid_hwq_lo", CTLFLAG_RW, &sc->sc_tid_hwq_lo, 0, + ""); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "tid_hwq_hi", CTLFLAG_RW, &sc->sc_tid_hwq_hi, 0, + ""); + #ifdef IEEE80211_SUPPORT_TDMA if (ath_hal_macversion(ah) > 0x78) { sc->sc_tdmadbaprep = 2; @@ -510,6 +610,8 @@ ath_sysctl_clearstats(SYSCTL_HANDLER_ARG if (val == 0) return 0; /* Not clearing the stats is still valid */ memset(&sc->sc_stats, 0, sizeof(sc->sc_stats)); + memset(&sc->sc_aggr_stats, 0, sizeof(sc->sc_aggr_stats)); + val = 0; return 0; } Modified: head/sys/dev/ath/if_athvar.h ============================================================================== --- head/sys/dev/ath/if_athvar.h Tue Nov 8 01:35:44 2011 (r227327) +++ head/sys/dev/ath/if_athvar.h Tue Nov 8 02:12:11 2011 (r227328) @@ -83,12 +83,73 @@ struct taskqueue; struct kthread; struct ath_buf; +#define ATH_TID_MAX_BUFS (2 * IEEE80211_AGGR_BAWMAX) + +/* + * Per-TID state + * + * Note that TID 16 (WME_NUM_TID+1) is for handling non-QoS frames. + */ +struct ath_tid { + TAILQ_HEAD(,ath_buf) axq_q; /* pending buffers */ + u_int axq_depth; /* SW queue depth */ + char axq_name[48]; /* lock name */ + struct ath_node *an; /* pointer to parent */ + int tid; /* tid */ + int ac; /* which AC gets this trafic */ + int hwq_depth; /* how many buffers are on HW */ + + /* + * Entry on the ath_txq; when there's traffic + * to send + */ + TAILQ_ENTRY(ath_tid) axq_qelem; + int sched; + int paused; /* >0 if the TID has been paused */ + + /* + * Is the TID being cleaned up after a transition + * from aggregation to non-aggregation? + * When this is set to 1, this TID will be paused + * and no further traffic will be queued until all + * the hardware packets pending for this TID have been + * TXed/completed; at which point (non-aggregation) + * traffic will resume being TXed. + */ + int cleanup_inprogress; + /* + * How many hardware-queued packets are + * waiting to be cleaned up. + * This is only valid if cleanup_inprogress is 1. + */ + int incomp; + + /* + * The following implements a ring representing + * the frames in the current BAW. + * To avoid copying the array content each time + * the BAW is moved, the baw_head/baw_tail point + * to the current BAW begin/end; when the BAW is + * shifted the head/tail of the array are also + * appropriately shifted. + */ + /* active tx buffers, beginning at current BAW */ + struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; + /* where the baw head is in the array */ + int baw_head; + /* where the BAW tail is in the array */ + int baw_tail; +}; + /* driver-specific node state */ struct ath_node { struct ieee80211_node an_node; /* base class */ u_int8_t an_mgmtrix; /* min h/w rate index */ u_int8_t an_mcastrix; /* mcast h/w rate index */ struct ath_buf *an_ff_buf[WME_NUM_AC]; /* ff staging area */ + struct ath_tid an_tid[IEEE80211_TID_SIZE]; /* per-TID state */ + char an_name[32]; /* eg "wlan0_a1" */ + struct mtx an_mtx; /* protecting the ath_node state */ /* variable-length rate control state follows */ }; #define ATH_NODE(ni) ((struct ath_node *)(ni)) @@ -110,6 +171,7 @@ struct ath_node { struct ath_buf { STAILQ_ENTRY(ath_buf) bf_list; + struct ath_buf * bf_next; /* next buffer in the aggregate */ int bf_nseg; uint16_t bf_txflags; /* tx descriptor flags */ uint16_t bf_flags; /* status flags (below) */ @@ -119,9 +181,63 @@ struct ath_buf { bus_dmamap_t bf_dmamap; /* DMA map for mbuf chain */ struct mbuf *bf_m; /* mbuf for buf */ struct ieee80211_node *bf_node; /* pointer to the node */ + struct ath_desc *bf_lastds; /* last descriptor for comp status */ + struct ath_buf *bf_last; /* last buffer in aggregate, or self for non-aggregate */ bus_size_t bf_mapsize; #define ATH_MAX_SCATTER ATH_TXDESC /* max(tx,rx,beacon) desc's */ bus_dma_segment_t bf_segs[ATH_MAX_SCATTER]; + + /* Completion function to call on TX complete (fail or not) */ + /* + * "fail" here is set to 1 if the queue entries were removed + * through a call to ath_tx_draintxq(). + */ + void(* bf_comp) (struct ath_softc *sc, struct ath_buf *bf, int fail); + + /* This state is kept to support software retries and aggregation */ + struct { + int bfs_seqno; /* sequence number of this packet */ + int bfs_retries; /* retry count */ + uint16_t bfs_tid; /* packet TID (or TID_MAX for no QoS) */ + uint16_t bfs_pri; /* packet AC priority */ + struct ath_txq *bfs_txq; /* eventual dest hardware TXQ */ + uint16_t bfs_pktdur; /* packet duration (at current rate?) */ + uint16_t bfs_nframes; /* number of frames in aggregate */ + uint16_t bfs_ndelim; /* number of delims for padding */ + + int bfs_aggr:1; /* part of aggregate? */ + int bfs_aggrburst:1; /* part of aggregate burst? */ + int bfs_isretried:1; /* retried frame? */ + int bfs_dobaw:1; /* actually check against BAW? */ + int bfs_addedbaw:1; /* has been added to the BAW */ + int bfs_shpream:1; /* use short preamble */ + int bfs_istxfrag:1; /* is fragmented */ + int bfs_ismrr:1; /* do multi-rate TX retry */ + int bfs_doprot:1; /* do RTS/CTS based protection */ + int bfs_doratelookup:1; /* do rate lookup before each TX */ + int bfs_nfl; /* next fragment length */ + + /* + * These fields are passed into the + * descriptor setup functions. + */ + HAL_PKT_TYPE bfs_atype; /* packet type */ + int bfs_pktlen; /* length of this packet */ + int bfs_hdrlen; /* length of this packet header */ + uint16_t bfs_al; /* length of aggregate */ + int bfs_flags; /* HAL descriptor flags */ + int bfs_txrate0; /* first TX rate */ + int bfs_try0; /* first try count */ + uint8_t bfs_ctsrate0; /* Non-zero - use this as ctsrate */ + int bfs_keyix; /* crypto key index */ + int bfs_txpower; /* tx power */ + int bfs_txantenna; /* TX antenna config */ + enum ieee80211_protmode bfs_protmode; + HAL_11N_RATE_SERIES bfs_rc11n[ATH_RC_NUM]; /* 11n TX series */ + int bfs_ctsrate; /* CTS rate */ + int bfs_ctsduration; /* CTS duration (pre-11n NICs) */ + struct ath_rc_series bfs_rc[ATH_RC_NUM]; /* non-11n TX series */ + } bf_state; }; typedef STAILQ_HEAD(, ath_buf) ath_bufhead; @@ -151,19 +267,27 @@ struct ath_descdma { * hardware queue). */ struct ath_txq { + struct ath_softc *axq_softc; /* Needed for scheduling */ u_int axq_qnum; /* hardware q number */ #define ATH_TXQ_SWQ (HAL_NUM_TX_QUEUES+1) /* qnum for s/w only queue */ u_int axq_ac; /* WME AC */ u_int axq_flags; #define ATH_TXQ_PUTPENDING 0x0001 /* ath_hal_puttxbuf pending */ u_int axq_depth; /* queue depth (stat only) */ + u_int axq_aggr_depth; /* how many aggregates are queued */ u_int axq_intrcnt; /* interrupt count */ u_int32_t *axq_link; /* link ptr in last TX desc */ STAILQ_HEAD(, ath_buf) axq_q; /* transmit queue */ struct mtx axq_lock; /* lock on q and link */ char axq_name[12]; /* e.g. "ath0_txq4" */ + /* Per-TID traffic queue for software -> hardware TX */ + TAILQ_HEAD(axq_t_s,ath_tid) axq_tidq; }; +#define ATH_NODE_LOCK(_an) mtx_lock(&(_an)->an_mtx) +#define ATH_NODE_UNLOCK(_an) mtx_unlock(&(_an)->an_mtx) +#define ATH_NODE_LOCK_ASSERT(_an) mtx_assert(&(_an)->an_mtx, MA_OWNED) + #define ATH_TXQ_LOCK_INIT(_sc, _tq) do { \ snprintf((_tq)->axq_name, sizeof((_tq)->axq_name), "%s_txq%u", \ device_get_nameunit((_sc)->sc_dev), (_tq)->axq_qnum); \ @@ -173,6 +297,7 @@ struct ath_txq { #define ATH_TXQ_LOCK(_tq) mtx_lock(&(_tq)->axq_lock) #define ATH_TXQ_UNLOCK(_tq) mtx_unlock(&(_tq)->axq_lock) #define ATH_TXQ_LOCK_ASSERT(_tq) mtx_assert(&(_tq)->axq_lock, MA_OWNED) +#define ATH_TXQ_IS_LOCKED(_tq) mtx_owned(&(_tq)->axq_lock) #define ATH_TXQ_INSERT_TAIL(_tq, _elm, _field) do { \ STAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \ @@ -205,9 +330,20 @@ struct ath_vap { struct taskqueue; struct ath_tx99; +/* + * Whether to reset the TX/RX queue with or without + * a queue flush. + */ +typedef enum { + ATH_RESET_DEFAULT = 0, + ATH_RESET_NOLOSS = 1, + ATH_RESET_FULL = 2, +} ATH_RESET_TYPE; + struct ath_softc { struct ifnet *sc_ifp; /* interface common */ struct ath_stats sc_stats; /* interface statistics */ + struct ath_tx_aggr_stats sc_aggr_stats; int sc_debug; int sc_nvaps; /* # vaps */ int sc_nstavaps; /* # station vaps */ @@ -216,12 +352,15 @@ struct ath_softc { u_int8_t sc_nbssid0; /* # vap's using base mac */ uint32_t sc_bssidmask; /* bssid mask */ + void (*sc_node_cleanup)(struct ieee80211_node *); void (*sc_node_free)(struct ieee80211_node *); device_t sc_dev; HAL_BUS_TAG sc_st; /* bus space tag */ HAL_BUS_HANDLE sc_sh; /* bus space handle */ bus_dma_tag_t sc_dmat; /* bus DMA tag */ struct mtx sc_mtx; /* master lock (recursive) */ + struct mtx sc_pcu_mtx; /* PCU access mutex */ + char sc_pcu_mtx_name[32]; struct taskqueue *sc_tq; /* private task queue */ struct ath_hal *sc_ah; /* Atheros HAL */ struct ath_ratectrl *sc_rc; /* tx rate control support */ @@ -360,10 +499,38 @@ struct ath_softc { int sc_txchainmask; /* currently configured TX chainmask */ int sc_rxchainmask; /* currently configured RX chainmask */ + /* + * Aggregation twiddles + * + * hwq_limit: how busy to keep the hardware queue - don't schedule + * further packets to the hardware, regardless of the TID + * tid_hwq_lo: how low the per-TID hwq count has to be before the + * TID will be scheduled again + * tid_hwq_hi: how many frames to queue to the HWQ before the TID + * stops being scheduled. + */ + int sc_hwq_limit; + int sc_tid_hwq_lo; + int sc_tid_hwq_hi; + /* DFS related state */ void *sc_dfs; /* Used by an optional DFS module */ int sc_dodfs; /* Whether to enable DFS rx filter bits */ struct task sc_dfstask; /* DFS processing task */ + + /* TX AMPDU handling */ + int (*sc_addba_request)(struct ieee80211_node *, + struct ieee80211_tx_ampdu *, int, int, int); + int (*sc_addba_response)(struct ieee80211_node *, + struct ieee80211_tx_ampdu *, int, int, int); + void (*sc_addba_stop)(struct ieee80211_node *, + struct ieee80211_tx_ampdu *); + void (*sc_addba_response_timeout) + (struct ieee80211_node *, + struct ieee80211_tx_ampdu *); + void (*sc_bar_response)(struct ieee80211_node *ni, + struct ieee80211_tx_ampdu *tap, + int status); }; #define ATH_LOCK_INIT(_sc) \ @@ -374,6 +541,37 @@ struct ath_softc { #define ATH_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) #define ATH_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) +/* + * The PCU lock is non-recursive and should be treated as a spinlock. + * Although currently the interrupt code is run in netisr context and + * doesn't require this, this may change in the future. + * Please keep this in mind when protecting certain code paths + * with the PCU lock. + * + * The PCU lock is used to serialise access to the PCU so things such + * as TX, RX, state change (eg channel change), channel reset and updates + * from interrupt context (eg kickpcu, txqactive bits) do not clash. + * + * Although the current single-thread taskqueue mechanism protects the + * majority of these situations by simply serialising them, there are + * a few others which occur at the same time. These include the TX path + * (which only acquires ATH_LOCK when recycling buffers to the free list), + * ath_set_channel, the channel scanning API and perhaps quite a bit more. + */ +#define ATH_PCU_LOCK_INIT(_sc) do {\ + snprintf((_sc)->sc_pcu_mtx_name, \ + sizeof((_sc)->sc_pcu_mtx_name), \ + "%s PCU lock", \ + device_get_nameunit((_sc)->sc_dev)); \ + mtx_init(&(_sc)->sc_pcu_mtx, (_sc)->sc_pcu_mtx_name, \ + NULL, MTX_DEF); \ + } while (0) +#define ATH_PCU_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_pcu_mtx) +#define ATH_PCU_LOCK(_sc) mtx_lock(&(_sc)->sc_pcu_mtx) +#define ATH_PCU_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_pcu_mtx) +#define ATH_PCU_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_pcu_mtx, \ + MA_OWNED) + #define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<ah_getTxCompletionRates)((_ah), (_ds), (_rates), (_tries))) -#define ath_hal_chaintxdesc(_ah, _ds, _pktlen, _hdrlen, _type, _keyix, \ - _cipher, _delims, _seglen, _first, _last) \ - ((*(_ah)->ah_chainTxDesc((_ah), (_ds), (_pktlen), (_hdrlen), \ - (_type), (_keyix), (_cipher), (_delims), (_seglen), \ - (_first), (_last)))) #define ath_hal_setupfirsttxdesc(_ah, _ds, _aggrlen, _flags, _txpower, \ _txr0, _txtr0, _antm, _rcr, _rcd) \ ((*(_ah)->ah_setupFirstTxDesc)((_ah), (_ds), (_aggrlen), (_flags), \ (_txpower), (_txr0), (_txtr0), (_antm), (_rcr), (_rcd))) +#define ath_hal_chaintxdesc(_ah, _ds, _pktlen, _hdrlen, _type, _keyix, \ + _cipher, _delims, _seglen, _first, _last) \ + ((*(_ah)->ah_chainTxDesc)((_ah), (_ds), (_pktlen), (_hdrlen), \ + (_type), (_keyix), (_cipher), (_delims), (_seglen), \ + (_first), (_last))) #define ath_hal_setuplasttxdesc(_ah, _ds, _ds0) \ ((*(_ah)->ah_setupLastTxDesc)((_ah), (_ds), (_ds0))) + #define ath_hal_set11nratescenario(_ah, _ds, _dur, _rt, _series, _ns, _flags) \ ((*(_ah)->ah_set11nRateScenario)((_ah), (_ds), (_dur), (_rt), \ (_series), (_ns), (_flags))) + +#define ath_hal_set11n_aggr_first(_ah, _ds, _len, _num) \ + ((*(_ah)->ah_set11nAggrFirst)((_ah), (_ds), (_len), (_num))) #define ath_hal_set11naggrmiddle(_ah, _ds, _num) \ - ((*(_ah)->ah_set11nAggrMiddle((_ah), (_ds), (_num)))) + ((*(_ah)->ah_set11nAggrMiddle)((_ah), (_ds), (_num))) +#define ath_hal_set11n_aggr_last(_ah, _ds) \ + ((*(_ah)->ah_set11nAggrLast)((_ah), (_ds))) + #define ath_hal_set11nburstduration(_ah, _ds, _dur) \ ((*(_ah)->ah_set11nBurstDuration)((_ah), (_ds), (_dur))) +#define ath_hal_clr11n_aggr(_ah, _ds) \ + ((*(_ah)->ah_clr11nAggr)((_ah), (_ds))) /* * This is badly-named; you need to set the correct parameters