[PATCH] ipw2200: Exponential averaging for signal and noise Level

This patch replaces sliding averaging by exponential averaging for
reporting the wireless statistics for signal and noise level for ipw2200.
See details from: http://www.ces.clemson.edu/linux/ipw2200_averages.shtml

Signed-off-by: Bill Moss <bmoss@clemson.edu>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index bca89cf..a879edb 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -3771,6 +3771,13 @@
 	memset(avg, 0, sizeof(*avg));
 }
 
+#define DEPTH_RSSI 8
+#define DEPTH_NOISE 16
+static s16 exponential_average(s16 prev_avg, s16 val, u8 depth)
+{
+	return ((depth-1)*prev_avg +  val)/depth;
+}
+
 static void average_add(struct average *avg, s16 val)
 {
 	avg->sum -= avg->entries[avg->pos];
@@ -3800,8 +3807,8 @@
 	priv->quality = 0;
 
 	average_init(&priv->average_missed_beacons);
-	average_init(&priv->average_rssi);
-	average_init(&priv->average_noise);
+	priv->exp_avg_rssi = -60;
+	priv->exp_avg_noise = -85 + 0x100;
 
 	priv->last_rate = 0;
 	priv->last_missed_beacons = 0;
@@ -4008,7 +4015,7 @@
 	IPW_DEBUG_STATS("Tx quality   : %3d%% (%u errors, %u packets)\n",
 			tx_quality, tx_failures_delta, tx_packets_delta);
 
-	rssi = average_value(&priv->average_rssi);
+	rssi = priv->exp_avg_rssi;
 	signal_quality =
 	    (100 *
 	     (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) *
@@ -4023,7 +4030,7 @@
 	else if (signal_quality < 1)
 		signal_quality = 0;
 
-	IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n",
+	IPW_ERROR("Signal level : %3d%% (%d dBm)\n",
 			signal_quality, rssi);
 
 	quality = min(beacon_quality,
@@ -4577,11 +4584,10 @@
 
 	case HOST_NOTIFICATION_NOISE_STATS:{
 			if (notif->size == sizeof(u32)) {
-				priv->last_noise =
-				    (u8) (le32_to_cpu(notif->u.noise.value) &
-					  0xff);
-				average_add(&priv->average_noise,
-					    priv->last_noise);
+				priv->exp_avg_noise =
+				    exponential_average(priv->exp_avg_noise,
+				    (u8) (le32_to_cpu(notif->u.noise.value) & 0xff),
+				    DEPTH_NOISE);
 				break;
 			}
 
@@ -7837,9 +7843,9 @@
 				if (network_packet && priv->assoc_network) {
 					priv->assoc_network->stats.rssi =
 					    stats.rssi;
-					average_add(&priv->average_rssi,
-						    stats.rssi);
-					priv->last_rx_rssi = stats.rssi;
+					priv->exp_avg_rssi =
+					    exponential_average(priv->exp_avg_rssi,
+					    stats.rssi, DEPTH_RSSI);
 				}
 
 				IPW_DEBUG_RX("Frame: len=%u\n",
@@ -9579,8 +9585,8 @@
 	}
 
 	wstats->qual.qual = priv->quality;
-	wstats->qual.level = average_value(&priv->average_rssi);
-	wstats->qual.noise = average_value(&priv->average_noise);
+	wstats->qual.level = priv->exp_avg_rssi;
+	wstats->qual.noise = priv->exp_avg_noise;
 	wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
 	    IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM;