mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 23:39:18 +00:00
mac80211: add support for per-chain signal strength reporting
Signed-off-by: Felix Fietkau <nbd@openwrt.org> [fix unit documentation] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
119363c7dc
commit
ef0621e805
@ -850,6 +850,10 @@ enum mac80211_rx_flags {
|
|||||||
* @signal: signal strength when receiving this frame, either in dBm, in dB or
|
* @signal: signal strength when receiving this frame, either in dBm, in dB or
|
||||||
* unspecified depending on the hardware capabilities flags
|
* unspecified depending on the hardware capabilities flags
|
||||||
* @IEEE80211_HW_SIGNAL_*
|
* @IEEE80211_HW_SIGNAL_*
|
||||||
|
* @chains: bitmask of receive chains for which separate signal strength
|
||||||
|
* values were filled.
|
||||||
|
* @chain_signal: per-chain signal strength, in dBm (unlike @signal, doesn't
|
||||||
|
* support dB or unspecified units)
|
||||||
* @antenna: antenna used
|
* @antenna: antenna used
|
||||||
* @rate_idx: index of data rate into band's supported rates or MCS index if
|
* @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)
|
* HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
|
||||||
@ -881,6 +885,8 @@ struct ieee80211_rx_status {
|
|||||||
u8 band;
|
u8 band;
|
||||||
u8 antenna;
|
u8 antenna;
|
||||||
s8 signal;
|
s8 signal;
|
||||||
|
u8 chains;
|
||||||
|
s8 chain_signal[IEEE80211_MAX_CHAINS];
|
||||||
u8 ampdu_delimiter_crc;
|
u8 ampdu_delimiter_crc;
|
||||||
u8 vendor_radiotap_align;
|
u8 vendor_radiotap_align;
|
||||||
u8 vendor_radiotap_oui[3];
|
u8 vendor_radiotap_oui[3];
|
||||||
|
@ -444,7 +444,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct timespec uptime;
|
struct timespec uptime;
|
||||||
u64 packets = 0;
|
u64 packets = 0;
|
||||||
int ac;
|
int i, ac;
|
||||||
|
|
||||||
sinfo->generation = sdata->local->sta_generation;
|
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 = (s8)sta->last_signal;
|
||||||
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_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_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
|
||||||
sta_set_rate_info_rx(sta, &sinfo->rxrate);
|
sta_set_rate_info_rx(sta, &sinfo->rxrate);
|
||||||
|
@ -1372,6 +1372,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||||||
struct sk_buff *skb = rx->skb;
|
struct sk_buff *skb = rx->skb;
|
||||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!sta)
|
if (!sta)
|
||||||
return RX_CONTINUE;
|
return RX_CONTINUE;
|
||||||
@ -1422,6 +1423,19 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||||||
ewma_add(&sta->avg_signal, -status->signal);
|
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
|
* Change STA power saving mode only at the end of a frame
|
||||||
* exchange sequence.
|
* exchange sequence.
|
||||||
|
@ -358,6 +358,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|||||||
do_posix_clock_monotonic_gettime(&uptime);
|
do_posix_clock_monotonic_gettime(&uptime);
|
||||||
sta->last_connected = uptime.tv_sec;
|
sta->last_connected = uptime.tv_sec;
|
||||||
ewma_init(&sta->avg_signal, 1024, 8);
|
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)) {
|
if (sta_prepare_rate_control(local, sta, gfp)) {
|
||||||
kfree(sta);
|
kfree(sta);
|
||||||
|
@ -344,6 +344,11 @@ struct sta_info {
|
|||||||
int last_signal;
|
int last_signal;
|
||||||
struct ewma avg_signal;
|
struct ewma avg_signal;
|
||||||
int last_ack_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 */
|
/* Plus 1 for non-QoS frames */
|
||||||
__le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1];
|
__le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1];
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user