Page MenuHomeFreeBSD

D53780.diff
No OneTemporary

D53780.diff

diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c
--- a/sys/dev/iwx/if_iwx.c
+++ b/sys/dev/iwx/if_iwx.c
@@ -432,7 +432,7 @@
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 *,
@@ -4208,6 +4208,17 @@
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)
@@ -4226,6 +4237,26 @@
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)
@@ -4253,12 +4284,18 @@
}
/*
- * 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++) {
@@ -4270,7 +4307,14 @@
}
/* 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
@@ -4666,9 +4710,8 @@
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;
@@ -4685,9 +4728,19 @@
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;
@@ -9129,11 +9182,16 @@
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;
}
@@ -10574,6 +10632,9 @@
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
--- a/sys/dev/iwx/if_iwxreg.h
+++ b/sys/dev/iwx/if_iwxreg.h
@@ -7902,6 +7902,23 @@
#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))

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 14, 2:40 PM (59 m, 33 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29673835
Default Alt Text
D53780.diff (5 KB)

Event Timeline