From owner-svn-src-all@freebsd.org Thu Jan 24 03:41:10 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A8BFA14BFE4C; Thu, 24 Jan 2019 03:41:10 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4C30975560; Thu, 24 Jan 2019 03:41:10 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4071422AAC; Thu, 24 Jan 2019 03:41:10 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x0O3fAZn022112; Thu, 24 Jan 2019 03:41:10 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x0O3f9jX022110; Thu, 24 Jan 2019 03:41:09 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201901240341.x0O3f9jX022110@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Thu, 24 Jan 2019 03:41:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r343373 - head/sys/dev/iwm X-SVN-Group: head X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: head/sys/dev/iwm X-SVN-Commit-Revision: 343373 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 4C30975560 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.96 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.96)[-0.959,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_LONG(-1.00)[-1.000,0] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 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: Thu, 24 Jan 2019 03:41:11 -0000 Author: kevans Date: Thu Jan 24 03:41:09 2019 New Revision: 343373 URL: https://svnweb.freebsd.org/changeset/base/343373 Log: if_iwm - Update firmware rs table, instead of indexing the table in tx cmds. * Rather than providing a non-zero index into the firmware RS table, we should always use index 0 and update the firmware RS table whenever our chosen tx rate for data-frames changes. * Send IWM_LQ_CMD updates when the tx rate gets updated by the net80211 rate control (which is after we tell the tx status to the net80211 rate-control in iwm_mvm_rx_tx_cmd_single()). * Disregard frames transferred with a different tx rate than the currently selected rate for the rate-control calculations. This way we avoid counting management frames (which are sent at a slow, and fixed rate), as well as frames we added to the tx queue just before a new IWM_LQ_CMD update took effect. Submitted by: Augustin Cavalier (Haiku) Obtained from: DragonFlyBSD (5d6b465e288ac5b52d7115688d4e6516acbbea1c) Modified: head/sys/dev/iwm/if_iwm.c head/sys/dev/iwm/if_iwmvar.h Modified: head/sys/dev/iwm/if_iwm.c ============================================================================== --- head/sys/dev/iwm/if_iwm.c Thu Jan 24 01:08:37 2019 (r343372) +++ head/sys/dev/iwm/if_iwm.c Thu Jan 24 03:41:09 2019 (r343373) @@ -353,7 +353,9 @@ static int iwm_release(struct iwm_softc *, struct iwm_ static struct ieee80211_node * iwm_node_alloc(struct ieee80211vap *, const uint8_t[IEEE80211_ADDR_LEN]); -static void iwm_setrates(struct iwm_softc *, struct iwm_node *); +static uint8_t iwm_rate_from_ucode_rate(uint32_t); +static int iwm_rate2ridx(struct iwm_softc *, uint8_t); +static void iwm_setrates(struct iwm_softc *, struct iwm_node *, int); static int iwm_media_change(struct ifnet *); static int iwm_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void iwm_endscan_cb(void *, int); @@ -3317,7 +3319,11 @@ iwm_mvm_rx_tx_cmd_single(struct iwm_softc *sc, struct struct iwm_mvm_tx_resp *tx_resp = (void *)pkt->data; struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct ieee80211_node *ni = &in->in_ni; + struct ieee80211vap *vap = ni->ni_vap; int status = le16toh(tx_resp->status.status) & IWM_TX_STATUS_MSK; + int new_rate, cur_rate = vap->iv_bss->ni_txrate; + boolean_t rate_matched; + uint8_t tx_resp_rate; KASSERT(tx_resp->frame_count == 1, ("too many frames")); @@ -3333,6 +3339,17 @@ iwm_mvm_rx_tx_cmd_single(struct iwm_softc *sc, struct le32toh(tx_resp->initial_rate), (int) le16toh(tx_resp->wireless_media_time)); + tx_resp_rate = iwm_rate_from_ucode_rate(le32toh(tx_resp->initial_rate)); + + /* For rate control, ignore frames sent at different initial rate */ + rate_matched = (tx_resp_rate != 0 && tx_resp_rate == cur_rate); + + if (tx_resp_rate != 0 && cur_rate != 0 && !rate_matched) { + IWM_DPRINTF(sc, IWM_DEBUG_TXRATE, + "tx_resp_rate doesn't match ni_txrate (tx_resp_rate=%u " + "ni_txrate=%d)\n", tx_resp_rate, cur_rate); + } + txs->flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY | IEEE80211_RATECTL_STATUS_LONG_RETRY; txs->short_retries = tx_resp->failure_rts; @@ -3356,8 +3373,19 @@ iwm_mvm_rx_tx_cmd_single(struct iwm_softc *sc, struct } else { txs->status = IEEE80211_RATECTL_TX_SUCCESS; } - ieee80211_ratectl_tx_complete(ni, txs); + if (rate_matched) { + ieee80211_ratectl_tx_complete(ni, txs); + + int rix = ieee80211_ratectl_rate(vap->iv_bss, NULL, 0); + new_rate = vap->iv_bss->ni_txrate; + if (new_rate != 0 && new_rate != cur_rate) { + struct iwm_node *in = IWM_NODE(vap->iv_bss); + iwm_setrates(sc, in, rix); + iwm_mvm_send_lq_cmd(sc, &in->in_lq, FALSE); + } + } + return (txs->status != IEEE80211_RATECTL_TX_SUCCESS); } @@ -3482,38 +3510,7 @@ iwm_update_sched(struct iwm_softc *sc, int qid, int id } #endif -/* - * Take an 802.11 (non-n) rate, find the relevant rate - * table entry. return the index into in_ridx[]. - * - * The caller then uses that index back into in_ridx - * to figure out the rate index programmed /into/ - * the firmware for this given node. - */ static int -iwm_tx_rateidx_lookup(struct iwm_softc *sc, struct iwm_node *in, - uint8_t rate) -{ - int i; - uint8_t r; - - for (i = 0; i < nitems(in->in_ridx); i++) { - r = iwm_rates[in->in_ridx[i]].rate; - if (rate == r) - return (i); - } - - IWM_DPRINTF(sc, IWM_DEBUG_XMIT | IWM_DEBUG_TXRATE, - "%s: couldn't find an entry for rate=%d\n", - __func__, - rate); - - /* XXX Return the first */ - /* XXX TODO: have it return the /lowest/ */ - return (0); -} - -static int iwm_tx_rateidx_global_lookup(struct iwm_softc *sc, uint8_t rate) { int i; @@ -3565,22 +3562,15 @@ iwm_tx_fill_cmd(struct iwm_softc *sc, struct iwm_node IWM_DPRINTF(sc, IWM_DEBUG_TXRATE, "%s: FIXED_RATE (%d)\n", __func__, tp->ucastrate); } else { - int i; - /* for data frames, use RS table */ IWM_DPRINTF(sc, IWM_DEBUG_TXRATE, "%s: DATA\n", __func__); - /* XXX pass pktlen */ - (void) ieee80211_ratectl_rate(ni, NULL, 0); - i = iwm_tx_rateidx_lookup(sc, in, ni->ni_txrate); - ridx = in->in_ridx[i]; + ridx = iwm_rate2ridx(sc, ni->ni_txrate); + if (ridx == -1) + ridx = 0; /* This is the index into the programmed table */ - tx->initial_rate_index = i; + tx->initial_rate_index = 0; tx->tx_flags |= htole32(IWM_TX_CMD_FLG_STA_RATE); - - IWM_DPRINTF(sc, IWM_DEBUG_XMIT | IWM_DEBUG_TXRATE, - "%s: start with i=%d, txrate %d\n", - __func__, i, iwm_rates[ridx].rate); } IWM_DPRINTF(sc, IWM_DEBUG_XMIT | IWM_DEBUG_TXRATE, @@ -4165,6 +4155,19 @@ iwm_node_alloc(struct ieee80211vap *vap, const uint8_t M_NOWAIT | M_ZERO); } +static uint8_t +iwm_rate_from_ucode_rate(uint32_t rate_n_flags) +{ + uint8_t plcp = rate_n_flags & 0xff; + int i; + + for (i = 0; i <= IWM_RIDX_MAX; i++) { + if (iwm_rates[i].plcp == plcp) + return iwm_rates[i].rate; + } + return 0; +} + uint8_t iwm_ridx2rate(struct ieee80211_rateset *rs, int ridx) { @@ -4180,15 +4183,36 @@ iwm_ridx2rate(struct ieee80211_rateset *rs, int ridx) return 0; } +static int +iwm_rate2ridx(struct iwm_softc *sc, uint8_t rate) +{ + int i; + + for (i = 0; i <= IWM_RIDX_MAX; i++) { + if (iwm_rates[i].rate == rate) + return i; + } + + device_printf(sc->sc_dev, + "%s: WARNING: device rate for %u not found!\n", + __func__, rate); + + return -1; +} + + static void -iwm_setrates(struct iwm_softc *sc, struct iwm_node *in) +iwm_setrates(struct iwm_softc *sc, struct iwm_node *in, int rix) { struct ieee80211_node *ni = &in->in_ni; struct iwm_lq_cmd *lq = &in->in_lq; - int nrates = ni->ni_rates.rs_nrates; + struct ieee80211_rateset *rs = &ni->ni_rates; + int nrates = rs->rs_nrates; int i, ridx, tab = 0; // int txant = 0; + KASSERT(rix >= 0 && rix < nrates, ("invalid rix")); + if (nrates > nitems(lq->rs_table)) { device_printf(sc->sc_dev, "%s: node supports %d rates, driver handles " @@ -4200,45 +4224,11 @@ iwm_setrates(struct iwm_softc *sc, struct iwm_node *in "%s: node supports 0 rates, odd!\n", __func__); return; } + nrates = imin(rix + 1, nrates); - /* - * XXX .. and most of iwm_node is not initialised explicitly; - * it's all just 0x0 passed to the firmware. - */ - - /* first figure out which rates we should support */ - /* XXX TODO: this isn't 11n aware /at all/ */ - memset(&in->in_ridx, -1, sizeof(in->in_ridx)); IWM_DPRINTF(sc, IWM_DEBUG_TXRATE, "%s: nrates=%d\n", __func__, nrates); - /* - * Loop over nrates and populate in_ridx from the highest - * rate to the lowest rate. Remember, in_ridx[] has - * IEEE80211_RATE_MAXSIZE entries! - */ - for (i = 0; i < min(nrates, IEEE80211_RATE_MAXSIZE); i++) { - int rate = ni->ni_rates.rs_rates[(nrates - 1) - i] & IEEE80211_RATE_VAL; - - /* Map 802.11 rate to HW rate index. */ - for (ridx = 0; ridx <= IWM_RIDX_MAX; ridx++) - if (iwm_rates[ridx].rate == rate) - break; - if (ridx > IWM_RIDX_MAX) { - device_printf(sc->sc_dev, - "%s: WARNING: device rate for %d not found!\n", - __func__, rate); - } else { - IWM_DPRINTF(sc, IWM_DEBUG_TXRATE, - "%s: rate: i: %d, rate=%d, ridx=%d\n", - __func__, - i, - rate, - ridx); - in->in_ridx[i] = ridx; - } - } - /* then construct a lq_cmd based on those */ memset(lq, 0, sizeof(*lq)); lq->sta_id = IWM_STATION_ID; @@ -4262,13 +4252,15 @@ iwm_setrates(struct iwm_softc *sc, struct iwm_node *in * Note that we add the rates in the highest rate first * (opposite of ni_rates). */ - /* - * XXX TODO: this should be looping over the min of nrates - * and LQ_MAX_RETRY_NUM. Sigh. - */ for (i = 0; i < nrates; i++) { + int rate = rs->rs_rates[rix - i] & IEEE80211_RATE_VAL; int nextant; + /* Map 802.11 rate to HW rate index. */ + ridx = iwm_rate2ridx(sc, rate); + if (ridx == -1) + continue; + #if 0 if (txant == 0) txant = iwm_mvm_get_valid_tx_ant(sc); @@ -4277,12 +4269,6 @@ iwm_setrates(struct iwm_softc *sc, struct iwm_node *in #else nextant = iwm_mvm_get_valid_tx_ant(sc); #endif - /* - * Map the rate id into a rate index into - * our hardware table containing the - * configuration to use for this rate. - */ - ridx = in->in_ridx[i]; tab = iwm_rates[ridx].plcp; tab |= nextant << IWM_RATE_MCS_ANT_POS; if (IWM_RIDX_IS_CCK(ridx)) @@ -4474,7 +4460,8 @@ iwm_newstate(struct ieee80211vap *vap, enum ieee80211_ iwm_mvm_enable_beacon_filter(sc, ivp); iwm_mvm_power_update_mac(sc); iwm_mvm_update_quotas(sc, ivp); - iwm_setrates(sc, in); + int rix = ieee80211_ratectl_rate(&in->in_ni, NULL, 0); + iwm_setrates(sc, in, rix); if ((error = iwm_mvm_send_lq_cmd(sc, &in->in_lq, TRUE)) != 0) { device_printf(sc->sc_dev, Modified: head/sys/dev/iwm/if_iwmvar.h ============================================================================== --- head/sys/dev/iwm/if_iwmvar.h Thu Jan 24 01:08:37 2019 (r343372) +++ head/sys/dev/iwm/if_iwmvar.h Thu Jan 24 03:41:09 2019 (r343373) @@ -404,8 +404,6 @@ struct iwm_node { int in_assoc; struct iwm_lq_cmd in_lq; - - uint8_t in_ridx[IEEE80211_RATE_MAXSIZE]; }; #define IWM_NODE(_ni) ((struct iwm_node *)(_ni))