From nobody Tue May 19 05:43:37 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gKNrT6RLbz6dqW3 for ; Tue, 19 May 2026 05:43:37 +0000 (UTC) (envelope-from git@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) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gKNrT5RR1z3b4t for ; Tue, 19 May 2026 05:43:37 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779169417; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5tl//C4uT3XEVWRQkzRqLVNvjoCJe5iIfyuu1N+3q/w=; b=ILiZeHxNrk7XxCGrvMPbfe3wh62plFu5hzjqBVktGUDPpbsql9rZJWVisUZPJBbno9cXYC ySzmeuN08/sdatS4hvycbA/KOv2SS83wT1oO48Odu2Z69ajhkwZfxClIZGdkHLSbEtTGob FSpvITOZHh+SEpksLVykkVfzwm83qjMhCrTCzTaCscerLZngg/RhvmEFLFddJTlKpMeYRC UJJpAmu6MOOhKWcoChhDotKsVXu5wXgs1cJmCFfw8ajPXfujG9P1j9UvnTqS5MQK/Ag4Kq h39g0jRWVjKXI5khy0pcE6jmMgPjqmY0eWnBmhJD5q8BCvLXbptzqM2n9gcUcw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1779169417; a=rsa-sha256; cv=none; b=s2cepf9BCKa7e4qitVNr0PjKweiueCZs1lKKN53ih69yeCWSPrbiMxEvkgjYd4SMpeYCpy EKlApO2cCRF+PKlIekIiklqnz2RH3/SFvlvVP6oK/J8/9awyceSkKk0gFDJNTwWpy9yXdt 20Ql9NHIJTfZSkq0JaqhOApxu4iH4GO/SSEPLHXzHiyU0xjE34XRS0oe2U617f2lca17D0 W9GDIO1pEp+qj+YHcjYzpjCUTLGALm09sWv1Y0CRxB7WdcmEA0Y13yTQHjrL89kHyut3u3 mEL37VPH/Pu16U+vEADMMY95uSmMpxhAP3zBkPuRrK7e+9a+X9M2uf2VKiKziQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779169417; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5tl//C4uT3XEVWRQkzRqLVNvjoCJe5iIfyuu1N+3q/w=; b=ko0v67St6C20K9lw0SXwEpjfCjQT29rqjB8jVQrkpb2FVvuz6KMsq94Whv8jaP6fuJEfur fE4C558rgo9m5FCRNxmAh/ZX7YWbvnuDtXVroQkeML4MQqP0Z8jq8/86e8z0o1G17naKQ1 fVcnHLZEToDphpa28yeT6h995dbpzrkkjYOPI9PY2lrdsDj6NvIkYcYyUYHgJbsdMap0qz Df3imggc+0pxkPMQpDMmYlEwrTkfNOtV40gmI3JEU7svJ4db9torPS8Ne/eUbHNQI3blGD Qwa7nfWuBtHe3mpjpXIkd3/TS1O6Alc3kfgKVHO/eM+7G2v0f6COdpJGQcU8vw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gKNrT527kz11dM for ; Tue, 19 May 2026 05:43:37 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1e29a by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 19 May 2026 05:43:37 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Adrian Chadd Subject: git: e56f7becc7ef - main - iwx: clean up / document noise floor and RSSI fetching List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: adrian X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e56f7becc7efe05acbb08162961dca574b152720 Auto-Submitted: auto-generated Date: Tue, 19 May 2026 05:43:37 +0000 Message-Id: <6a0bf889.1e29a.6f1dfea2@gitrepo.freebsd.org> The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=e56f7becc7efe05acbb08162961dca574b152720 commit e56f7becc7efe05acbb08162961dca574b152720 Author: Adrian Chadd AuthorDate: 2025-11-16 03:13:59 +0000 Commit: Adrian Chadd CommitDate: 2026-05-19 05:27:59 +0000 iwx: clean up / document noise floor and RSSI fetching * Document what iwx_rxmq_get_signal_strength() is doing in a comment, noting what the firmware returns and what math is being done on it to turn it into a dBm value. * Document what iwx_get_noise() is supposed to do, that we can't just go do math with log numbers like we're doing, but also that we're seeing zeros in this firmware (AX210), which may mean we're decoding using the wrong structs. * Swizzle around the RSSI calculation as a function, add min/max RSSI values, and calculate RSSI against the noise floor. * And handle the lowest noise floor value - it can't be -127dBm as that will throw things off. Cap it at -100dBm which is a little lower than the thermal noise floor at 20MHz (-98dBm), but it matches IWX_MIN_DBM. Differential Revision: https://reviews.freebsd.org/D53780 --- sys/dev/iwx/if_iwx.c | 83 ++++++++++++++++++++++++++++++++++++++++++------- sys/dev/iwx/if_iwxreg.h | 17 ++++++++++ 2 files changed, 89 insertions(+), 11 deletions(-) diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c index 03ef775205e7..372fa440466c 100644 --- a/sys/dev/iwx/if_iwx.c +++ b/sys/dev/iwx/if_iwx.c @@ -433,7 +433,7 @@ static int iwx_rx_addbuf(struct iwx_softc *, int, int); static int iwx_rxmq_get_signal_strength(struct iwx_softc *, struct iwx_rx_mpdu_desc *); static void iwx_rx_rx_phy_cmd(struct iwx_softc *, struct iwx_rx_packet *, struct iwx_rx_data *); -static int iwx_get_noise(const struct iwx_statistics_rx_non_phy *); +static int iwx_get_noise(struct iwx_softc *, const struct iwx_statistics_rx_non_phy *); static int iwx_rx_hwdecrypt(struct iwx_softc *, struct mbuf *, uint32_t); #if 0 int iwx_ccmp_decap(struct iwx_softc *, struct mbuf *, @@ -4209,6 +4209,17 @@ iwx_rx_addbuf(struct iwx_softc *sc, int size, int idx) return 0; } +/* + * @brief Return a single signal strength for the given frame. + * + * The firmware communicates up an energy field which is the negative of + * the dBm value. Ie, the number is positive and it increases as the + * signal level decreases. + * + * Fetch the two values, map 0 (inactive antenna) to -256 dBm which is a + * very small number, negate a non-zero value so it's mapped into a dBm + * value, then choose the maximum value to return. + */ static int iwx_rxmq_get_signal_strength(struct iwx_softc *sc, struct iwx_rx_mpdu_desc *desc) @@ -4227,6 +4238,26 @@ iwx_rxmq_get_signal_strength(struct iwx_softc *sc, return MAX(energy_a, energy_b); } +/** + * @brief Calculate an RSSI from the given signal level and noise floor. + * + * This calculates an RSSI and clamps it at IWX_RSSI_MINIMUM at the lower level + * and IWX_RSSI_MAXIMUM at the upper level. + * + * All units are in dBm. + */ +static int +iwx_calculate_rssi(struct iwx_softc *sc, int ss, int nf) +{ + int rssi = (ss - nf); + if (rssi < IWX_RSSI_MINIMUM) + rssi = IWX_RSSI_MINIMUM; + else if (rssi > IWX_RSSI_MAXIMUM) + rssi = IWX_RSSI_MAXIMUM; + + return (rssi); +} + static int iwx_rxmq_get_chains(struct iwx_softc *sc, struct iwx_rx_mpdu_desc *desc) @@ -4254,12 +4285,18 @@ iwx_rx_rx_phy_cmd(struct iwx_softc *sc, struct iwx_rx_packet *pkt, } /* - * Retrieve the average noise (in dBm) among receivers. + * @brief Retrieve the average noise (in dBm) among receivers. + * + * Note: This routine calculates the noise floor sum incorrectly, as + * you can't just linearly add the logarithm based dB units together. + * + * If no noise floor is available then this routine will return -127. */ static int -iwx_get_noise(const struct iwx_statistics_rx_non_phy *stats) +iwx_get_noise(struct iwx_softc *sc, + const struct iwx_statistics_rx_non_phy *stats) { - int i, total, nbant, noise; + int i, total, nbant, noise, ret; total = nbant = noise = 0; for (i = 0; i < 3; i++) { @@ -4271,7 +4308,14 @@ iwx_get_noise(const struct iwx_statistics_rx_non_phy *stats) } /* There should be at least one antenna but check anyway. */ - return (nbant == 0) ? -127 : (total / nbant) - 107; + if (nbant == 0) + ret = -127; + else if (total == 0) + ret = -127; + else + ret = (total / nbant) - 127; + + return (ret); } #if 0 @@ -4669,9 +4713,8 @@ iwx_rx_mpdu_mq(struct iwx_softc *sc, struct mbuf *m, void *pktdata, phy_info = le16toh(desc->phy_info); + /* note: RSSI here is absolute signal strength, not relative */ rssi = iwx_rxmq_get_signal_strength(sc, desc); - rssi = (0 - IWX_MIN_DBM) + rssi; /* normalize */ - rssi = MIN(rssi, (IWX_MAX_DBM - IWX_MIN_DBM)); /* clip to max. 100% */ memset(&rxs, 0, sizeof(rxs)); rxs.r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ; @@ -4688,9 +4731,19 @@ iwx_rx_mpdu_mq(struct iwx_softc *sc, struct mbuf *m, void *pktdata, if (rxs.c_chain != 0) rxs.r_flags |= IEEE80211_R_C_CHAIN; - /* rssi is in 1/2db units */ - rxs.c_rssi = rssi * 2; - rxs.c_nf = sc->sc_noise; + /* noise floor is in 1dB units */ + if (sc->sc_noise < IWX_DEFAULT_NF) + /* + * For now choose /a/ default, net80211 expects nf to be passed + * in various places and older drivers fake NF values where + * needed. + */ + rxs.c_nf = IWX_DEFAULT_NF; + else + rxs.c_nf = sc->sc_noise; + + /* rssi is in 1/2db units relative to the noise floor */ + rxs.c_rssi = iwx_calculate_rssi(sc, rssi, rxs.c_nf) * 2; if (pad) { rxs.c_pktflags |= IEEE80211_RX_F_DECRYPTED; @@ -9142,11 +9195,16 @@ iwx_rx_pkt(struct iwx_softc *sc, struct iwx_rx_data *data, struct mbuf *ml) break; } + /* + * TODO: is this the right struct to use? Look at what + * mvm is doing for statistics notification (eg + * iwl_mvm_handle_rx_statistics() . + */ case IWX_STATISTICS_NOTIFICATION: { struct iwx_notif_statistics *stats; SYNC_RESP_STRUCT(stats, pkt); memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats)); - sc->sc_noise = iwx_get_noise(&stats->rx.general); + sc->sc_noise = iwx_get_noise(sc, &stats->rx.general); break; } @@ -10587,6 +10645,9 @@ iwx_attach(device_t dev) mbufq_init(&rxba->entries[j].frames, ifqmaxlen); } + /* Initialize to something to have a chance to get S:N values. */ + sc->sc_noise = IWX_DEFAULT_NF; + sc->sc_preinit_hook.ich_func = iwx_attach_hook; sc->sc_preinit_hook.ich_arg = sc; if (config_intrhook_establish(&sc->sc_preinit_hook) != 0) { diff --git a/sys/dev/iwx/if_iwxreg.h b/sys/dev/iwx/if_iwxreg.h index f3d1f078b48e..3f161b627a5f 100644 --- a/sys/dev/iwx/if_iwxreg.h +++ b/sys/dev/iwx/if_iwxreg.h @@ -7902,6 +7902,23 @@ iwx_rx_packet_payload_len(const struct iwx_rx_packet *pkt) #define IWX_MIN_DBM -100 #define IWX_MAX_DBM -33 /* realistic guess */ +/* + * NF values for various channel widths at 20C + * + * 20MHz - -98 dBm + * 40MHz - -94 dBm + * 80MHz - -92 dBm + * 160MHz - -88 dBm + * 320MHz - -85 dBm + */ +#define IWX_DEFAULT_NF -100 +/* + * Note; RSSI is for net80211, and it's calculated against the noise floor + * as a reference. + */ +#define IWX_RSSI_MINIMUM -10 +#define IWX_RSSI_MAXIMUM 60 + #define IWX_READ(sc, reg) \ bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))