[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
This commit is contained in:
Adrian Chadd 2017-05-12 05:50:38 +00:00
parent 702287e43a
commit b80e7ca55b
4 changed files with 75 additions and 20 deletions

View File

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

View File

@ -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);

View File

@ -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);

View File

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