diff options
-rw-r--r-- | include/linux/nl80211.h | 3 | ||||
-rw-r--r-- | include/net/cfg80211.h | 5 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 56 |
3 files changed, 44 insertions, 20 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 821ffb954f14..30022189104d 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -1243,6 +1243,8 @@ enum nl80211_rate_info { | |||
1243 | * @NL80211_STA_INFO_LLID: the station's mesh LLID | 1243 | * @NL80211_STA_INFO_LLID: the station's mesh LLID |
1244 | * @NL80211_STA_INFO_PLID: the station's mesh PLID | 1244 | * @NL80211_STA_INFO_PLID: the station's mesh PLID |
1245 | * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station | 1245 | * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station |
1246 | * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested | ||
1247 | * attribute, like NL80211_STA_INFO_TX_BITRATE. | ||
1246 | * @__NL80211_STA_INFO_AFTER_LAST: internal | 1248 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
1247 | * @NL80211_STA_INFO_MAX: highest possible station info attribute | 1249 | * @NL80211_STA_INFO_MAX: highest possible station info attribute |
1248 | */ | 1250 | */ |
@@ -1261,6 +1263,7 @@ enum nl80211_sta_info { | |||
1261 | NL80211_STA_INFO_TX_RETRIES, | 1263 | NL80211_STA_INFO_TX_RETRIES, |
1262 | NL80211_STA_INFO_TX_FAILED, | 1264 | NL80211_STA_INFO_TX_FAILED, |
1263 | NL80211_STA_INFO_SIGNAL_AVG, | 1265 | NL80211_STA_INFO_SIGNAL_AVG, |
1266 | NL80211_STA_INFO_RX_BITRATE, | ||
1264 | 1267 | ||
1265 | /* keep last */ | 1268 | /* keep last */ |
1266 | __NL80211_STA_INFO_AFTER_LAST, | 1269 | __NL80211_STA_INFO_AFTER_LAST, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 679a0494b5f2..1ac5786da14b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -413,7 +413,7 @@ struct station_parameters { | |||
413 | * @STATION_INFO_PLID: @plid filled | 413 | * @STATION_INFO_PLID: @plid filled |
414 | * @STATION_INFO_PLINK_STATE: @plink_state filled | 414 | * @STATION_INFO_PLINK_STATE: @plink_state filled |
415 | * @STATION_INFO_SIGNAL: @signal filled | 415 | * @STATION_INFO_SIGNAL: @signal filled |
416 | * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled | 416 | * @STATION_INFO_TX_BITRATE: @txrate fields are filled |
417 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) | 417 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) |
418 | * @STATION_INFO_RX_PACKETS: @rx_packets filled | 418 | * @STATION_INFO_RX_PACKETS: @rx_packets filled |
419 | * @STATION_INFO_TX_PACKETS: @tx_packets filled | 419 | * @STATION_INFO_TX_PACKETS: @tx_packets filled |
@@ -421,6 +421,7 @@ struct station_parameters { | |||
421 | * @STATION_INFO_TX_FAILED: @tx_failed filled | 421 | * @STATION_INFO_TX_FAILED: @tx_failed filled |
422 | * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled | 422 | * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled |
423 | * @STATION_INFO_SIGNAL_AVG: @signal_avg filled | 423 | * @STATION_INFO_SIGNAL_AVG: @signal_avg filled |
424 | * @STATION_INFO_RX_BITRATE: @rxrate fields are filled | ||
424 | */ | 425 | */ |
425 | enum station_info_flags { | 426 | enum station_info_flags { |
426 | STATION_INFO_INACTIVE_TIME = 1<<0, | 427 | STATION_INFO_INACTIVE_TIME = 1<<0, |
@@ -437,6 +438,7 @@ enum station_info_flags { | |||
437 | STATION_INFO_TX_FAILED = 1<<11, | 438 | STATION_INFO_TX_FAILED = 1<<11, |
438 | STATION_INFO_RX_DROP_MISC = 1<<12, | 439 | STATION_INFO_RX_DROP_MISC = 1<<12, |
439 | STATION_INFO_SIGNAL_AVG = 1<<13, | 440 | STATION_INFO_SIGNAL_AVG = 1<<13, |
441 | STATION_INFO_RX_BITRATE = 1<<14, | ||
440 | }; | 442 | }; |
441 | 443 | ||
442 | /** | 444 | /** |
@@ -506,6 +508,7 @@ struct station_info { | |||
506 | s8 signal; | 508 | s8 signal; |
507 | s8 signal_avg; | 509 | s8 signal_avg; |
508 | struct rate_info txrate; | 510 | struct rate_info txrate; |
511 | struct rate_info rxrate; | ||
509 | u32 rx_packets; | 512 | u32 rx_packets; |
510 | u32 tx_packets; | 513 | u32 tx_packets; |
511 | u32 tx_retries; | 514 | u32 tx_retries; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 864ddfbeff2f..4ebce4284e9d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1968,13 +1968,41 @@ static int parse_station_flags(struct genl_info *info, | |||
1968 | return 0; | 1968 | return 0; |
1969 | } | 1969 | } |
1970 | 1970 | ||
1971 | static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | ||
1972 | int attr) | ||
1973 | { | ||
1974 | struct nlattr *rate; | ||
1975 | u16 bitrate; | ||
1976 | |||
1977 | rate = nla_nest_start(msg, attr); | ||
1978 | if (!rate) | ||
1979 | goto nla_put_failure; | ||
1980 | |||
1981 | /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ | ||
1982 | bitrate = cfg80211_calculate_bitrate(info); | ||
1983 | if (bitrate > 0) | ||
1984 | NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); | ||
1985 | |||
1986 | if (info->flags & RATE_INFO_FLAGS_MCS) | ||
1987 | NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs); | ||
1988 | if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) | ||
1989 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH); | ||
1990 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI) | ||
1991 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI); | ||
1992 | |||
1993 | nla_nest_end(msg, rate); | ||
1994 | return true; | ||
1995 | |||
1996 | nla_put_failure: | ||
1997 | return false; | ||
1998 | } | ||
1999 | |||
1971 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | 2000 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, |
1972 | int flags, struct net_device *dev, | 2001 | int flags, struct net_device *dev, |
1973 | const u8 *mac_addr, struct station_info *sinfo) | 2002 | const u8 *mac_addr, struct station_info *sinfo) |
1974 | { | 2003 | { |
1975 | void *hdr; | 2004 | void *hdr; |
1976 | struct nlattr *sinfoattr, *txrate; | 2005 | struct nlattr *sinfoattr; |
1977 | u16 bitrate; | ||
1978 | 2006 | ||
1979 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); | 2007 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); |
1980 | if (!hdr) | 2008 | if (!hdr) |
@@ -2013,24 +2041,14 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
2013 | NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG, | 2041 | NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG, |
2014 | sinfo->signal_avg); | 2042 | sinfo->signal_avg); |
2015 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { | 2043 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { |
2016 | txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE); | 2044 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, |
2017 | if (!txrate) | 2045 | NL80211_STA_INFO_TX_BITRATE)) |
2046 | goto nla_put_failure; | ||
2047 | } | ||
2048 | if (sinfo->filled & STATION_INFO_RX_BITRATE) { | ||
2049 | if (!nl80211_put_sta_rate(msg, &sinfo->rxrate, | ||
2050 | NL80211_STA_INFO_RX_BITRATE)) | ||
2018 | goto nla_put_failure; | 2051 | goto nla_put_failure; |
2019 | |||
2020 | /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ | ||
2021 | bitrate = cfg80211_calculate_bitrate(&sinfo->txrate); | ||
2022 | if (bitrate > 0) | ||
2023 | NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); | ||
2024 | |||
2025 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS) | ||
2026 | NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, | ||
2027 | sinfo->txrate.mcs); | ||
2028 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) | ||
2029 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH); | ||
2030 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI) | ||
2031 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI); | ||
2032 | |||
2033 | nla_nest_end(msg, txrate); | ||
2034 | } | 2052 | } |
2035 | if (sinfo->filled & STATION_INFO_RX_PACKETS) | 2053 | if (sinfo->filled & STATION_INFO_RX_PACKETS) |
2036 | NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS, | 2054 | NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS, |