Index: dev/ath/if_ath.c =================================================================== --- dev/ath/if_ath.c (revision 324536) +++ dev/ath/if_ath.c (working copy) @@ -4049,10 +4049,14 @@ #define ATH_EXPONENT_TO_VALUE(v) ((1<sc_ic; struct ath_txq *txq = sc->sc_ac2q[ac]; - struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac]; + struct chanAccParams chp; + struct wmeParams *wmep; struct ath_hal *ah = sc->sc_ah; HAL_TXQ_INFO qi; + ieee80211_wme_ic_getparams(ic, &chp); + wmep = &chp.cap_wmeParams[ac]; + ath_hal_gettxqueueprops(ah, txq->axq_qnum, &qi); #ifdef IEEE80211_SUPPORT_TDMA if (sc->sc_tdma) { Index: dev/ath/if_ath_beacon.c =================================================================== --- dev/ath/if_ath_beacon.c (revision 324536) +++ dev/ath/if_ath_beacon.c (working copy) @@ -148,8 +148,12 @@ qi.tqi_cwmin = ATH_BEACON_CWMIN_DEFAULT; qi.tqi_cwmax = ATH_BEACON_CWMAX_DEFAULT; } else { - struct wmeParams *wmep = - &ic->ic_wme.wme_chanParams.cap_wmeParams[WME_AC_BE]; + struct chanAccParams chp; + struct wmeParams *wmep; + + ieee80211_wme_ic_getparams(ic, &chp); + wmep = &chp.cap_wmeParams[WME_AC_BE]; + /* * Adhoc mode; important thing is to use 2x cwmin. */ Index: dev/ath/if_ath_tx.c =================================================================== --- dev/ath/if_ath_tx.c (revision 324536) +++ dev/ath/if_ath_tx.c (working copy) @@ -1552,7 +1552,6 @@ { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = &sc->sc_ic; - const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams; int error, iswep, ismcast, isfrag, ismrr; int keyix, hdrlen, pktlen, try0 = 0; u_int8_t rix = 0, txrate = 0; @@ -1695,7 +1694,11 @@ ismrr = 1; bf->bf_state.bfs_doratelookup = 1; } - if (cap->cap_wmeParams[pri].wmep_noackPolicy) + + /* + * Check whether to set NOACK for this WME category or not. + */ + if (ieee80211_wme_vap_ac_is_noack(vap, pri)) flags |= HAL_TXDESC_NOACK; break; default: Index: dev/bwn/if_bwn.c =================================================================== --- dev/bwn/if_bwn.c (revision 324536) +++ dev/bwn/if_bwn.c (working copy) @@ -1733,15 +1733,18 @@ { struct bwn_softc *sc = ic->ic_softc; struct bwn_mac *mac = sc->sc_curmac; + struct chanAccParams chp; struct wmeParams *wmep; int i; + ieee80211_wme_ic_getparams(ic, &chp); + BWN_LOCK(sc); mac = sc->sc_curmac; if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) { bwn_mac_suspend(mac); for (i = 0; i < N(sc->sc_wmeParams); i++) { - wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i]; + wmep = &chp.cap_wmeParams[i]; bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]); } bwn_mac_enable(mac); Index: dev/iwi/if_iwi.c =================================================================== --- dev/iwi/if_iwi.c (revision 324536) +++ dev/iwi/if_iwi.c (working copy) @@ -1048,12 +1048,15 @@ iwi_wme_setparams(struct iwi_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; + struct chanAccParams chp; const struct wmeParams *wmep; int ac; + ieee80211_wme_ic_getparams(ic, &chp); + for (ac = 0; ac < WME_NUM_AC; ac++) { /* set WME values for current operating mode */ - wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac]; + wmep = &chp.cap_wmeParams[ac]; sc->wme[0].aifsn[ac] = wmep->wmep_aifsn; sc->wme[0].cwmin[ac] = IWI_EXP2(wmep->wmep_logcwmin); sc->wme[0].cwmax[ac] = IWI_EXP2(wmep->wmep_logcwmax); @@ -1769,11 +1772,9 @@ int ac) { struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; struct iwi_node *in = (struct iwi_node *)ni; const struct ieee80211_frame *wh; struct ieee80211_key *k; - const struct chanAccParams *cap; struct iwi_tx_ring *txq = &sc->txq[ac]; struct iwi_tx_data *data; struct iwi_tx_desc *desc; @@ -1795,8 +1796,7 @@ flags |= IWI_DATA_FLAG_SHPREAMBLE; if (IEEE80211_QOS_HAS_SEQ(wh)) { xflags |= IWI_DATA_XFLAG_QOS; - cap = &ic->ic_wme.wme_chanParams; - if (!cap->cap_wmeParams[ac].wmep_noackPolicy) + if (ieee80211_wme_vap_ac_is_noack(vap, ac)) flags &= ~IWI_DATA_FLAG_NEED_ACK; } Index: dev/iwm/if_iwm.c =================================================================== --- dev/iwm/if_iwm.c (revision 324536) +++ dev/iwm/if_iwm.c (working copy) @@ -6041,6 +6041,7 @@ { #define IWM_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ struct iwm_softc *sc = ic->ic_softc; + struct chanAccParams chp; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct iwm_vap *ivp = IWM_VAP(vap); struct iwm_node *in; @@ -6050,9 +6051,11 @@ if (vap == NULL) return (0); + ieee80211_wme_ic_getparams(ic, &chp); + IEEE80211_LOCK(ic); for (aci = 0; aci < WME_NUM_AC; aci++) - tmp[aci] = ic->ic_wme.wme_chanParams.cap_wmeParams[aci]; + tmp[aci] = chp.cap_wmeParams[aci]; IEEE80211_UNLOCK(ic); IWM_LOCK(sc); Index: dev/iwn/if_iwn.c =================================================================== --- dev/iwn/if_iwn.c (revision 324536) +++ dev/iwn/if_iwn.c (working copy) @@ -5301,17 +5301,19 @@ #define IWN_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ struct iwn_softc *sc = ic->ic_softc; struct iwn_edca_params cmd; + struct chanAccParams chp; int aci; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); + ieee80211_wme_ic_getparams(ic, &chp); + memset(&cmd, 0, sizeof cmd); cmd.flags = htole32(IWN_EDCA_UPDATE); IEEE80211_LOCK(ic); for (aci = 0; aci < WME_NUM_AC; aci++) { - const struct wmeParams *ac = - &ic->ic_wme.wme_chanParams.cap_wmeParams[aci]; + const struct wmeParams *ac = &chp.cap_wmeParams[aci]; cmd.ac[aci].aifsn = ac->wmep_aifsn; cmd.ac[aci].cwmin = htole16(IWN_EXP2(ac->wmep_logcwmin)); cmd.ac[aci].cwmax = htole16(IWN_EXP2(ac->wmep_logcwmax)); Index: dev/mwl/if_mwl.c =================================================================== --- dev/mwl/if_mwl.c (revision 324536) +++ dev/mwl/if_mwl.c (working copy) @@ -2891,11 +2891,15 @@ { #define MWL_EXPONENT_TO_VALUE(v) ((1<sc_ic; + struct chanAccParams chp; struct mwl_txq *txq = sc->sc_ac2q[ac]; - struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac]; + struct wmeParams *wmep; struct mwl_hal *mh = sc->sc_mh; int aifs, cwmin, cwmax, txoplim; + ieee80211_wme_ic_getparams(ic, &chp); + wmep = &chp.cap_wmeParams[ac]; + aifs = wmep->wmep_aifsn; /* XXX in sta mode need to pass log values for cwmin/max */ cwmin = MWL_EXPONENT_TO_VALUE(wmep->wmep_logcwmin); Index: dev/otus/if_otus.c =================================================================== --- dev/otus/if_otus.c (revision 324536) +++ dev/otus/if_otus.c (working copy) @@ -2392,12 +2392,15 @@ { #define EXP2(val) ((1 << (val)) - 1) #define AIFS(val) ((val) * 9 + 10) + struct chanAccParams chp; struct ieee80211com *ic = &sc->sc_ic; const struct wmeParams *edca; + ieee80211_wme_ic_getparams(ic, &chp); + OTUS_LOCK_ASSERT(sc); - edca = ic->ic_wme.wme_chanParams.cap_wmeParams; + edca = chp.cap_wmeParams; /* Set CWmin/CWmax values. */ otus_write(sc, AR_MAC_REG_AC0_CW, Index: dev/ral/rt2661.c =================================================================== --- dev/ral/rt2661.c (revision 324536) +++ dev/ral/rt2661.c (working copy) @@ -1437,7 +1437,6 @@ struct ieee80211_frame *wh; const struct ieee80211_txparam *tp = ni->ni_txparms; struct ieee80211_key *k; - const struct chanAccParams *cap; struct mbuf *mnew; bus_dma_segment_t segs[RT2661_MAX_SCATTER]; uint16_t dur; @@ -1458,10 +1457,8 @@ } rate &= IEEE80211_RATE_VAL; - if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) { - cap = &ic->ic_wme.wme_chanParams; - noack = cap->cap_wmeParams[ac].wmep_noackPolicy; - } + if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) + noack = !! ieee80211_wme_vap_ac_is_noack(vap, ac); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); @@ -2045,10 +2042,13 @@ rt2661_wme_update(struct ieee80211com *ic) { struct rt2661_softc *sc = ic->ic_softc; + struct chanAccParams chp; const struct wmeParams *wmep; - wmep = ic->ic_wme.wme_chanParams.cap_wmeParams; + ieee80211_wme_ic_getparams(ic, &chp); + wmep = chp.cap_wmeParams; + /* XXX: not sure about shifts. */ /* XXX: the reference driver plays with AC_VI settings too. */ Index: dev/ral/rt2860.c =================================================================== --- dev/ral/rt2860.c (revision 324536) +++ dev/ral/rt2860.c (working copy) @@ -3115,11 +3115,14 @@ rt2860_updateedca(struct ieee80211com *ic) { struct rt2860_softc *sc = ic->ic_softc; + struct chanAccParams chp; const struct wmeParams *wmep; int aci; - wmep = ic->ic_wme.wme_chanParams.cap_wmeParams; + ieee80211_wme_ic_getparams(ic, &chp); + wmep = chp.cap_wmeParams; + /* update MAC TX configuration registers */ for (aci = 0; aci < WME_NUM_AC; aci++) { RAL_WRITE(sc, RT2860_EDCA_AC_CFG(aci), Index: dev/rtwn/if_rtwn.c =================================================================== --- dev/rtwn/if_rtwn.c (revision 324536) +++ dev/rtwn/if_rtwn.c (working copy) @@ -1574,6 +1574,7 @@ static int rtwn_wme_update(struct ieee80211com *ic) { + struct chanAccParams chp; struct ieee80211_channel *c = ic->ic_curchan; struct rtwn_softc *sc = ic->ic_softc; struct wmeParams *wmep = sc->cap_wmeParams; @@ -1580,11 +1581,12 @@ uint8_t aifs, acm, slottime; int ac; + ieee80211_wme_ic_getparams(ic, &chp); + /* Prevent possible races. */ IEEE80211_LOCK(ic); /* XXX */ RTWN_LOCK(sc); - memcpy(wmep, ic->ic_wme.wme_chanParams.cap_wmeParams, - sizeof(sc->cap_wmeParams)); + memcpy(wmep, chp.cap_wmeParams, sizeof(sc->cap_wmeParams)); RTWN_UNLOCK(sc); IEEE80211_UNLOCK(ic); Index: dev/usb/wlan/if_rum.c =================================================================== --- dev/usb/wlan/if_rum.c (revision 324536) +++ dev/usb/wlan/if_rum.c (working copy) @@ -2301,11 +2301,14 @@ static int rum_wme_update(struct ieee80211com *ic) { - const struct wmeParams *chanp = - ic->ic_wme.wme_chanParams.cap_wmeParams; + struct chanAccParams chp; + const struct wmeParams *chanp; struct rum_softc *sc = ic->ic_softc; int error = 0; + ieee80211_wme_ic_getparams(ic, &chp); + chanp = chp.cap_wmeParams; + RUM_LOCK(sc); error = rum_write(sc, RT2573_AIFSN_CSR, chanp[WME_AC_VO].wmep_aifsn << 12 | Index: dev/usb/wlan/if_run.c =================================================================== --- dev/usb/wlan/if_run.c (revision 324536) +++ dev/usb/wlan/if_run.c (working copy) @@ -2217,11 +2217,14 @@ static int run_wme_update(struct ieee80211com *ic) { + struct chanAccParams chp; struct run_softc *sc = ic->ic_softc; - const struct wmeParams *ac = - ic->ic_wme.wme_chanParams.cap_wmeParams; + const struct wmeParams *ac; int aci, error = 0; + ieee80211_wme_ic_getparams(ic, &chp); + ac = chp.cap_wmeParams; + /* update MAC TX configuration registers */ RUN_LOCK(sc); for (aci = 0; aci < WME_NUM_AC; aci++) { Index: dev/wpi/if_wpi.c =================================================================== --- dev/wpi/if_wpi.c (revision 324536) +++ dev/wpi/if_wpi.c (working copy) @@ -3521,16 +3521,18 @@ { #define WPI_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ struct wpi_softc *sc = ic->ic_softc; + struct chanAccParams chp; struct wpi_edca_params cmd; int aci, error; + ieee80211_wme_ic_getparams(ic, &chp); + DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); memset(&cmd, 0, sizeof cmd); cmd.flags = htole32(WPI_EDCA_UPDATE); for (aci = 0; aci < WME_NUM_AC; aci++) { - const struct wmeParams *ac = - &ic->ic_wme.wme_chanParams.cap_wmeParams[aci]; + const struct wmeParams *ac = &chp.cap_wmeParams[aci]; cmd.ac[aci].aifsn = ac->wmep_aifsn; cmd.ac[aci].cwmin = htole16(WPI_EXP2(ac->wmep_logcwmin)); cmd.ac[aci].cwmax = htole16(WPI_EXP2(ac->wmep_logcwmax)); Index: net80211/ieee80211_proto.c =================================================================== --- net80211/ieee80211_proto.c (revision 324684) +++ net80211/ieee80211_proto.c (working copy) @@ -1306,6 +1306,12 @@ } } +/* + * Fetch the WME parameters for the given VAP. + * + * When net80211 grows p2p, etc support, this may return different + * parameters for each VAP. + */ void ieee80211_wme_vap_getparams(struct ieee80211vap *vap, struct chanAccParams *wp) { @@ -1313,6 +1319,12 @@ memcpy(wp, &vap->iv_ic->ic_wme.wme_chanParams, sizeof(*wp)); } +/* + * For NICs which only support one set of WME paramaters (ie, softmac NICs) + * there may be different VAP WME parameters but only one is "active". + * This returns the "NIC" WME parameters for the currently active + * context. + */ void ieee80211_wme_ic_getparams(struct ieee80211com *ic, struct chanAccParams *wp) { @@ -1320,6 +1332,26 @@ memcpy(wp, &ic->ic_wme.wme_chanParams, sizeof(*wp)); } +/* + * Return whether to use QoS on a given WME queue. + * + * This is intended to be called from the transmit path of softmac drivers + * which are setting NoAck bits in transmit descriptors. + * + * Ideally this would be set in some transmit field before the packet is + * queued to the driver but net80211 isn't quite there yet. + */ +int +ieee80211_wme_vap_ac_is_noack(struct ieee80211vap *vap, int ac) +{ + /* Bounds/sanity check */ + if (ac < 0 || ac >= WME_NUM_AC) + return (0); + + /* Again, there's only one global context for now */ + return (!! vap->iv_ic->ic_wme.wme_chanParams.cap_wmeParams[ac].wmep_noackPolicy); +} + static void parent_updown(void *arg, int npending) { Index: net80211/ieee80211_proto.h =================================================================== --- net80211/ieee80211_proto.h (revision 324684) +++ net80211/ieee80211_proto.h (working copy) @@ -296,6 +296,7 @@ struct chanAccParams *); void ieee80211_wme_ic_getparams(struct ieee80211com *ic, struct chanAccParams *); +int ieee80211_wme_vap_ac_is_noack(struct ieee80211vap *vap, int ac); /* * Return the WME TID from a QoS frame. If no TID