From b80e7ca55b9a3d2a8e769e0b67787cfb4e6e738d Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Fri, 12 May 2017 05:50:38 +0000 Subject: [PATCH] [iwm] Properly implement iwm_wme_update callback function. * Inspired by iwn(4) and Linux iwlwifi. * Read wme parameters into a buffer within struct iwm_vap in iwm_wme_update(). * If we aren't associated yet, the new settings will soon be sent by iwm_mvm_mac_ctxt_changed() during association. * If we are already associated, explicitly call iwm_mvm_mac_ctxt_changed() from iwm_wme_update() to send the new settings to the firmware. * Change iwm_mvm_ac_to_tx_fifo mapping, to fit the freebsd net80211 WME stream class numbering, instead of Linux's enum ieee80211_ac_numbers. Obtained from: dragonflybsd.git b8bd6cd746d1f45e616ccfcbeed06dfe452a1108 --- sys/dev/iwm/if_iwm.c | 56 +++++++++++++++++++++++++++-------- sys/dev/iwm/if_iwm_mac_ctxt.c | 24 ++++++++++----- sys/dev/iwm/if_iwm_mac_ctxt.h | 2 ++ sys/dev/iwm/if_iwmvar.h | 13 ++++++++ 4 files changed, 75 insertions(+), 20 deletions(-) diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c index 25e4822784e..30249dc7442 100644 --- a/sys/dev/iwm/if_iwm.c +++ b/sys/dev/iwm/if_iwm.c @@ -1533,13 +1533,6 @@ iwm_nic_init(struct iwm_softc *sc) return 0; } -const uint8_t iwm_mvm_ac_to_tx_fifo[] = { - IWM_MVM_TX_FIFO_VO, - IWM_MVM_TX_FIFO_VI, - IWM_MVM_TX_FIFO_BE, - IWM_MVM_TX_FIFO_BK, -}; - static int iwm_enable_txq(struct iwm_softc *sc, int sta_id, int qid, int fifo) { @@ -4258,7 +4251,7 @@ iwm_release(struct iwm_softc *sc, struct iwm_node *in) * from RUN back to SCAN is: * * iwm_mvm_power_mac_disable(sc, in); - * iwm_mvm_mac_ctxt_changed(sc, in); + * iwm_mvm_mac_ctxt_changed(sc, vap); * iwm_mvm_rm_sta(sc, in); * iwm_mvm_update_quotas(sc, NULL); * iwm_mvm_mac_ctxt_changed(sc, in); @@ -4295,7 +4288,7 @@ iwm_release(struct iwm_softc *sc, struct iwm_node *in) iwm_mvm_power_mac_disable(sc, in); - if ((error = iwm_mvm_mac_ctxt_changed(sc, in)) != 0) { + if ((error = iwm_mvm_mac_ctxt_changed(sc, vap)) != 0) { device_printf(sc->sc_dev, "mac ctxt change fail 1 %d\n", error); return error; } @@ -4307,7 +4300,7 @@ iwm_release(struct iwm_softc *sc, struct iwm_node *in) error = iwm_mvm_rm_sta(sc, in); in->in_assoc = 0; iwm_mvm_update_quotas(sc, NULL); - if ((error = iwm_mvm_mac_ctxt_changed(sc, in)) != 0) { + if ((error = iwm_mvm_mac_ctxt_changed(sc, vap)) != 0) { device_printf(sc->sc_dev, "mac ctxt change fail 2 %d\n", error); return error; } @@ -6260,12 +6253,47 @@ iwm_is_valid_ether_addr(uint8_t *addr) } static int -iwm_update_edca(struct ieee80211com *ic) +iwm_wme_update(struct ieee80211com *ic) { +#define IWM_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ struct iwm_softc *sc = ic->ic_softc; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + struct iwm_vap *ivp = IWM_VAP(vap); + struct iwm_node *in; + struct wmeParams tmp[WME_NUM_AC]; + int aci, error; + + if (vap == NULL) + return (0); + + IEEE80211_LOCK(ic); + for (aci = 0; aci < WME_NUM_AC; aci++) + tmp[aci] = ic->ic_wme.wme_chanParams.cap_wmeParams[aci]; + IEEE80211_UNLOCK(ic); + + IWM_LOCK(sc); + for (aci = 0; aci < WME_NUM_AC; aci++) { + const struct wmeParams *ac = &tmp[aci]; + ivp->queue_params[aci].aifsn = ac->wmep_aifsn; + ivp->queue_params[aci].cw_min = IWM_EXP2(ac->wmep_logcwmin); + ivp->queue_params[aci].cw_max = IWM_EXP2(ac->wmep_logcwmax); + ivp->queue_params[aci].edca_txop = + IEEE80211_TXOP_TO_US(ac->wmep_txopLimit); + } + ivp->have_wme = TRUE; + if (ivp->is_uploaded && vap->iv_bss != NULL) { + in = IWM_NODE(vap->iv_bss); + if (in->in_assoc) { + if ((error = iwm_mvm_mac_ctxt_changed(sc, vap)) != 0) { + device_printf(sc->sc_dev, + "%s: failed to update MAC\n", __func__); + } + } + } + IWM_UNLOCK(sc); - device_printf(sc->sc_dev, "%s: called\n", __func__); return (0); +#undef IWM_EXP2 } static void @@ -6322,7 +6350,7 @@ iwm_preinit(void *arg) ic->ic_set_channel = iwm_set_channel; ic->ic_scan_curchan = iwm_scan_curchan; ic->ic_scan_mindwell = iwm_scan_mindwell; - ic->ic_wme.wme_update = iwm_update_edca; + ic->ic_wme.wme_update = iwm_wme_update; ic->ic_parent = iwm_parent; ic->ic_transmit = iwm_transmit; iwm_radiotap_attach(sc); @@ -6380,6 +6408,8 @@ iwm_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, ivp->id = IWM_DEFAULT_MACID; ivp->color = IWM_DEFAULT_COLOR; + ivp->have_wme = FALSE; + ieee80211_ratectl_init(vap); /* Complete setup. */ ieee80211_vap_attach(vap, iwm_media_change, ieee80211_media_status, diff --git a/sys/dev/iwm/if_iwm_mac_ctxt.c b/sys/dev/iwm/if_iwm_mac_ctxt.c index 17fd469fe0d..37725e79fb5 100644 --- a/sys/dev/iwm/if_iwm_mac_ctxt.c +++ b/sys/dev/iwm/if_iwm_mac_ctxt.c @@ -161,6 +161,13 @@ __FBSDID("$FreeBSD$"); * BEGIN mvm/mac-ctxt.c */ +const uint8_t iwm_mvm_ac_to_tx_fifo[] = { + IWM_MVM_TX_FIFO_BE, + IWM_MVM_TX_FIFO_BK, + IWM_MVM_TX_FIFO_VI, + IWM_MVM_TX_FIFO_VO, +}; + static void iwm_mvm_ack_rates(struct iwm_softc *sc, int is2ghz, int *cck_rates, int *ofdm_rates, struct iwm_node *in) @@ -329,17 +336,20 @@ iwm_mvm_mac_ctxt_cmd_common(struct iwm_softc *sc, struct iwm_node *in, * cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA) */ - /* XXX TODO: set wme parameters; also handle getting updated wme parameters */ - for (i = 0; i < IWM_AC_NUM+1; i++) { - int txf = i; + for (i = 0; i < WME_NUM_AC; i++) { + uint8_t txf = iwm_mvm_ac_to_tx_fifo[i]; - cmd->ac[txf].cw_min = htole16(0x0f); - cmd->ac[txf].cw_max = htole16(0x3f); - cmd->ac[txf].aifsn = 1; + cmd->ac[txf].cw_min = htole16(ivp->queue_params[i].cw_min); + cmd->ac[txf].cw_max = htole16(ivp->queue_params[i].cw_max); + cmd->ac[txf].edca_txop = + htole16(ivp->queue_params[i].edca_txop); + cmd->ac[txf].aifsn = ivp->queue_params[i].aifsn; cmd->ac[txf].fifos_mask = (1 << txf); - cmd->ac[txf].edca_txop = 0; } + if (ivp->have_wme) + cmd->qos_flags |= htole32(IWM_MAC_QOS_FLG_UPDATE_EDCA); + if (ic->ic_flags & IEEE80211_F_USEPROT) cmd->protection_flags |= htole32(IWM_MAC_PROT_FLG_TGG_PROTECT); diff --git a/sys/dev/iwm/if_iwm_mac_ctxt.h b/sys/dev/iwm/if_iwm_mac_ctxt.h index 00940536ea0..3abcc20579f 100644 --- a/sys/dev/iwm/if_iwm_mac_ctxt.h +++ b/sys/dev/iwm/if_iwm_mac_ctxt.h @@ -106,6 +106,8 @@ #ifndef __IF_IWM_MAC_CTXT_H__ #define __IF_IWM_MAC_CTXT_H__ +extern const uint8_t iwm_mvm_ac_to_tx_fifo[]; + extern int iwm_mvm_mac_ctxt_add(struct iwm_softc *sc, struct ieee80211vap *vap); extern int iwm_mvm_mac_ctxt_changed(struct iwm_softc *sc, struct ieee80211vap *vap); extern int iwm_mvm_mac_ctxt_remove(struct iwm_softc *sc, struct ieee80211vap *vap); diff --git a/sys/dev/iwm/if_iwmvar.h b/sys/dev/iwm/if_iwmvar.h index e9ec102d96a..c73e2e3de40 100644 --- a/sys/dev/iwm/if_iwmvar.h +++ b/sys/dev/iwm/if_iwmvar.h @@ -377,6 +377,19 @@ struct iwm_vap { uint16_t id; uint16_t color; + + boolean_t have_wme; + /* + * QoS data from net80211, need to store this here + * as net80211 has a separate callback but we need + * to have the data for the MAC context + */ + struct { + uint16_t cw_min; + uint16_t cw_max; + uint16_t edca_txop; + uint8_t aifsn; + } queue_params[WME_NUM_AC]; }; #define IWM_VAP(_vap) ((struct iwm_vap *)(_vap))