s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */
};
+/**
+ * struct avg_val - Helper structure for average calculation
+ * @avg: contains the actual average value
+ * @avg_weight: is used internally during calculation to prevent rounding errors
+ */
+struct ath5k_avg_val {
+ int avg;
+ int avg_weight;
+};
/***************************************\
HARDWARE ABSTRACTION LAYER STRUCTURE
struct ath5k_nfcal_hist ah_nfcal_hist;
+ /* average beacon RSSI in our BSS (used by ANI) */
+ struct ath5k_avg_val ah_beacon_rssi_avg;
+
/* noise floor from last periodic calibration */
s32 ah_noise_floor;
return retval;
}
+#define AVG_SAMPLES 8
+#define AVG_FACTOR 1000
+
+/**
+ * ath5k_moving_average - Exponentially weighted moving average
+ * @avg: average structure
+ * @val: current value
+ *
+ * This implementation make use of a struct ath5k_avg_val to prevent rounding
+ * errors.
+ */
+static inline struct ath5k_avg_val
+ath5k_moving_average(const struct ath5k_avg_val avg, const int val)
+{
+ struct ath5k_avg_val new;
+ new.avg_weight = avg.avg_weight ?
+ (((avg.avg_weight * ((AVG_SAMPLES) - 1)) +
+ (val * (AVG_FACTOR))) / (AVG_SAMPLES)) :
+ (val * (AVG_FACTOR));
+ new.avg = new.avg_weight / (AVG_FACTOR);
+ return new;
+}
+
#endif
}
}
+static void
+ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
+{
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+ struct ath5k_hw *ah = sc->ah;
+ struct ath_common *common = ath5k_hw_common(ah);
+
+ /* only beacons from our BSSID */
+ if (!ieee80211_is_beacon(mgmt->frame_control) ||
+ memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0)
+ return;
+
+ ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg,
+ rssi);
+
+ /* in IBSS mode we should keep RSSI statistics per neighbour */
+ /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */
+}
+
/*
* Compute padding position. skb must contains an IEEE 802.11 frame
*/
ath5k_debug_dump_skb(sc, skb, "RX ", 0);
+ ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi);
+
/* check beacons in IBSS mode */
if (sc->opmode == NL80211_IFTYPE_ADHOC)
ath5k_check_ibss_tsf(sc, skb, rxs);