Search Linux Wireless

[PATCH] mac80211: report per-chain signal values through ethtool.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ben Greear <greearb@xxxxxxxxxxxxxxx>

Combine them into a u64, each byte is one chain.
Re-work the way that APs averaged stats to be more
efficient.

Signed-off-by: Ben Greear <greearb@xxxxxxxxxxxxxxx>
---
 net/mac80211/ethtool.c | 103 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 93 insertions(+), 10 deletions(-)

diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c
index 028ffe1a4d2d..10a9a30bcbf3 100644
--- a/net/mac80211/ethtool.c
+++ b/net/mac80211/ethtool.c
@@ -64,6 +64,7 @@ static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
 	"tx_packets", "tx_bytes",
 	"tx_filtered", "tx_retry_failed", "tx_retries",
 	"sta_state", "txrate", "rxrate", "signal", "signal_beacon",
+	"signal_chains", "signal_chains_avg",
 	"channel", "noise", "ch_time", "ch_time_busy",
 	"ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
 };
@@ -96,6 +97,7 @@ static void ieee80211_get_stats2(struct net_device *dev,
 	struct station_info sinfo;
 	struct survey_info survey;
 	int i, q;
+	int z;
 #define STA_STATS_SURVEY_LEN 7
 
 	memset(data, 0, sizeof(u64) * STA_STATS_LEN);
@@ -154,14 +156,49 @@ static void ieee80211_get_stats2(struct net_device *dev,
 		if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG))
 			data[i] = (u8)sinfo.rx_beacon_signal_avg;
 		i++;
+
+		if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
+			int mn = min_t(int, sizeof(u64), ARRAY_SIZE(sinfo.chain_signal));
+			u64 accum = (u8)sinfo.chain_signal[0];
+
+			mn = min_t(int, mn, sinfo.chains);
+			for (z = 1; z < mn; z++) {
+				u64 csz = sinfo.chain_signal[z] & 0xFF;
+				u64 cs = csz << (8 * z);
+
+				accum |= cs;
+			}
+			data[i] = accum;
+		}
+		i++;
+
+		if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
+			int mn = min_t(int, sizeof(u64), ARRAY_SIZE(sinfo.chain_signal_avg));
+			u64 accum = (u8)sinfo.chain_signal_avg[0];
+
+			for (z = 1; z < mn; z++) {
+				u64 csz = sinfo.chain_signal_avg[z] & 0xFF;
+				u64 cs = csz << (8 * z);
+
+				accum |= cs;
+			}
+			data[i] = accum;
+		}
+		i++;
 	} else {
 		int amt_tx = 0;
 		int amt_rx = 0;
 		int amt_sig = 0;
+		s16 amt_accum_chain[8] = {0};
+		s16 amt_accum_chain_avg[8] = {0};
 		s64 tx_accum = 0;
 		s64 rx_accum = 0;
 		s64 sig_accum = 0;
 		s64 sig_accum_beacon = 0;
+		s64 sig_accum_chain[8] = {0};
+		s64 sig_accum_chain_avg[8] = {0};
+		int start_accum_idx = 0;
+
 		list_for_each_entry(sta, &local->sta_list, list) {
 			/* Make sure this station belongs to the proper dev */
 			if (sta->sdata->dev != dev)
@@ -173,35 +210,48 @@ static void ieee80211_get_stats2(struct net_device *dev,
 			ADD_STA_STATS(sta);
 
 			i++; /* skip sta state */
+			start_accum_idx = i;
 
 			if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
 				tx_accum += 100000ULL *
 					cfg80211_calculate_bitrate(&sinfo.txrate);
 				amt_tx++;
 			}
-			if (amt_tx)
-				data[i] = mac_div(tx_accum, amt_tx);
-			i++;
 
 			if (sinfo.filled & BIT(NL80211_STA_INFO_RX_BITRATE)) {
 				rx_accum += 100000ULL *
 					cfg80211_calculate_bitrate(&sinfo.rxrate);
 				amt_rx++;
 			}
-			if (amt_rx)
-				data[i] = mac_div(rx_accum, amt_rx);
-			i++;
 
 			if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL_AVG)) {
 				sig_accum += sinfo.signal_avg;
 				sig_accum_beacon += sinfo.rx_beacon_signal_avg;
 				amt_sig++;
 			}
-			if (amt_sig) {
-				data[i] = (mac_div(sig_accum, amt_sig) & 0xFF);
-				data[i+1] = (mac_div(sig_accum_beacon, amt_sig) & 0xFF);
+
+			if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
+				int mn = min_t(int, sizeof(u64), ARRAY_SIZE(sinfo.chain_signal));
+
+				mn = min_t(int, mn, sinfo.chains);
+				for (z = 0; z < mn; z++) {
+					sig_accum_chain[z] += sinfo.chain_signal[z];
+					amt_accum_chain[z]++;
+				}
 			}
-			i += 2;
+			i++;
+
+			if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
+				int mn;
+
+				mn = min_t(int, sizeof(u64), ARRAY_SIZE(sinfo.chain_signal_avg));
+				mn = min_t(int, mn, sinfo.chains);
+				for (z = 0; z < mn; z++) {
+					sig_accum_chain_avg[z] += sinfo.chain_signal_avg[z];
+					amt_accum_chain_avg[z]++;
+				}
+			}
+			i++;
 
 			/*pr_err("sta: %p (%s) sig_accum: %ld  amt-sig: %d filled: 0x%x:%08x rpt-sig-avg: %d  i: %d  div: %d sinfo.signal_avg: %d\n",
 			       sta, sta->sdata->name, (long)(sig_accum), amt_sig, (u32)(sinfo.filled >> 32),
@@ -209,6 +259,39 @@ static void ieee80211_get_stats2(struct net_device *dev,
 			       sinfo.signal_avg);*/
 
 		}
+
+		/* Do averaging */
+		i = start_accum_idx;
+
+		if (amt_tx)
+			data[i] = mac_div(tx_accum, amt_tx);
+		i++;
+
+		if (amt_rx)
+			data[i] = mac_div(rx_accum, amt_rx);
+		i++;
+
+		if (amt_sig) {
+			data[i] = (mac_div(sig_accum, amt_sig) & 0xFF);
+			data[i + 1] = (mac_div(sig_accum_beacon, amt_sig) & 0xFF);
+		}
+		i += 2;
+
+		for (z = 0; z < sizeof(u64); z++) {
+			if (amt_accum_chain[z]) {
+				u64 val = mac_div(sig_accum_chain[z], amt_accum_chain[z]);
+
+				val |= 0xFF;
+				data[i] |= (val << (z * 8));
+			}
+			if (amt_accum_chain_avg[z]) {
+				u64 val = mac_div(sig_accum_chain_avg[z], amt_accum_chain_avg[z]);
+
+				val |= 0xFF;
+				data[i + 1] |= (val << (z * 8));
+			}
+		}
+		i += 2;
 	}
 
 do_survey:
-- 
2.20.1




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux