linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] cfg80211: add support for per-chain signal strength reporting
@ 2013-04-20 12:33 Felix Fietkau
  2013-04-20 12:33 ` [PATCH 2/2] mac80211: " Felix Fietkau
  2013-04-22 14:03 ` [PATCH 1/2] cfg80211: " Johannes Berg
  0 siblings, 2 replies; 4+ messages in thread
From: Felix Fietkau @ 2013-04-20 12:33 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
 include/net/cfg80211.h       | 14 ++++++++++++++
 include/uapi/linux/nl80211.h |  4 ++++
 net/wireless/nl80211.c       | 38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index dff96d8..0c51500 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -753,6 +753,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
  * @STATION_INFO_LOCAL_PM: @local_pm filled
  * @STATION_INFO_PEER_PM: @peer_pm filled
  * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled
+ * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled
+ * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -781,6 +783,8 @@ enum station_info_flags {
 	STATION_INFO_NONPEER_PM		= 1<<23,
 	STATION_INFO_RX_BYTES64		= 1<<24,
 	STATION_INFO_TX_BYTES64		= 1<<25,
+	STATION_INFO_CHAIN_SIGNAL	= 1<<26,
+	STATION_INFO_CHAIN_SIGNAL_AVG	= 1<<27,
 };
 
 /**
@@ -857,6 +861,8 @@ struct sta_bss_parameters {
 	u16 beacon_interval;
 };
 
+#define IEEE80211_MAX_CHAINS	4
+
 /**
  * struct station_info - station information
  *
@@ -874,6 +880,9 @@ struct sta_bss_parameters {
  *	For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
  * @signal_avg: Average signal strength, type depends on the wiphy's signal_type.
  *	For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
+ * @chains: bitmask for filled values in @chain_signal, @chain_signal_avg
+ * @chain_signal: per-chain signal strength of last received packet in dBm
+ * @chain_signal_avg: per-chain signal strength average in dBm
  * @txrate: current unicast bitrate from this station
  * @rxrate: current unicast bitrate to this station
  * @rx_packets: packets received from this station
@@ -909,6 +918,11 @@ struct station_info {
 	u8 plink_state;
 	s8 signal;
 	s8 signal_avg;
+
+	u8 chains;
+	s8 chain_signal[IEEE80211_MAX_CHAINS];
+	s8 chain_signal_avg[IEEE80211_MAX_CHAINS];
+
 	struct rate_info txrate;
 	struct rate_info rxrate;
 	u32 rx_packets;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 79da871..3f0b2bc 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1973,6 +1973,8 @@ enum nl80211_sta_bss_param {
  * @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode
  * @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards
  *	non-peer STA
+ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
+ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
  */
@@ -2002,6 +2004,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_NONPEER_PM,
 	NL80211_STA_INFO_RX_BYTES64,
 	NL80211_STA_INFO_TX_BYTES64,
+	NL80211_STA_INFO_CHAIN_SIGNAL,
+	NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 671b69a..c09a84e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3365,6 +3365,32 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
 	return true;
 }
 
+static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
+			       int id)
+{
+	void *attr;
+	int i = 0;
+
+	if (!mask)
+		return true;
+
+	attr = nla_nest_start(msg, id);
+	if (!attr)
+		return false;
+
+	for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
+		if (!(mask & BIT(i)))
+			continue;
+
+		if (nla_put_u8(msg, i, signal[i]))
+			return false;
+	}
+
+	nla_nest_end(msg, attr);
+
+	return true;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
 				int flags,
 				struct cfg80211_registered_device *rdev,
@@ -3436,6 +3462,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
 	default:
 		break;
 	}
+	if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) {
+		if (!nl80211_put_signal(msg, sinfo->chains,
+					sinfo->chain_signal,
+					NL80211_STA_INFO_CHAIN_SIGNAL))
+			goto nla_put_failure;
+	}
+	if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) {
+		if (!nl80211_put_signal(msg, sinfo->chains,
+					sinfo->chain_signal_avg,
+					NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
+			goto nla_put_failure;
+	}
 	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
 		if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
 					  NL80211_STA_INFO_TX_BITRATE))
-- 
1.8.0.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] mac80211: add support for per-chain signal strength reporting
  2013-04-20 12:33 [PATCH 1/2] cfg80211: add support for per-chain signal strength reporting Felix Fietkau
@ 2013-04-20 12:33 ` Felix Fietkau
  2013-04-22 14:03 ` [PATCH 1/2] cfg80211: " Johannes Berg
  1 sibling, 0 replies; 4+ messages in thread
