Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147779893
D53780.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D53780.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D53780: iwx: clean up / document noise floor and RSSI fetching
Attached
Detach File
Event Timeline
Log In to Comment