aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-11-14 10:43:50 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-01-08 09:27:54 -0500
commit11f78ac32b06648c1dde9371b70323168b51a83e (patch)
tree2cea75cf1a053308f980dc69ebc9e7e7cd7a59e6
parent4ed20bebf51578229a1986efcf46344075ec8447 (diff)
cfg80211: allow survey data to return global data
Not all devices are able to report survey data (particularly time spent for various operations) per channel. As all these statistics already exist in survey data, allow such devices to report them (if userspace requested it) Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h3
-rw-r--r--include/uapi/linux/nl80211.h16
-rw-r--r--net/wireless/nl80211.c31
3 files changed, 33 insertions, 17 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3b489f8fc4cd..5a861440c122 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -542,7 +542,8 @@ enum survey_info_flags {
542/** 542/**
543 * struct survey_info - channel survey response 543 * struct survey_info - channel survey response
544 * 544 *
545 * @channel: the channel this survey record reports, mandatory 545 * @channel: the channel this survey record reports, may be %NULL for a single
546 * record to report global statistics
546 * @filled: bitflag of flags from &enum survey_info_flags 547 * @filled: bitflag of flags from &enum survey_info_flags
547 * @noise: channel noise in dBm. This and all following fields are 548 * @noise: channel noise in dBm. This and all following fields are
548 * optional 549 * optional
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1a5acc80ab88..5e8b65f239a5 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1727,6 +1727,14 @@ enum nl80211_commands {
1727 * is located at bit 0 of byte 0. bit index 25 would be located at bit 1 1727 * is located at bit 0 of byte 0. bit index 25 would be located at bit 1
1728 * of byte 3 (u8 array). 1728 * of byte 3 (u8 array).
1729 * 1729 *
1730 * @NL80211_ATTR_SURVEY_RADIO_STATS: Request overall radio statistics to be
1731 * returned along with other survey data. If set, @NL80211_CMD_GET_SURVEY
1732 * may return a survey entry without a channel indicating global radio
1733 * statistics (only some values are valid and make sense.)
1734 * For devices that don't return such an entry even then, the information
1735 * should be contained in the result as the sum of the respective counters
1736 * over all channels.
1737 *
1730 * @NUM_NL80211_ATTR: total number of nl80211_attrs available 1738 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
1731 * @NL80211_ATTR_MAX: highest attribute number currently defined 1739 * @NL80211_ATTR_MAX: highest attribute number currently defined
1732 * @__NL80211_ATTR_AFTER_LAST: internal use 1740 * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2088,6 +2096,8 @@ enum nl80211_attrs {
2088 2096
2089 NL80211_ATTR_EXT_FEATURES, 2097 NL80211_ATTR_EXT_FEATURES,
2090 2098
2099 NL80211_ATTR_SURVEY_RADIO_STATS,
2100
2091 /* add attributes here, update the policy in nl80211.c */ 2101 /* add attributes here, update the policy in nl80211.c */
2092 2102
2093 __NL80211_ATTR_AFTER_LAST, 2103 __NL80211_ATTR_AFTER_LAST,
@@ -2816,15 +2826,15 @@ enum nl80211_user_reg_hint_type {
2816 * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) 2826 * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
2817 * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used 2827 * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used
2818 * @NL80211_SURVEY_INFO_TIME: amount of time (in ms) that the radio 2828 * @NL80211_SURVEY_INFO_TIME: amount of time (in ms) that the radio
2819 * spent on this channel 2829 * was turned on (on channel or globally)
2820 * @NL80211_SURVEY_INFO_TIME_BUSY: amount of the time the primary 2830 * @NL80211_SURVEY_INFO_TIME_BUSY: amount of the time the primary
2821 * channel was sensed busy (either due to activity or energy detect) 2831 * channel was sensed busy (either due to activity or energy detect)
2822 * @NL80211_SURVEY_INFO_TIME_EXT_BUSY: amount of time the extension 2832 * @NL80211_SURVEY_INFO_TIME_EXT_BUSY: amount of time the extension
2823 * channel was sensed busy 2833 * channel was sensed busy
2824 * @NL80211_SURVEY_INFO_TIME_RX: amount of time the radio spent 2834 * @NL80211_SURVEY_INFO_TIME_RX: amount of time the radio spent
2825 * receiving data 2835 * receiving data (on channel or globally)
2826 * @NL80211_SURVEY_INFO_TIME_TX: amount of time the radio spent 2836 * @NL80211_SURVEY_INFO_TIME_TX: amount of time the radio spent
2827 * transmitting data 2837 * transmitting data (on channel or globally)
2828 * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number 2838 * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
2829 * currently defined 2839 * currently defined
2830 * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use 2840 * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 94ab2014fefe..9555ef9fd99e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6613,12 +6613,17 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
6613} 6613}
6614 6614
6615static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq, 6615static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
6616 int flags, struct net_device *dev, 6616 int flags, struct net_device *dev,
6617 struct survey_info *survey) 6617 bool allow_radio_stats,
6618 struct survey_info *survey)
6618{ 6619{
6619 void *hdr; 6620 void *hdr;
6620 struct nlattr *infoattr; 6621 struct nlattr *infoattr;
6621 6622
6623 /* skip radio stats if userspace didn't request them */
6624 if (!survey->channel && !allow_radio_stats)
6625 return 0;
6626
6622 hdr = nl80211hdr_put(msg, portid, seq, flags, 6627 hdr = nl80211hdr_put(msg, portid, seq, flags,
6623 NL80211_CMD_NEW_SURVEY_RESULTS); 6628 NL80211_CMD_NEW_SURVEY_RESULTS);
6624 if (!hdr) 6629 if (!hdr)
@@ -6631,7 +6636,8 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
6631 if (!infoattr) 6636 if (!infoattr)
6632 goto nla_put_failure; 6637 goto nla_put_failure;
6633 6638
6634 if (nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY, 6639 if (survey->channel &&
6640 nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
6635 survey->channel->center_freq)) 6641 survey->channel->center_freq))
6636 goto nla_put_failure; 6642 goto nla_put_failure;
6637 6643
@@ -6671,19 +6677,22 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
6671 return -EMSGSIZE; 6677 return -EMSGSIZE;
6672} 6678}
6673 6679
6674static int nl80211_dump_survey(struct sk_buff *skb, 6680static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
6675 struct netlink_callback *cb)
6676{ 6681{
6677 struct survey_info survey; 6682 struct survey_info survey;
6678 struct cfg80211_registered_device *rdev; 6683 struct cfg80211_registered_device *rdev;
6679 struct wireless_dev *wdev; 6684 struct wireless_dev *wdev;
6680 int survey_idx = cb->args[2]; 6685 int survey_idx = cb->args[2];
6681 int res; 6686 int res;
6687 bool radio_stats;
6682 6688
6683 res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); 6689 res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
6684 if (res) 6690 if (res)
6685 return res; 6691 return res;
6686 6692
6693 /* prepare_wdev_dump parsed the attributes */
6694 radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
6695
6687 if (!wdev->netdev) { 6696 if (!wdev->netdev) {
6688 res = -EINVAL; 6697 res = -EINVAL;
6689 goto out_err; 6698 goto out_err;
@@ -6701,13 +6710,9 @@ static int nl80211_dump_survey(struct sk_buff *skb,
6701 if (res) 6710 if (res)
6702 goto out_err; 6711 goto out_err;
6703 6712
6704 /* Survey without a channel doesn't make sense */ 6713 /* don't send disabled channels, but do send non-channel data */
6705 if (!survey.channel) { 6714 if (survey.channel &&
6706 res = -EINVAL; 6715 survey.channel->flags & IEEE80211_CHAN_DISABLED) {
6707 goto out;
6708 }
6709
6710 if (survey.channel->flags & IEEE80211_CHAN_DISABLED) {
6711 survey_idx++; 6716 survey_idx++;
6712 continue; 6717 continue;
6713 } 6718 }
@@ -6715,7 +6720,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
6715 if (nl80211_send_survey(skb, 6720 if (nl80211_send_survey(skb,
6716 NETLINK_CB(cb->skb).portid, 6721 NETLINK_CB(cb->skb).portid,
6717 cb->nlh->nlmsg_seq, NLM_F_MULTI, 6722 cb->nlh->nlmsg_seq, NLM_F_MULTI,
6718 wdev->netdev, &survey) < 0) 6723 wdev->netdev, radio_stats, &survey) < 0)
6719 goto out; 6724 goto out;
6720 survey_idx++; 6725 survey_idx++;
6721 } 6726 }