From: Felix Fietkau @ 2013-04-20 12:33 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
 include/net/mac80211.h  |  5 +++++
 net/mac80211/cfg.c      | 13 ++++++++++++-
 net/mac80211/rx.c       | 14 ++++++++++++++
 net/mac80211/sta_info.c |  2 ++
 net/mac80211/sta_info.h |  5 +++++
 5 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 39c0d51..542279a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -847,6 +847,9 @@ enum mac80211_rx_flags {
  * @signal: signal strength when receiving this frame, either in dBm, in dB or
  *	unspecified depending on the hardware capabilities flags
  *	@IEEE80211_HW_SIGNAL_*
+ * @chains: bitmask of receive chains for which separate signal strength
+ *	values were filled.
+ * @chain_signal: per-chain signal strength, same format as @signal
  * @antenna: antenna used
  * @rate_idx: index of data rate into band's supported rates or MCS index if
  *	HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
@@ -878,6 +881,8 @@ struct ieee80211_rx_status {
 	u8 band;
 	u8 antenna;
 	s8 signal;
+	u8 chains;
+	s8 chain_signal[IEEE80211_MAX_CHAINS];
 	u8 ampdu_delimiter_crc;
 	u8 vendor_radiotap_align;
 	u8 vendor_radiotap_oui[3];
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 490990e..b1b8841 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -444,7 +444,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 	struct ieee80211_local *local = sdata->local;
 	struct timespec uptime;
 	u64 packets = 0;
-	int ac;
+	int i, ac;
 
 	sinfo->generation = sdata->local->sta_generation;
 
@@ -488,6 +488,17 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 			sinfo->signal = (s8)sta->last_signal;
 		sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
 	}
+	if (sta->chains) {
+		sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
+				 STATION_INFO_CHAIN_SIGNAL_AVG;
+
+		sinfo->chains = sta->chains;
+		for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
+			sinfo->chain_signal[i] = sta->chain_signal_last[i];
+			sinfo->chain_signal_avg[i] =
+				(s8) -ewma_read(&sta->chain_signal_avg[i]);
+		}
+	}
 
 	sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
 	sta_set_rate_info_rx(sta, &sinfo->rxrate);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 4ffff07..ce33b56 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1372,6 +1372,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	int i;
 
 	if (!sta)
 		return RX_CONTINUE;
@@ -1422,6 +1423,19 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 		ewma_add(&sta->avg_signal, -status->signal);
 	}
 
+	if (status->chains) {
+		sta->chains = status->chains;
+		for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {
+			int signal = status->chain_signal[i];
+
+			if (!(status->chains & BIT(i)))
+				continue;
+
+			sta->chain_signal_last[i] = signal;
+			ewma_add(&sta->chain_signal_avg[i], -signal);
+		}
+	}
+
 	/*
 	 * Change STA power saving mode only at the end of a frame
 	 * exchange sequence.
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 11216bc..a04c5671 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -358,6 +358,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 	do_posix_clock_monotonic_gettime(&uptime);
 	sta->last_connected = uptime.tv_sec;
 	ewma_init(&sta->avg_signal, 1024, 8);
+	for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
+		ewma_init(&sta->chain_signal_avg[i], 1024, 8);
 
 	if (sta_prepare_rate_control(local, sta, gfp)) {
 		kfree(sta);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 876dd3f..fa1aa8a 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -342,6 +342,11 @@ struct sta_info {
 	int last_signal;
 	struct ewma avg_signal;
 	int last_ack_signal;
+
+	u8 chains;
+	s8 chain_signal_last[IEEE80211_MAX_CHAINS];
+	struct ewma chain_signal_avg[IEEE80211_MAX_CHAINS];
+
 	/* Plus 1 for non-QoS frames */
 	__le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1];
 
-- 
1.8.0.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] cfg80211: add support for per-chain signal strength reporting
  2013-04-20 12:33 [PATCH 1/2] cfg80211: add support for per-chain signal strength reporting Felix Fietkau
  2013-04-20 12:33 ` [PATCH 2/2] mac80211: " Felix Fietkau
@ 2013-04-22 14:03 ` Johannes Berg
  2013-04-22 14:24   ` Felix Fietkau
  1 sibling, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2013-04-22 14:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless

On Sat, 2013-04-20 at 14:33 +0200, Felix Fietkau wrote:

> + * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
> + * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average

please document the units/data structure (nested) here


> +		if (nla_put_u8(msg, i, signal[i]))
> +			return false;

does u8 make sense? it takes the same space as u32.

johannes



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] cfg80211: add support for per-chain signal strength reporting
  2013-04-22 14:03 ` [PATCH 1/2] cfg80211: " Johannes Berg
@ 2013-04-22 14:24   ` Felix Fietkau
  0 siblings, 0 replies; 4+ messages in thread
From: Felix Fietkau @ 2013-04-22 14:24 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

On 2013-04-22 4:03 PM, Johannes Berg wrote:
> On Sat, 2013-04-20 at 14:33 +0200, Felix Fietkau wrote:
> 
>> + * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
>> + * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
> 
> please document the units/data structure (nested) here
Will do.

>> +		if (nla_put_u8(msg, i, signal[i]))
>> +			return false;
> 
> does u8 make sense? it takes the same space as u32.
I used u8 because the other signal strength attributes also use u8.

- Felix


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-04-22 14:24 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-20 12:33 [PATCH 1/2] cfg80211: add support for per-chain signal strength reporting Felix Fietkau
2013-04-20 12:33 ` [PATCH 2/2] mac80211: " Felix Fietkau
2013-04-22 14:03 ` [PATCH 1/2] cfg80211: " Johannes Berg
2013-04-22 14:24   ` Felix Fietkau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).