summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2018-09-10 07:29:12 -0400
committerJohannes Berg <johannes.berg@intel.com>2018-11-09 05:20:13 -0500
commit9bb7e0f24e7e7d00daa1219b14539e2e602649b2 (patch)
treeba16695740cec99cd4a4af3198cf791b7ca81b70
parent801f87469ee8d97af5997ef52188bb0e1908b110 (diff)
cfg80211: add peer measurement with FTM initiator API
Add a new "peer measurement" API, that can be used to measure certain things related to a peer. Right now, only implement FTM (flight time measurement) over it, but the idea is that it'll be extensible to also support measuring the necessary things to calculate e.g. angle-of-arrival for WiGig. The API is structured to have a generic list of peers and channels to measure with/on, and then for each of those a set of measurements (again, only FTM right now) to perform. Results are sent to the requesting socket, including a final complete message. Closing the controlling netlink socket will abort a running measurement. v3: - add a bit to report "final" for partial results - remove list keeping etc. and just unicast out the results to the requester (big code reduction ...) - also send complete message unicast, and as a result remove the multicast group - separate out struct cfg80211_pmsr_ftm_request_peer from struct cfg80211_pmsr_request_peer - document timeout == 0 if no timeout - disallow setting timeout nl80211 attribute to 0, must not include attribute for no timeout - make MAC address randomization optional - change num bursts exponent default to 0 (1 burst, rather rather than the old default of 15==don't care) v4: - clarify NL80211_ATTR_TIMEOUT documentation v5: - remove unnecessary nl80211 multicast/family changes - remove partial results bit/flag, final is sufficient - add max_bursts_exponent, max_ftms_per_burst to capability - rename "frames per burst" -> "FTMs per burst" v6: - rename cfg80211_pmsr_free_wdev() to cfg80211_pmsr_wdev_down() and call it in leave, so the device can't go down with any pending measurements v7: - wording fixes (Lior) - fix ftm.max_bursts_exponent to allow having the limit of 0 (Lior) v8: - copyright statements - minor coding style fixes - fix error path leak Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h263
-rw-r--r--include/uapi/linux/nl80211.h418
-rw-r--r--net/wireless/Makefile1
-rw-r--r--net/wireless/core.c34
-rw-r--r--net/wireless/core.h5
-rw-r--r--net/wireless/nl80211.c192
-rw-r--r--net/wireless/nl80211.h32
-rw-r--r--net/wireless/pmsr.c590
-rw-r--r--net/wireless/rdev-ops.h25
-rw-r--r--net/wireless/trace.h68
10 files changed, 1609 insertions, 19 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1fa41b7a1be3..c21c5c70a2fd 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2849,6 +2849,190 @@ struct cfg80211_ftm_responder_stats {
2849}; 2849};
2850 2850
2851/** 2851/**
2852 * struct cfg80211_pmsr_ftm_result - FTM result
2853 * @failure_reason: if this measurement failed (PMSR status is
2854 * %NL80211_PMSR_STATUS_FAILURE), this gives a more precise
2855 * reason than just "failure"
2856 * @burst_index: if reporting partial results, this is the index
2857 * in [0 .. num_bursts-1] of the burst that's being reported
2858 * @num_ftmr_attempts: number of FTM request frames transmitted
2859 * @num_ftmr_successes: number of FTM request frames acked
2860 * @busy_retry_time: if failure_reason is %NL80211_PMSR_FTM_FAILURE_PEER_BUSY,
2861 * fill this to indicate in how many seconds a retry is deemed possible
2862 * by the responder
2863 * @num_bursts_exp: actual number of bursts exponent negotiated
2864 * @burst_duration: actual burst duration negotiated
2865 * @ftms_per_burst: actual FTMs per burst negotiated
2866 * @lci_len: length of LCI information (if present)
2867 * @civicloc_len: length of civic location information (if present)
2868 * @lci: LCI data (may be %NULL)
2869 * @civicloc: civic location data (may be %NULL)
2870 * @rssi_avg: average RSSI over FTM action frames reported
2871 * @rssi_spread: spread of the RSSI over FTM action frames reported
2872 * @tx_rate: bitrate for transmitted FTM action frame response
2873 * @rx_rate: bitrate of received FTM action frame
2874 * @rtt_avg: average of RTTs measured (must have either this or @dist_avg)
2875 * @rtt_variance: variance of RTTs measured (note that standard deviation is
2876 * the square root of the variance)
2877 * @rtt_spread: spread of the RTTs measured
2878 * @dist_avg: average of distances (mm) measured
2879 * (must have either this or @rtt_avg)
2880 * @dist_variance: variance of distances measured (see also @rtt_variance)
2881 * @dist_spread: spread of distances measured (see also @rtt_spread)
2882 * @num_ftmr_attempts_valid: @num_ftmr_attempts is valid
2883 * @num_ftmr_successes_valid: @num_ftmr_successes is valid
2884 * @rssi_avg_valid: @rssi_avg is valid
2885 * @rssi_spread_valid: @rssi_spread is valid
2886 * @tx_rate_valid: @tx_rate is valid
2887 * @rx_rate_valid: @rx_rate is valid
2888 * @rtt_avg_valid: @rtt_avg is valid
2889 * @rtt_variance_valid: @rtt_variance is valid
2890 * @rtt_spread_valid: @rtt_spread is valid
2891 * @dist_avg_valid: @dist_avg is valid
2892 * @dist_variance_valid: @dist_variance is valid
2893 * @dist_spread_valid: @dist_spread is valid
2894 */
2895struct cfg80211_pmsr_ftm_result {
2896 const u8 *lci;
2897 const u8 *civicloc;
2898 unsigned int lci_len;
2899 unsigned int civicloc_len;
2900 enum nl80211_peer_measurement_ftm_failure_reasons failure_reason;
2901 u32 num_ftmr_attempts, num_ftmr_successes;
2902 s16 burst_index;
2903 u8 busy_retry_time;
2904 u8 num_bursts_exp;
2905 u8 burst_duration;
2906 u8 ftms_per_burst;
2907 s32 rssi_avg;
2908 s32 rssi_spread;
2909 struct rate_info tx_rate, rx_rate;
2910 s64 rtt_avg;
2911 s64 rtt_variance;
2912 s64 rtt_spread;
2913 s64 dist_avg;
2914 s64 dist_variance;
2915 s64 dist_spread;
2916
2917 u16 num_ftmr_attempts_valid:1,
2918 num_ftmr_successes_valid:1,
2919 rssi_avg_valid:1,
2920 rssi_spread_valid:1,
2921 tx_rate_valid:1,
2922 rx_rate_valid:1,
2923 rtt_avg_valid:1,
2924 rtt_variance_valid:1,
2925 rtt_spread_valid:1,
2926 dist_avg_valid:1,
2927 dist_variance_valid:1,
2928 dist_spread_valid:1;
2929};
2930
2931/**
2932 * struct cfg80211_pmsr_result - peer measurement result
2933 * @addr: address of the peer
2934 * @host_time: host time (use ktime_get_boottime() adjust to the time when the
2935 * measurement was made)
2936 * @ap_tsf: AP's TSF at measurement time
2937 * @status: status of the measurement
2938 * @final: if reporting partial results, mark this as the last one; if not
2939 * reporting partial results always set this flag
2940 * @ap_tsf_valid: indicates the @ap_tsf value is valid
2941 * @type: type of the measurement reported, note that we only support reporting
2942 * one type at a time, but you can report multiple results separately and
2943 * they're all aggregated for userspace.
2944 */
2945struct cfg80211_pmsr_result {
2946 u64 host_time, ap_tsf;
2947 enum nl80211_peer_measurement_status status;
2948
2949 u8 addr[ETH_ALEN];
2950
2951 u8 final:1,
2952 ap_tsf_valid:1;
2953
2954 enum nl80211_peer_measurement_type type;
2955
2956 union {
2957 struct cfg80211_pmsr_ftm_result ftm;
2958 };
2959};
2960
2961/**
2962 * struct cfg80211_pmsr_ftm_request_peer - FTM request data
2963 * @requested: indicates FTM is requested
2964 * @preamble: frame preamble to use
2965 * @burst_period: burst period to use
2966 * @asap: indicates to use ASAP mode
2967 * @num_bursts_exp: number of bursts exponent
2968 * @burst_duration: burst duration
2969 * @ftms_per_burst: number of FTMs per burst
2970 * @ftmr_retries: number of retries for FTM request
2971 * @request_lci: request LCI information
2972 * @request_civicloc: request civic location information
2973 *
2974 * See also nl80211 for the respective attribute documentation.
2975 */
2976struct cfg80211_pmsr_ftm_request_peer {
2977 enum nl80211_preamble preamble;
2978 u16 burst_period;
2979 u8 requested:1,
2980 asap:1,
2981 request_lci:1,
2982 request_civicloc:1;
2983 u8 num_bursts_exp;
2984 u8 burst_duration;
2985 u8 ftms_per_burst;
2986 u8 ftmr_retries;
2987};
2988
2989/**
2990 * struct cfg80211_pmsr_request_peer - peer data for a peer measurement request
2991 * @addr: MAC address
2992 * @chandef: channel to use
2993 * @report_ap_tsf: report the associated AP's TSF
2994 * @ftm: FTM data, see &struct cfg80211_pmsr_ftm_request_peer
2995 */
2996struct cfg80211_pmsr_request_peer {
2997 u8 addr[ETH_ALEN];
2998 struct cfg80211_chan_def chandef;
2999 u8 report_ap_tsf:1;
3000 struct cfg80211_pmsr_ftm_request_peer ftm;
3001};
3002
3003/**
3004 * struct cfg80211_pmsr_request - peer measurement request
3005 * @cookie: cookie, set by cfg80211
3006 * @nl_portid: netlink portid - used by cfg80211
3007 * @drv_data: driver data for this request, if required for aborting,
3008 * not otherwise freed or anything by cfg80211
3009 * @mac_addr: MAC address used for (randomised) request
3010 * @mac_addr_mask: MAC address mask used for randomisation, bits that
3011 * are 0 in the mask should be randomised, bits that are 1 should
3012 * be taken from the @mac_addr
3013 * @list: used by cfg80211 to hold on to the request
3014 * @timeout: timeout (in milliseconds) for the whole operation, if
3015 * zero it means there's no timeout
3016 * @n_peers: number of peers to do measurements with
3017 * @peers: per-peer measurement request data
3018 */
3019struct cfg80211_pmsr_request {
3020 u64 cookie;
3021 void *drv_data;
3022 u32 n_peers;
3023 u32 nl_portid;
3024
3025 u32 timeout;
3026
3027 u8 mac_addr[ETH_ALEN] __aligned(2);
3028 u8 mac_addr_mask[ETH_ALEN] __aligned(2);
3029
3030 struct list_head list;
3031
3032 struct cfg80211_pmsr_request_peer peers[];
3033};
3034
3035/**
2852 * struct cfg80211_ops - backend description for wireless configuration 3036 * struct cfg80211_ops - backend description for wireless configuration
2853 * 3037 *
2854 * This struct is registered by fullmac card drivers and/or wireless stacks 3038 * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -3183,6 +3367,8 @@ struct cfg80211_ftm_responder_stats {
3183 * 3367 *
3184 * @get_ftm_responder_stats: Retrieve FTM responder statistics, if available. 3368 * @get_ftm_responder_stats: Retrieve FTM responder statistics, if available.
3185 * Statistics should be cumulative, currently no way to reset is provided. 3369 * Statistics should be cumulative, currently no way to reset is provided.
3370 * @start_pmsr: start peer measurement (e.g. FTM)
3371 * @abort_pmsr: abort peer measurement
3186 */ 3372 */
3187struct cfg80211_ops { 3373struct cfg80211_ops {
3188 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); 3374 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3492,6 +3678,11 @@ struct cfg80211_ops {
3492 int (*get_ftm_responder_stats)(struct wiphy *wiphy, 3678 int (*get_ftm_responder_stats)(struct wiphy *wiphy,
3493 struct net_device *dev, 3679 struct net_device *dev,
3494 struct cfg80211_ftm_responder_stats *ftm_stats); 3680 struct cfg80211_ftm_responder_stats *ftm_stats);
3681
3682 int (*start_pmsr)(struct wiphy *wiphy, struct wireless_dev *wdev,
3683 struct cfg80211_pmsr_request *request);
3684 void (*abort_pmsr)(struct wiphy *wiphy, struct wireless_dev *wdev,
3685 struct cfg80211_pmsr_request *request);
3495}; 3686};
3496 3687
3497/* 3688/*
@@ -3864,6 +4055,42 @@ struct wiphy_iftype_ext_capab {
3864}; 4055};
3865 4056
3866/** 4057/**
4058 * struct cfg80211_pmsr_capabilities - cfg80211 peer measurement capabilities
4059 * @max_peers: maximum number of peers in a single measurement
4060 * @report_ap_tsf: can report assoc AP's TSF for radio resource measurement
4061 * @randomize_mac_addr: can randomize MAC address for measurement
4062 * @ftm.supported: FTM measurement is supported
4063 * @ftm.asap: ASAP-mode is supported
4064 * @ftm.non_asap: non-ASAP-mode is supported
4065 * @ftm.request_lci: can request LCI data
4066 * @ftm.request_civicloc: can request civic location data
4067 * @ftm.preambles: bitmap of preambles supported (&enum nl80211_preamble)
4068 * @ftm.bandwidths: bitmap of bandwidths supported (&enum nl80211_chan_width)
4069 * @ftm.max_bursts_exponent: maximum burst exponent supported
4070 * (set to -1 if not limited; note that setting this will necessarily
4071 * forbid using the value 15 to let the responder pick)
4072 * @ftm.max_ftms_per_burst: maximum FTMs per burst supported (set to 0 if
4073 * not limited)
4074 */
4075struct cfg80211_pmsr_capabilities {
4076 unsigned int max_peers;
4077 u8 report_ap_tsf:1,
4078 randomize_mac_addr:1;
4079
4080 struct {
4081 u32 preambles;
4082 u32 bandwidths;
4083 s8 max_bursts_exponent;
4084 u8 max_ftms_per_burst;
4085 u8 supported:1,
4086 asap:1,
4087 non_asap:1,
4088 request_lci:1,
4089 request_civicloc:1;
4090 } ftm;
4091};
4092
4093/**
3867 * struct wiphy - wireless hardware description 4094 * struct wiphy - wireless hardware description
3868 * @reg_notifier: the driver's regulatory notification callback, 4095 * @reg_notifier: the driver's regulatory notification callback,
3869 * note that if your driver uses wiphy_apply_custom_regulatory() 4096 * note that if your driver uses wiphy_apply_custom_regulatory()
@@ -4027,6 +4254,8 @@ struct wiphy_iftype_ext_capab {
4027 * @txq_limit: configuration of internal TX queue frame limit 4254 * @txq_limit: configuration of internal TX queue frame limit
4028 * @txq_memory_limit: configuration internal TX queue memory limit 4255 * @txq_memory_limit: configuration internal TX queue memory limit
4029 * @txq_quantum: configuration of internal TX queue scheduler quantum 4256 * @txq_quantum: configuration of internal TX queue scheduler quantum
4257 *
4258 * @pmsr_capa: peer measurement capabilities
4030 */ 4259 */
4031struct wiphy { 4260struct wiphy {
4032 /* assign these fields before you register the wiphy */ 4261 /* assign these fields before you register the wiphy */
@@ -4163,6 +4392,8 @@ struct wiphy {
4163 u32 txq_memory_limit; 4392 u32 txq_memory_limit;
4164 u32 txq_quantum; 4393 u32 txq_quantum;
4165 4394
4395 const struct cfg80211_pmsr_capabilities *pmsr_capa;
4396
4166 char priv[0] __aligned(NETDEV_ALIGN); 4397 char priv[0] __aligned(NETDEV_ALIGN);
4167}; 4398};
4168 4399
@@ -4365,6 +4596,9 @@ struct cfg80211_cqm_config;
4365 * @owner_nlportid: (private) owner socket port ID 4596 * @owner_nlportid: (private) owner socket port ID
4366 * @nl_owner_dead: (private) owner socket went away 4597 * @nl_owner_dead: (private) owner socket went away
4367 * @cqm_config: (private) nl80211 RSSI monitor state 4598 * @cqm_config: (private) nl80211 RSSI monitor state
4599 * @pmsr_list: (private) peer measurement requests
4600 * @pmsr_lock: (private) peer measurements requests/results lock
4601 * @pmsr_free_wk: (private) peer measurements cleanup work
4368 */ 4602 */
4369struct wireless_dev { 4603struct wireless_dev {
4370 struct wiphy *wiphy; 4604 struct wiphy *wiphy;
@@ -4436,6 +4670,10 @@ struct wireless_dev {
4436#endif 4670#endif
4437 4671
4438 struct cfg80211_cqm_config *cqm_config; 4672 struct cfg80211_cqm_config *cqm_config;
4673
4674 struct list_head pmsr_list;
4675 spinlock_t pmsr_lock;
4676 struct work_struct pmsr_free_wk;
4439}; 4677};
4440 4678
4441static inline u8 *wdev_address(struct wireless_dev *wdev) 4679static inline u8 *wdev_address(struct wireless_dev *wdev)
@@ -6630,6 +6868,31 @@ int cfg80211_external_auth_request(struct net_device *netdev,
6630 struct cfg80211_external_auth_params *params, 6868 struct cfg80211_external_auth_params *params,
6631 gfp_t gfp); 6869 gfp_t gfp);
6632 6870
6871/**
6872 * cfg80211_pmsr_report - report peer measurement result data
6873 * @wdev: the wireless device reporting the measurement
6874 * @req: the original measurement request
6875 * @result: the result data
6876 * @gfp: allocation flags
6877 */
6878void cfg80211_pmsr_report(struct wireless_dev *wdev,
6879 struct cfg80211_pmsr_request *req,
6880 struct cfg80211_pmsr_result *result,
6881 gfp_t gfp);
6882
6883/**
6884 * cfg80211_pmsr_complete - report peer measurement completed
6885 * @wdev: the wireless device reporting the measurement
6886 * @req: the original measurement request
6887 * @gfp: allocation flags
6888 *
6889 * Report that the entire measurement completed, after this
6890 * the request pointer will no longer be valid.
6891 */
6892void cfg80211_pmsr_complete(struct wireless_dev *wdev,
6893 struct cfg80211_pmsr_request *req,
6894 gfp_t gfp);
6895
6633/* Logging, debugging and troubleshooting/diagnostic helpers. */ 6896/* Logging, debugging and troubleshooting/diagnostic helpers. */
6634 6897
6635/* wiphy_printk helpers, similar to dev_printk */ 6898/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 6d610bae30a9..e45b88925783 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1036,6 +1036,30 @@
1036 * @NL80211_CMD_GET_FTM_RESPONDER_STATS: Retrieve FTM responder statistics, in 1036 * @NL80211_CMD_GET_FTM_RESPONDER_STATS: Retrieve FTM responder statistics, in
1037 * the %NL80211_ATTR_FTM_RESPONDER_STATS attribute. 1037 * the %NL80211_ATTR_FTM_RESPONDER_STATS attribute.
1038 * 1038 *
1039 * @NL80211_CMD_PEER_MEASUREMENT_START: start a (set of) peer measurement(s)
1040 * with the given parameters, which are encapsulated in the nested
1041 * %NL80211_ATTR_PEER_MEASUREMENTS attribute. Optionally, MAC address
1042 * randomization may be enabled and configured by specifying the
1043 * %NL80211_ATTR_MAC and %NL80211_ATTR_MAC_MASK attributes.
1044 * If a timeout is requested, use the %NL80211_ATTR_TIMEOUT attribute.
1045 * A u64 cookie for further %NL80211_ATTR_COOKIE use is is returned in
1046 * the netlink extended ack message.
1047 *
1048 * To cancel a measurement, close the socket that requested it.
1049 *
1050 * Measurement results are reported to the socket that requested the
1051 * measurement using @NL80211_CMD_PEER_MEASUREMENT_RESULT when they
1052 * become available, so applications must ensure a large enough socket
1053 * buffer size.
1054 *
1055 * Depending on driver support it may or may not be possible to start
1056 * multiple concurrent measurements.
1057 * @NL80211_CMD_PEER_MEASUREMENT_RESULT: This command number is used for the
1058 * result notification from the driver to the requesting socket.
1059 * @NL80211_CMD_PEER_MEASUREMENT_COMPLETE: Notification only, indicating that
1060 * the measurement completed, using the measurement cookie
1061 * (%NL80211_ATTR_COOKIE).
1062 *
1039 * @NL80211_CMD_MAX: highest used command number 1063 * @NL80211_CMD_MAX: highest used command number
1040 * @__NL80211_CMD_AFTER_LAST: internal use 1064 * @__NL80211_CMD_AFTER_LAST: internal use
1041 */ 1065 */
@@ -1250,6 +1274,10 @@ enum nl80211_commands {
1250 1274
1251 NL80211_CMD_GET_FTM_RESPONDER_STATS, 1275 NL80211_CMD_GET_FTM_RESPONDER_STATS,
1252 1276
1277 NL80211_CMD_PEER_MEASUREMENT_START,
1278 NL80211_CMD_PEER_MEASUREMENT_RESULT,
1279 NL80211_CMD_PEER_MEASUREMENT_COMPLETE,
1280
1253 /* add new commands above here */ 1281 /* add new commands above here */
1254 1282
1255 /* used to define NL80211_CMD_MAX below */ 1283 /* used to define NL80211_CMD_MAX below */
@@ -2254,6 +2282,16 @@ enum nl80211_commands {
2254 * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder 2282 * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder
2255 * statistics, see &enum nl80211_ftm_responder_stats. 2283 * statistics, see &enum nl80211_ftm_responder_stats.
2256 * 2284 *
2285 * @NL80211_ATTR_TIMEOUT: Timeout for the given operation in milliseconds (u32),
2286 * if the attribute is not given no timeout is requested. Note that 0 is an
2287 * invalid value.
2288 *
2289 * @NL80211_ATTR_PEER_MEASUREMENTS: peer measurements request (and result)
2290 * data, uses nested attributes specified in
2291 * &enum nl80211_peer_measurement_attrs.
2292 * This is also used for capability advertisement in the wiphy information,
2293 * with the appropriate sub-attributes.
2294 *
2257 * @NUM_NL80211_ATTR: total number of nl80211_attrs available 2295 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
2258 * @NL80211_ATTR_MAX: highest attribute number currently defined 2296 * @NL80211_ATTR_MAX: highest attribute number currently defined
2259 * @__NL80211_ATTR_AFTER_LAST: internal use 2297 * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2699,6 +2737,10 @@ enum nl80211_attrs {
2699 2737
2700 NL80211_ATTR_FTM_RESPONDER_STATS, 2738 NL80211_ATTR_FTM_RESPONDER_STATS,
2701 2739
2740 NL80211_ATTR_TIMEOUT,
2741
2742 NL80211_ATTR_PEER_MEASUREMENTS,
2743
2702 /* add attributes here, update the policy in nl80211.c */ 2744 /* add attributes here, update the policy in nl80211.c */
2703 2745
2704 __NL80211_ATTR_AFTER_LAST, 2746 __NL80211_ATTR_AFTER_LAST,
@@ -5906,4 +5948,380 @@ enum nl80211_ftm_responder_stats {
5906 NL80211_FTM_STATS_MAX = __NL80211_FTM_STATS_AFTER_LAST - 1 5948 NL80211_FTM_STATS_MAX = __NL80211_FTM_STATS_AFTER_LAST - 1
5907}; 5949};
5908 5950
5951/**
5952 * enum nl80211_preamble - frame preamble types
5953 * @NL80211_PREAMBLE_LEGACY: legacy (HR/DSSS, OFDM, ERP PHY) preamble
5954 * @NL80211_PREAMBLE_HT: HT preamble
5955 * @NL80211_PREAMBLE_VHT: VHT preamble
5956 * @NL80211_PREAMBLE_DMG: DMG preamble
5957 */
5958enum nl80211_preamble {
5959 NL80211_PREAMBLE_LEGACY,
5960 NL80211_PREAMBLE_HT,
5961 NL80211_PREAMBLE_VHT,
5962 NL80211_PREAMBLE_DMG,
5963};
5964
5965/**
5966 * enum nl80211_peer_measurement_type - peer measurement types
5967 * @NL80211_PMSR_TYPE_INVALID: invalid/unused, needed as we use
5968 * these numbers also for attributes
5969 *
5970 * @NL80211_PMSR_TYPE_FTM: flight time measurement
5971 *
5972 * @NUM_NL80211_PMSR_TYPES: internal
5973 * @NL80211_PMSR_TYPE_MAX: highest type number
5974 */
5975enum nl80211_peer_measurement_type {
5976 NL80211_PMSR_TYPE_INVALID,
5977
5978 NL80211_PMSR_TYPE_FTM,
5979
5980 NUM_NL80211_PMSR_TYPES,
5981 NL80211_PMSR_TYPE_MAX = NUM_NL80211_PMSR_TYPES - 1
5982};
5983
5984/**
5985 * enum nl80211_peer_measurement_status - peer measurement status
5986 * @NL80211_PMSR_STATUS_SUCCESS: measurement completed successfully
5987 * @NL80211_PMSR_STATUS_REFUSED: measurement was locally refused
5988 * @NL80211_PMSR_STATUS_TIMEOUT: measurement timed out
5989 * @NL80211_PMSR_STATUS_FAILURE: measurement failed, a type-dependent
5990 * reason may be available in the response data
5991 */
5992enum nl80211_peer_measurement_status {
5993 NL80211_PMSR_STATUS_SUCCESS,
5994 NL80211_PMSR_STATUS_REFUSED,
5995 NL80211_PMSR_STATUS_TIMEOUT,
5996 NL80211_PMSR_STATUS_FAILURE,
5997};
5998
5999/**
6000 * enum nl80211_peer_measurement_req - peer measurement request attributes
6001 * @__NL80211_PMSR_REQ_ATTR_INVALID: invalid
6002 *
6003 * @NL80211_PMSR_REQ_ATTR_DATA: This is a nested attribute with measurement
6004 * type-specific request data inside. The attributes used are from the
6005 * enums named nl80211_peer_measurement_<type>_req.
6006 * @NL80211_PMSR_REQ_ATTR_GET_AP_TSF: include AP TSF timestamp, if supported
6007 * (flag attribute)
6008 *
6009 * @NUM_NL80211_PMSR_REQ_ATTRS: internal
6010 * @NL80211_PMSR_REQ_ATTR_MAX: highest attribute number
6011 */
6012enum nl80211_peer_measurement_req {
6013 __NL80211_PMSR_REQ_ATTR_INVALID,
6014
6015 NL80211_PMSR_REQ_ATTR_DATA,
6016 NL80211_PMSR_REQ_ATTR_GET_AP_TSF,
6017
6018 /* keep last */
6019 NUM_NL80211_PMSR_REQ_ATTRS,
6020 NL80211_PMSR_REQ_ATTR_MAX = NUM_NL80211_PMSR_REQ_ATTRS - 1
6021};
6022
6023/**
6024 * enum nl80211_peer_measurement_resp - peer measurement response attributes
6025 * @__NL80211_PMSR_RESP_ATTR_INVALID: invalid
6026 *
6027 * @NL80211_PMSR_RESP_ATTR_DATA: This is a nested attribute with measurement
6028 * type-specific results inside. The attributes used are from the enums
6029 * named nl80211_peer_measurement_<type>_resp.
6030 * @NL80211_PMSR_RESP_ATTR_STATUS: u32 value with the measurement status
6031 * (using values from &enum nl80211_peer_measurement_status.)
6032 * @NL80211_PMSR_RESP_ATTR_HOST_TIME: host time (%CLOCK_BOOTTIME) when the
6033 * result was measured; this value is not expected to be accurate to
6034 * more than 20ms. (u64, nanoseconds)
6035 * @NL80211_PMSR_RESP_ATTR_AP_TSF: TSF of the AP that the interface
6036 * doing the measurement is connected to when the result was measured.
6037 * This shall be accurately reported if supported and requested
6038 * (u64, usec)
6039 * @NL80211_PMSR_RESP_ATTR_FINAL: If results are sent to the host partially
6040 * (*e.g. with FTM per-burst data) this flag will be cleared on all but
6041 * the last result; if all results are combined it's set on the single
6042 * result.
6043 * @NL80211_PMSR_RESP_ATTR_PAD: padding for 64-bit attributes, ignore
6044 *
6045 * @NUM_NL80211_PMSR_RESP_ATTRS: internal
6046 * @NL80211_PMSR_RESP_ATTR_MAX: highest attribute number
6047 */
6048enum nl80211_peer_measurement_resp {
6049 __NL80211_PMSR_RESP_ATTR_INVALID,
6050
6051 NL80211_PMSR_RESP_ATTR_DATA,
6052 NL80211_PMSR_RESP_ATTR_STATUS,
6053 NL80211_PMSR_RESP_ATTR_HOST_TIME,
6054 NL80211_PMSR_RESP_ATTR_AP_TSF,
6055 NL80211_PMSR_RESP_ATTR_FINAL,
6056 NL80211_PMSR_RESP_ATTR_PAD,
6057
6058 /* keep last */
6059 NUM_NL80211_PMSR_RESP_ATTRS,
6060 NL80211_PMSR_RESP_ATTR_MAX = NUM_NL80211_PMSR_RESP_ATTRS - 1
6061};
6062
6063/**
6064 * enum nl80211_peer_measurement_peer_attrs - peer attributes for measurement
6065 * @__NL80211_PMSR_PEER_ATTR_INVALID: invalid
6066 *
6067 * @NL80211_PMSR_PEER_ATTR_ADDR: peer's MAC address
6068 * @NL80211_PMSR_PEER_ATTR_CHAN: channel definition, nested, using top-level
6069 * attributes like %NL80211_ATTR_WIPHY_FREQ etc.
6070 * @NL80211_PMSR_PEER_ATTR_REQ: This is a nested attribute indexed by
6071 * measurement type, with attributes from the
6072 * &enum nl80211_peer_measurement_req inside.
6073 * @NL80211_PMSR_PEER_ATTR_RESP: This is a nested attribute indexed by
6074 * measurement type, with attributes from the
6075 * &enum nl80211_peer_measurement_resp inside.
6076 *
6077 * @NUM_NL80211_PMSR_PEER_ATTRS: internal
6078 * @NL80211_PMSR_PEER_ATTR_MAX: highest attribute number
6079 */
6080enum nl80211_peer_measurement_peer_attrs {
6081 __NL80211_PMSR_PEER_ATTR_INVALID,
6082
6083 NL80211_PMSR_PEER_ATTR_ADDR,
6084 NL80211_PMSR_PEER_ATTR_CHAN,
6085 NL80211_PMSR_PEER_ATTR_REQ,
6086 NL80211_PMSR_PEER_ATTR_RESP,
6087
6088 /* keep last */
6089 NUM_NL80211_PMSR_PEER_ATTRS,
6090 NL80211_PMSR_PEER_ATTR_MAX = NUM_NL80211_PMSR_PEER_ATTRS - 1,
6091};
6092
6093/**
6094 * enum nl80211_peer_measurement_attrs - peer measurement attributes
6095 * @__NL80211_PMSR_ATTR_INVALID: invalid
6096 *
6097 * @NL80211_PMSR_ATTR_MAX_PEERS: u32 attribute used for capability
6098 * advertisement only, indicates the maximum number of peers
6099 * measurements can be done with in a single request
6100 * @NL80211_PMSR_ATTR_REPORT_AP_TSF: flag attribute in capability
6101 * indicating that the connected AP's TSF can be reported in
6102 * measurement results
6103 * @NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR: flag attribute in capability
6104 * indicating that MAC address randomization is supported.
6105 * @NL80211_PMSR_ATTR_TYPE_CAPA: capabilities reported by the device,
6106 * this contains a nesting indexed by measurement type, and
6107 * type-specific capabilities inside, which are from the enums
6108 * named nl80211_peer_measurement_<type>_capa.
6109 * @NL80211_PMSR_ATTR_PEERS: nested attribute, the nesting index is
6110 * meaningless, just a list of peers to measure with, with the
6111 * sub-attributes taken from
6112 * &enum nl80211_peer_measurement_peer_attrs.
6113 *
6114 * @NUM_NL80211_PMSR_ATTR: internal
6115 * @NL80211_PMSR_ATTR_MAX: highest attribute number
6116 */
6117enum nl80211_peer_measurement_attrs {
6118 __NL80211_PMSR_ATTR_INVALID,
6119
6120 NL80211_PMSR_ATTR_MAX_PEERS,
6121 NL80211_PMSR_ATTR_REPORT_AP_TSF,
6122 NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR,
6123 NL80211_PMSR_ATTR_TYPE_CAPA,
6124 NL80211_PMSR_ATTR_PEERS,
6125
6126 /* keep last */
6127 NUM_NL80211_PMSR_ATTR,
6128 NL80211_PMSR_ATTR_MAX = NUM_NL80211_PMSR_ATTR - 1
6129};
6130
6131/**
6132 * enum nl80211_peer_measurement_ftm_capa - FTM capabilities
6133 * @__NL80211_PMSR_FTM_CAPA_ATTR_INVALID: invalid
6134 *
6135 * @NL80211_PMSR_FTM_CAPA_ATTR_ASAP: flag attribute indicating ASAP mode
6136 * is supported
6137 * @NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP: flag attribute indicating non-ASAP
6138 * mode is supported
6139 * @NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI: flag attribute indicating if LCI
6140 * data can be requested during the measurement
6141 * @NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC: flag attribute indicating if civic
6142 * location data can be requested during the measurement
6143 * @NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES: u32 bitmap attribute of bits
6144 * from &enum nl80211_preamble.
6145 * @NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS: bitmap of values from
6146 * &enum nl80211_chan_width indicating the supported channel
6147 * bandwidths for FTM. Note that a higher channel bandwidth may be
6148 * configured to allow for other measurements types with different
6149 * bandwidth requirement in the same measurement.
6150 * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT: u32 attribute indicating
6151 * the maximum bursts exponent that can be used (if not present anything
6152 * is valid)
6153 * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST: u32 attribute indicating
6154 * the maximum FTMs per burst (if not present anything is valid)
6155 *
6156 * @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal
6157 * @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number
6158 */
6159enum nl80211_peer_measurement_ftm_capa {
6160 __NL80211_PMSR_FTM_CAPA_ATTR_INVALID,
6161
6162 NL80211_PMSR_FTM_CAPA_ATTR_ASAP,
6163 NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP,
6164 NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI,
6165 NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC,
6166 NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
6167 NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
6168 NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
6169 NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
6170
6171 /* keep last */
6172 NUM_NL80211_PMSR_FTM_CAPA_ATTR,
6173 NL80211_PMSR_FTM_CAPA_ATTR_MAX = NUM_NL80211_PMSR_FTM_CAPA_ATTR - 1
6174};
6175
6176/**
6177 * enum nl80211_peer_measurement_ftm_req - FTM request attributes
6178 * @__NL80211_PMSR_FTM_REQ_ATTR_INVALID: invalid
6179 *
6180 * @NL80211_PMSR_FTM_REQ_ATTR_ASAP: ASAP mode requested (flag)
6181 * @NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE: preamble type (see
6182 * &enum nl80211_preamble), optional for DMG (u32)
6183 * @NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP: number of bursts exponent as in
6184 * 802.11-2016 9.4.2.168 "Fine Timing Measurement Parameters element"
6185 * (u8, 0-15, optional with default 15 i.e. "no preference")
6186 * @NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD: interval between bursts in units
6187 * of 100ms (u16, optional with default 0)
6188 * @NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION: burst duration, as in 802.11-2016
6189 * Table 9-257 "Burst Duration field encoding" (u8, 0-15, optional with
6190 * default 15 i.e. "no preference")
6191 * @NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST: number of successful FTM frames
6192 * requested per burst
6193 * (u8, 0-31, optional with default 0 i.e. "no preference")
6194 * @NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES: number of FTMR frame retries
6195 * (u8, default 3)
6196 * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI: request LCI data (flag)
6197 * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC: request civic location data
6198 * (flag)
6199 *
6200 * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
6201 * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
6202 */
6203enum nl80211_peer_measurement_ftm_req {
6204 __NL80211_PMSR_FTM_REQ_ATTR_INVALID,
6205
6206 NL80211_PMSR_FTM_REQ_ATTR_ASAP,
6207 NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE,
6208 NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP,
6209 NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD,
6210 NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION,
6211 NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST,
6212 NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES,
6213 NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI,
6214 NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC,
6215
6216 /* keep last */
6217 NUM_NL80211_PMSR_FTM_REQ_ATTR,
6218 NL80211_PMSR_FTM_REQ_ATTR_MAX = NUM_NL80211_PMSR_FTM_REQ_ATTR - 1
6219};
6220
6221/**
6222 * enum nl80211_peer_measurement_ftm_failure_reasons - FTM failure reasons
6223 * @NL80211_PMSR_FTM_FAILURE_UNSPECIFIED: unspecified failure, not used
6224 * @NL80211_PMSR_FTM_FAILURE_NO_RESPONSE: no response from the FTM responder
6225 * @NL80211_PMSR_FTM_FAILURE_REJECTED: FTM responder rejected measurement
6226 * @NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL: we already know the peer is
6227 * on a different channel, so can't measure (if we didn't know, we'd
6228 * try and get no response)
6229 * @NL80211_PMSR_FTM_FAILURE_PEER_NOT_CAPABLE: peer can't actually do FTM
6230 * @NL80211_PMSR_FTM_FAILURE_INVALID_TIMESTAMP: invalid T1/T4 timestamps
6231 * received
6232 * @NL80211_PMSR_FTM_FAILURE_PEER_BUSY: peer reports busy, you may retry
6233 * later (see %NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME)
6234 * @NL80211_PMSR_FTM_FAILURE_BAD_CHANGED_PARAMS: parameters were changed
6235 * by the peer and are no longer supported
6236 */
6237enum nl80211_peer_measurement_ftm_failure_reasons {
6238 NL80211_PMSR_FTM_FAILURE_UNSPECIFIED,
6239 NL80211_PMSR_FTM_FAILURE_NO_RESPONSE,
6240 NL80211_PMSR_FTM_FAILURE_REJECTED,
6241 NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL,
6242 NL80211_PMSR_FTM_FAILURE_PEER_NOT_CAPABLE,
6243 NL80211_PMSR_FTM_FAILURE_INVALID_TIMESTAMP,
6244 NL80211_PMSR_FTM_FAILURE_PEER_BUSY,
6245 NL80211_PMSR_FTM_FAILURE_BAD_CHANGED_PARAMS,
6246};
6247
6248/**
6249 * enum nl80211_peer_measurement_ftm_resp - FTM response attributes
6250 * @__NL80211_PMSR_FTM_RESP_ATTR_INVALID: invalid
6251 *
6252 * @NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON: FTM-specific failure reason
6253 * (u32, optional)
6254 * @NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX: optional, if bursts are reported
6255 * as separate results then it will be the burst index 0...(N-1) and
6256 * the top level will indicate partial results (u32)
6257 * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS: number of FTM Request frames
6258 * transmitted (u32, optional)
6259 * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES: number of FTM Request frames
6260 * that were acknowleged (u32, optional)
6261 * @NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME: retry time received from the
6262 * busy peer (u32, seconds)
6263 * @NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP: actual number of bursts exponent
6264 * used by the responder (similar to request, u8)
6265 * @NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION: actual burst duration used by
6266 * the responder (similar to request, u8)
6267 * @NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST: actual FTMs per burst used
6268 * by the responder (similar to request, u8)
6269 * @NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG: average RSSI across all FTM action
6270 * frames (optional, s32, 1/2 dBm)
6271 * @NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD: RSSI spread across all FTM action
6272 * frames (optional, s32, 1/2 dBm)
6273 * @NL80211_PMSR_FTM_RESP_ATTR_TX_RATE: bitrate we used for the response to the
6274 * FTM action frame (optional, nested, using &enum nl80211_rate_info
6275 * attributes)
6276 * @NL80211_PMSR_FTM_RESP_ATTR_RX_RATE: bitrate the responder used for the FTM
6277 * action frame (optional, nested, using &enum nl80211_rate_info attrs)
6278 * @NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG: average RTT (s64, picoseconds, optional
6279 * but one of RTT/DIST must be present)
6280 * @NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE: RTT variance (u64, ps^2, note that
6281 * standard deviation is the square root of variance, optional)
6282 * @NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD: RTT spread (u64, picoseconds,
6283 * optional)
6284 * @NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG: average distance (s64, mm, optional
6285 * but one of RTT/DIST must be present)
6286 * @NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE: distance variance (u64, mm^2, note
6287 * that standard deviation is the square root of variance, optional)
6288 * @NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD: distance spread (u64, mm, optional)
6289 * @NL80211_PMSR_FTM_RESP_ATTR_LCI: LCI data from peer (binary, optional)
6290 * @NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC: civic location data from peer
6291 * (binary, optional)
6292 * @NL80211_PMSR_FTM_RESP_ATTR_PAD: ignore, for u64/s64 padding only
6293 *
6294 * @NUM_NL80211_PMSR_FTM_RESP_ATTR: internal
6295 * @NL80211_PMSR_FTM_RESP_ATTR_MAX: highest attribute number
6296 */
6297enum nl80211_peer_measurement_ftm_resp {
6298 __NL80211_PMSR_FTM_RESP_ATTR_INVALID,
6299
6300 NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON,
6301 NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX,
6302 NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS,
6303 NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES,
6304 NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME,
6305 NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP,
6306 NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION,
6307 NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST,
6308 NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG,
6309 NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD,
6310 NL80211_PMSR_FTM_RESP_ATTR_TX_RATE,
6311 NL80211_PMSR_FTM_RESP_ATTR_RX_RATE,
6312 NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG,
6313 NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE,
6314 NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD,
6315 NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG,
6316 NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE,
6317 NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD,
6318 NL80211_PMSR_FTM_RESP_ATTR_LCI,
6319 NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC,
6320 NL80211_PMSR_FTM_RESP_ATTR_PAD,
6321
6322 /* keep last */
6323 NUM_NL80211_PMSR_FTM_RESP_ATTR,
6324 NL80211_PMSR_FTM_RESP_ATTR_MAX = NUM_NL80211_PMSR_FTM_RESP_ATTR - 1
6325};
6326
5909#endif /* __LINUX_NL80211_H */ 6327#endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 1d84f91bbfb0..72a224ce8e0a 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
12 12
13cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o 13cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
14cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o 14cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o
15cfg80211-y += pmsr.o
15cfg80211-$(CONFIG_OF) += of.o 16cfg80211-$(CONFIG_OF) += of.o
16cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o 17cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
17cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o 18cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 5bd01058b9e6..0a3092c56b3e 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -4,6 +4,7 @@
4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH 5 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * Copyright 2015-2017 Intel Deutschland GmbH 6 * Copyright 2015-2017 Intel Deutschland GmbH
7 * Copyright (C) 2018 Intel Corporation
7 */ 8 */
8 9
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -664,6 +665,34 @@ int wiphy_register(struct wiphy *wiphy)
664 return -EINVAL; 665 return -EINVAL;
665#endif 666#endif
666 667
668 if (WARN_ON(wiphy->pmsr_capa && !wiphy->pmsr_capa->ftm.supported))
669 return -EINVAL;
670
671 if (wiphy->pmsr_capa && wiphy->pmsr_capa->ftm.supported) {
672 if (WARN_ON(!wiphy->pmsr_capa->ftm.asap &&
673 !wiphy->pmsr_capa->ftm.non_asap))
674 return -EINVAL;
675 if (WARN_ON(!wiphy->pmsr_capa->ftm.preambles ||
676 !wiphy->pmsr_capa->ftm.bandwidths))
677 return -EINVAL;
678 if (WARN_ON(wiphy->pmsr_capa->ftm.preambles &
679 ~(BIT(NL80211_PREAMBLE_LEGACY) |
680 BIT(NL80211_PREAMBLE_HT) |
681 BIT(NL80211_PREAMBLE_VHT) |
682 BIT(NL80211_PREAMBLE_DMG))))
683 return -EINVAL;
684 if (WARN_ON(wiphy->pmsr_capa->ftm.bandwidths &
685 ~(BIT(NL80211_CHAN_WIDTH_20_NOHT) |
686 BIT(NL80211_CHAN_WIDTH_20) |
687 BIT(NL80211_CHAN_WIDTH_40) |
688 BIT(NL80211_CHAN_WIDTH_80) |
689 BIT(NL80211_CHAN_WIDTH_80P80) |
690 BIT(NL80211_CHAN_WIDTH_160) |
691 BIT(NL80211_CHAN_WIDTH_5) |
692 BIT(NL80211_CHAN_WIDTH_10))))
693 return -EINVAL;
694 }
695
667 /* 696 /*
668 * if a wiphy has unsupported modes for regulatory channel enforcement, 697 * if a wiphy has unsupported modes for regulatory channel enforcement,
669 * opt-out of enforcement checking 698 * opt-out of enforcement checking
@@ -1087,6 +1116,8 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
1087 ASSERT_RTNL(); 1116 ASSERT_RTNL();
1088 ASSERT_WDEV_LOCK(wdev); 1117 ASSERT_WDEV_LOCK(wdev);
1089 1118
1119 cfg80211_pmsr_wdev_down(wdev);
1120
1090 switch (wdev->iftype) { 1121 switch (wdev->iftype) {
1091 case NL80211_IFTYPE_ADHOC: 1122 case NL80211_IFTYPE_ADHOC:
1092 __cfg80211_leave_ibss(rdev, dev, true); 1123 __cfg80211_leave_ibss(rdev, dev, true);
@@ -1174,6 +1205,9 @@ void cfg80211_init_wdev(struct cfg80211_registered_device *rdev,
1174 spin_lock_init(&wdev->event_lock); 1205 spin_lock_init(&wdev->event_lock);
1175 INIT_LIST_HEAD(&wdev->mgmt_registrations); 1206 INIT_LIST_HEAD(&wdev->mgmt_registrations);
1176 spin_lock_init(&wdev->mgmt_registrations_lock); 1207 spin_lock_init(&wdev->mgmt_registrations_lock);
1208 INIT_LIST_HEAD(&wdev->pmsr_list);
1209 spin_lock_init(&wdev->pmsr_lock);
1210 INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
1177 1211
1178 /* 1212 /*
1179 * We get here also when the interface changes network namespaces, 1213 * We get here also when the interface changes network namespaces,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index c61dbba8bf47..c5d6f3418601 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -3,6 +3,7 @@
3 * Wireless configuration interface internals. 3 * Wireless configuration interface internals.
4 * 4 *
5 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright (C) 2018 Intel Corporation
6 */ 7 */
7#ifndef __NET_WIRELESS_CORE_H 8#ifndef __NET_WIRELESS_CORE_H
8#define __NET_WIRELESS_CORE_H 9#define __NET_WIRELESS_CORE_H
@@ -530,4 +531,8 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
530 531
531void cfg80211_cqm_config_free(struct wireless_dev *wdev); 532void cfg80211_cqm_config_free(struct wireless_dev *wdev);
532 533
534void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid);
535void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev);
536void cfg80211_pmsr_free_wk(struct work_struct *work);
537
533#endif /* __NET_WIRELESS_CORE_H */ 538#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 744b5851bbf9..6fd93eb0df6d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -240,7 +240,63 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
240 .len = U8_MAX }, 240 .len = U8_MAX },
241}; 241};
242 242
243static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { 243static const struct nla_policy
244nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
245 [NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG },
246 [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 },
247 [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
248 NLA_POLICY_MAX(NLA_U8, 15),
249 [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
250 [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
251 NLA_POLICY_MAX(NLA_U8, 15),
252 [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
253 NLA_POLICY_MAX(NLA_U8, 15),
254 [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
255 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
256 [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
257};
258
259static const struct nla_policy
260nl80211_pmsr_req_data_policy[NL80211_PMSR_TYPE_MAX + 1] = {
261 [NL80211_PMSR_TYPE_FTM] =
262 NLA_POLICY_NESTED(NL80211_PMSR_FTM_REQ_ATTR_MAX,
263 nl80211_pmsr_ftm_req_attr_policy),
264};
265
266static const struct nla_policy
267nl80211_pmsr_req_attr_policy[NL80211_PMSR_REQ_ATTR_MAX + 1] = {
268 [NL80211_PMSR_REQ_ATTR_DATA] =
269 NLA_POLICY_NESTED(NL80211_PMSR_TYPE_MAX,
270 nl80211_pmsr_req_data_policy),
271 [NL80211_PMSR_REQ_ATTR_GET_AP_TSF] = { .type = NLA_FLAG },
272};
273
274static const struct nla_policy
275nl80211_psmr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = {
276 [NL80211_PMSR_PEER_ATTR_ADDR] = NLA_POLICY_ETH_ADDR,
277 /*
278 * we could specify this again to be the top-level policy,
279 * but that would open us up to recursion problems ...
280 */
281 [NL80211_PMSR_PEER_ATTR_CHAN] = { .type = NLA_NESTED },
282 [NL80211_PMSR_PEER_ATTR_REQ] =
283 NLA_POLICY_NESTED(NL80211_PMSR_REQ_ATTR_MAX,
284 nl80211_pmsr_req_attr_policy),
285 [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT },
286};
287
288static const struct nla_policy
289nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = {
290 [NL80211_PMSR_ATTR_MAX_PEERS] = { .type = NLA_REJECT },
291 [NL80211_PMSR_ATTR_REPORT_AP_TSF] = { .type = NLA_REJECT },
292 [NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR] = { .type = NLA_REJECT },
293 [NL80211_PMSR_ATTR_TYPE_CAPA] = { .type = NLA_REJECT },
294 [NL80211_PMSR_ATTR_PEERS] =
295 NLA_POLICY_NESTED_ARRAY(NL80211_PMSR_PEER_ATTR_MAX,
296 nl80211_psmr_peer_attr_policy),
297};
298
299const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
244 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, 300 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
245 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, 301 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
246 .len = 20-1 }, 302 .len = 20-1 },
@@ -497,6 +553,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
497 .type = NLA_NESTED, 553 .type = NLA_NESTED,
498 .validation_data = nl80211_ftm_responder_policy, 554 .validation_data = nl80211_ftm_responder_policy,
499 }, 555 },
556 [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
557 [NL80211_ATTR_PEER_MEASUREMENTS] =
558 NLA_POLICY_NESTED(NL80211_PMSR_FTM_REQ_ATTR_MAX,
559 nl80211_pmsr_attr_policy),
500}; 560};
501 561
502/* policy for the key attributes */ 562/* policy for the key attributes */
@@ -637,9 +697,9 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
637 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 }, 697 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
638}; 698};
639 699
640static int nl80211_prepare_wdev_dump(struct netlink_callback *cb, 700int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
641 struct cfg80211_registered_device **rdev, 701 struct cfg80211_registered_device **rdev,
642 struct wireless_dev **wdev) 702 struct wireless_dev **wdev)
643{ 703{
644 int err; 704 int err;
645 705
@@ -684,8 +744,8 @@ static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
684} 744}
685 745
686/* message building helper */ 746/* message building helper */
687static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq, 747void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
688 int flags, u8 cmd) 748 int flags, u8 cmd)
689{ 749{
690 /* since there is no private header just add the generic one */ 750 /* since there is no private header just add the generic one */
691 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd); 751 return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
@@ -1615,6 +1675,91 @@ static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev,
1615 return -ENOBUFS; 1675 return -ENOBUFS;
1616} 1676}
1617 1677
1678static int
1679nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
1680 struct sk_buff *msg)
1681{
1682 struct nlattr *ftm;
1683
1684 if (!cap->ftm.supported)
1685 return 0;
1686
1687 ftm = nla_nest_start(msg, NL80211_PMSR_TYPE_FTM);
1688 if (!ftm)
1689 return -ENOBUFS;
1690
1691 if (cap->ftm.asap && nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_ASAP))
1692 return -ENOBUFS;
1693 if (cap->ftm.non_asap &&
1694 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP))
1695 return -ENOBUFS;
1696 if (cap->ftm.request_lci &&
1697 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI))
1698 return -ENOBUFS;
1699 if (cap->ftm.request_civicloc &&
1700 nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC))
1701 return -ENOBUFS;
1702 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES,
1703 cap->ftm.preambles))
1704 return -ENOBUFS;
1705 if (nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
1706 cap->ftm.bandwidths))
1707 return -ENOBUFS;
1708 if (cap->ftm.max_bursts_exponent >= 0 &&
1709 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
1710 cap->ftm.max_bursts_exponent))
1711 return -ENOBUFS;
1712 if (cap->ftm.max_ftms_per_burst &&
1713 nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
1714 cap->ftm.max_ftms_per_burst))
1715 return -ENOBUFS;
1716
1717 nla_nest_end(msg, ftm);
1718 return 0;
1719}
1720
1721static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev,
1722 struct sk_buff *msg)
1723{
1724 const struct cfg80211_pmsr_capabilities *cap = rdev->wiphy.pmsr_capa;
1725 struct nlattr *pmsr, *caps;
1726
1727 if (!cap)
1728 return 0;
1729
1730 /*
1731 * we don't need to clean up anything here since the caller
1732 * will genlmsg_cancel() if we fail
1733 */
1734
1735 pmsr = nla_nest_start(msg, NL80211_ATTR_PEER_MEASUREMENTS);
1736 if (!pmsr)
1737 return -ENOBUFS;
1738
1739 if (nla_put_u32(msg, NL80211_PMSR_ATTR_MAX_PEERS, cap->max_peers))
1740 return -ENOBUFS;
1741
1742 if (cap->report_ap_tsf &&
1743 nla_put_flag(msg, NL80211_PMSR_ATTR_REPORT_AP_TSF))
1744 return -ENOBUFS;
1745
1746 if (cap->randomize_mac_addr &&
1747 nla_put_flag(msg, NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR))
1748 return -ENOBUFS;
1749
1750 caps = nla_nest_start(msg, NL80211_PMSR_ATTR_TYPE_CAPA);
1751 if (!caps)
1752 return -ENOBUFS;
1753
1754 if (nl80211_send_pmsr_ftm_capa(cap, msg))
1755 return -ENOBUFS;
1756
1757 nla_nest_end(msg, caps);
1758 nla_nest_end(msg, pmsr);
1759
1760 return 0;
1761}
1762
1618struct nl80211_dump_wiphy_state { 1763struct nl80211_dump_wiphy_state {
1619 s64 filter_wiphy; 1764 s64 filter_wiphy;
1620 long start; 1765 long start;
@@ -2118,6 +2263,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
2118 goto nla_put_failure; 2263 goto nla_put_failure;
2119 } 2264 }
2120 2265
2266 state->split_start++;
2267 break;
2268 case 14:
2269 if (nl80211_send_pmsr_capa(rdev, msg))
2270 goto nla_put_failure;
2271
2121 /* done */ 2272 /* done */
2122 state->split_start = 0; 2273 state->split_start = 0;
2123 break; 2274 break;
@@ -2318,9 +2469,9 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
2318 wdev->iftype == NL80211_IFTYPE_P2P_GO; 2469 wdev->iftype == NL80211_IFTYPE_P2P_GO;
2319} 2470}
2320 2471
2321static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, 2472int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
2322 struct genl_info *info, 2473 struct genl_info *info,
2323 struct cfg80211_chan_def *chandef) 2474 struct cfg80211_chan_def *chandef)
2324{ 2475{
2325 struct netlink_ext_ack *extack = info->extack; 2476 struct netlink_ext_ack *extack = info->extack;
2326 struct nlattr **attrs = info->attrs; 2477 struct nlattr **attrs = info->attrs;
@@ -2794,12 +2945,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
2794 return 0; 2945 return 0;
2795} 2946}
2796 2947
2797static inline u64 wdev_id(struct wireless_dev *wdev)
2798{
2799 return (u64)wdev->identifier |
2800 ((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32);
2801}
2802
2803static int nl80211_send_chandef(struct sk_buff *msg, 2948static int nl80211_send_chandef(struct sk_buff *msg,
2804 const struct cfg80211_chan_def *chandef) 2949 const struct cfg80211_chan_def *chandef)
2805{ 2950{
@@ -4521,8 +4666,7 @@ static int parse_station_flags(struct genl_info *info,
4521 return 0; 4666 return 0;
4522} 4667}
4523 4668
4524static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, 4669bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
4525 int attr)
4526{ 4670{
4527 struct nlattr *rate; 4671 struct nlattr *rate;
4528 u32 bitrate; 4672 u32 bitrate;
@@ -6855,8 +6999,8 @@ static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
6855 return 0; 6999 return 0;
6856} 7000}
6857 7001
6858static int nl80211_parse_random_mac(struct nlattr **attrs, 7002int nl80211_parse_random_mac(struct nlattr **attrs,
6859 u8 *mac_addr, u8 *mac_addr_mask) 7003 u8 *mac_addr, u8 *mac_addr_mask)
6860{ 7004{
6861 int i; 7005 int i;
6862 7006
@@ -13898,6 +14042,14 @@ static const struct genl_ops nl80211_ops[] = {
13898 .internal_flags = NL80211_FLAG_NEED_NETDEV | 14042 .internal_flags = NL80211_FLAG_NEED_NETDEV |
13899 NL80211_FLAG_NEED_RTNL, 14043 NL80211_FLAG_NEED_RTNL,
13900 }, 14044 },
14045 {
14046 .cmd = NL80211_CMD_PEER_MEASUREMENT_START,
14047 .doit = nl80211_pmsr_start,
14048 .policy = nl80211_policy,
14049 .flags = GENL_UNS_ADMIN_PERM,
14050 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
14051 NL80211_FLAG_NEED_RTNL,
14052 },
13901}; 14053};
13902 14054
13903static struct genl_family nl80211_fam __ro_after_init = { 14055static struct genl_family nl80211_fam __ro_after_init = {
@@ -15881,6 +16033,8 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
15881 } else if (wdev->conn_owner_nlportid == notify->portid) { 16033 } else if (wdev->conn_owner_nlportid == notify->portid) {
15882 schedule_work(&wdev->disconnect_wk); 16034 schedule_work(&wdev->disconnect_wk);
15883 } 16035 }
16036
16037 cfg80211_release_pmsr(wdev, notify->portid);
15884 } 16038 }
15885 16039
15886 spin_lock_bh(&rdev->beacon_registrations_lock); 16040 spin_lock_bh(&rdev->beacon_registrations_lock);
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 79e47fe60c35..531c82dcba6b 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -1,4 +1,8 @@
1/* SPDX-License-Identifier: GPL-2.0 */ 1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Portions of this file
4 * Copyright (C) 2018 Intel Corporation
5 */
2#ifndef __NET_WIRELESS_NL80211_H 6#ifndef __NET_WIRELESS_NL80211_H
3#define __NET_WIRELESS_NL80211_H 7#define __NET_WIRELESS_NL80211_H
4 8
@@ -6,6 +10,30 @@
6 10
7int nl80211_init(void); 11int nl80211_init(void);
8void nl80211_exit(void); 12void nl80211_exit(void);
13
14extern const struct nla_policy nl80211_policy[NUM_NL80211_ATTR];
15
16void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
17 int flags, u8 cmd);
18bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
19 int attr);
20
21static inline u64 wdev_id(struct wireless_dev *wdev)
22{
23 return (u64)wdev->identifier |
24 ((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32);
25}
26
27int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
28 struct cfg80211_registered_device **rdev,
29 struct wireless_dev **wdev);
30
31int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
32 struct genl_info *info,
33 struct cfg80211_chan_def *chandef);
34int nl80211_parse_random_mac(struct nlattr **attrs,
35 u8 *mac_addr, u8 *mac_addr_mask);
36
9void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev, 37void nl80211_notify_wiphy(struct cfg80211_registered_device *rdev,
10 enum nl80211_commands cmd); 38 enum nl80211_commands cmd);
11void nl80211_notify_iface(struct cfg80211_registered_device *rdev, 39void nl80211_notify_iface(struct cfg80211_registered_device *rdev,
@@ -95,4 +123,8 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev);
95 123
96void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev); 124void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
97 125
126/* peer measurement */
127int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info);
128int nl80211_pmsr_dump_results(struct sk_buff *skb, struct netlink_callback *cb);
129
98#endif /* __NET_WIRELESS_NL80211_H */ 130#endif /* __NET_WIRELESS_NL80211_H */
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
new file mode 100644
index 000000000000..de9286703280
--- /dev/null
+++ b/net/wireless/pmsr.c
@@ -0,0 +1,590 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2018 Intel Corporation
4 */
5#ifndef __PMSR_H
6#define __PMSR_H
7#include <net/cfg80211.h>
8#include "core.h"
9#include "nl80211.h"
10#include "rdev-ops.h"
11
12static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
13 struct nlattr *ftmreq,
14 struct cfg80211_pmsr_request_peer *out,
15 struct genl_info *info)
16{
17 const struct cfg80211_pmsr_capabilities *capa = rdev->wiphy.pmsr_capa;
18 struct nlattr *tb[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1];
19 u32 preamble = NL80211_PREAMBLE_DMG; /* only optional in DMG */
20
21 /* validate existing data */
22 if (!(rdev->wiphy.pmsr_capa->ftm.bandwidths & BIT(out->chandef.width))) {
23 NL_SET_ERR_MSG(info->extack, "FTM: unsupported bandwidth");
24 return -EINVAL;
25 }
26
27 /* no validation needed - was already done via nested policy */
28 nla_parse_nested(tb, NL80211_PMSR_FTM_REQ_ATTR_MAX, ftmreq, NULL, NULL);
29
30 if (tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE])
31 preamble = nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE]);
32
33 /* set up values - struct is 0-initialized */
34 out->ftm.requested = true;
35
36 switch (out->chandef.chan->band) {
37 case NL80211_BAND_60GHZ:
38 /* optional */
39 break;
40 default:
41 if (!tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE]) {
42 NL_SET_ERR_MSG(info->extack,
43 "FTM: must specify preamble");
44 return -EINVAL;
45 }
46 }
47
48 if (!(capa->ftm.preambles & BIT(preamble))) {
49 NL_SET_ERR_MSG_ATTR(info->extack,
50 tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE],
51 "FTM: invalid preamble");
52 return -EINVAL;
53 }
54
55 out->ftm.preamble = preamble;
56
57 out->ftm.burst_period = 0;
58 if (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD])
59 out->ftm.burst_period =
60 nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD]);
61
62 out->ftm.asap = !!tb[NL80211_PMSR_FTM_REQ_ATTR_ASAP];
63 if (out->ftm.asap && !capa->ftm.asap) {
64 NL_SET_ERR_MSG_ATTR(info->extack,
65 tb[NL80211_PMSR_FTM_REQ_ATTR_ASAP],
66 "FTM: ASAP mode not supported");
67 return -EINVAL;
68 }
69
70 if (!out->ftm.asap && !capa->ftm.non_asap) {
71 NL_SET_ERR_MSG(info->extack,
72 "FTM: non-ASAP mode not supported");
73 return -EINVAL;
74 }
75
76 out->ftm.num_bursts_exp = 0;
77 if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP])
78 out->ftm.num_bursts_exp =
79 nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP]);
80
81 if (capa->ftm.max_bursts_exponent >= 0 &&
82 out->ftm.num_bursts_exp > capa->ftm.max_bursts_exponent) {
83 NL_SET_ERR_MSG_ATTR(info->extack,
84 tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP],
85 "FTM: max NUM_BURSTS_EXP must be set lower than the device limit");
86 return -EINVAL;
87 }
88
89 out->ftm.burst_duration = 15;
90 if (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION])
91 out->ftm.burst_duration =
92 nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION]);
93
94 out->ftm.ftms_per_burst = 0;
95 if (tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST])
96 out->ftm.ftms_per_burst =
97 nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST]);
98
99 if (capa->ftm.max_ftms_per_burst &&
100 (out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst ||
101 out->ftm.ftms_per_burst == 0)) {
102 NL_SET_ERR_MSG_ATTR(info->extack,
103 tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST],
104 "FTM: FTMs per burst must be set lower than the device limit but non-zero");
105 return -EINVAL;
106 }
107
108 out->ftm.ftmr_retries = 3;
109 if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES])
110 out->ftm.ftmr_retries =
111 nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES]);
112
113 out->ftm.request_lci = !!tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI];
114 if (out->ftm.request_lci && !capa->ftm.request_lci) {
115 NL_SET_ERR_MSG_ATTR(info->extack,
116 tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI],
117 "FTM: LCI request not supported");
118 }
119
120 out->ftm.request_civicloc =
121 !!tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC];
122 if (out->ftm.request_civicloc && !capa->ftm.request_civicloc) {
123 NL_SET_ERR_MSG_ATTR(info->extack,
124 tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC],
125 "FTM: civic location request not supported");
126 }
127
128 return 0;
129}
130
131static int pmsr_parse_peer(struct cfg80211_registered_device *rdev,
132 struct nlattr *peer,
133 struct cfg80211_pmsr_request_peer *out,
134 struct genl_info *info)
135{
136 struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1];
137 struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1];
138 struct nlattr *treq;
139 int err, rem;
140
141 /* no validation needed - was already done via nested policy */
142 nla_parse_nested(tb, NL80211_PMSR_PEER_ATTR_MAX, peer, NULL, NULL);
143
144 if (!tb[NL80211_PMSR_PEER_ATTR_ADDR] ||
145 !tb[NL80211_PMSR_PEER_ATTR_CHAN] ||
146 !tb[NL80211_PMSR_PEER_ATTR_REQ]) {
147 NL_SET_ERR_MSG_ATTR(info->extack, peer,
148 "insufficient peer data");
149 return -EINVAL;
150 }
151
152 memcpy(out->addr, nla_data(tb[NL80211_PMSR_PEER_ATTR_ADDR]), ETH_ALEN);
153
154 /* reuse info->attrs */
155 memset(info->attrs, 0, sizeof(*info->attrs) * (NL80211_ATTR_MAX + 1));
156 /* need to validate here, we don't want to have validation recursion */
157 err = nla_parse_nested(info->attrs, NL80211_ATTR_MAX,
158 tb[NL80211_PMSR_PEER_ATTR_CHAN],
159 nl80211_policy, info->extack);
160 if (err)
161 return err;
162
163 err = nl80211_parse_chandef(rdev, info, &out->chandef);
164 if (err)
165 return err;
166
167 /* no validation needed - was already done via nested policy */
168 nla_parse_nested(req, NL80211_PMSR_REQ_ATTR_MAX,
169 tb[NL80211_PMSR_PEER_ATTR_REQ],
170 NULL, NULL);
171
172 if (!req[NL80211_PMSR_REQ_ATTR_DATA]) {
173 NL_SET_ERR_MSG_ATTR(info->extack,
174 tb[NL80211_PMSR_PEER_ATTR_REQ],
175 "missing request type/data");
176 return -EINVAL;
177 }
178
179 if (req[NL80211_PMSR_REQ_ATTR_GET_AP_TSF])
180 out->report_ap_tsf = true;
181
182 if (out->report_ap_tsf && !rdev->wiphy.pmsr_capa->report_ap_tsf) {
183 NL_SET_ERR_MSG_ATTR(info->extack,
184 req[NL80211_PMSR_REQ_ATTR_GET_AP_TSF],
185 "reporting AP TSF is not supported");
186 return -EINVAL;
187 }
188
189 nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) {
190 switch (nla_type(treq)) {
191 case NL80211_PMSR_TYPE_FTM:
192 err = pmsr_parse_ftm(rdev, treq, out, info);
193 break;
194 default:
195 NL_SET_ERR_MSG_ATTR(info->extack, treq,
196 "unsupported measurement type");
197 err = -EINVAL;
198 }
199 }
200
201 if (err)
202 return err;
203
204 return 0;
205}
206
207int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
208{
209 struct nlattr *reqattr = info->attrs[NL80211_ATTR_PEER_MEASUREMENTS];
210 struct cfg80211_registered_device *rdev = info->user_ptr[0];
211 struct wireless_dev *wdev = info->user_ptr[1];
212 struct cfg80211_pmsr_request *req;
213 struct nlattr *peers, *peer;
214 int count, rem, err, idx;
215
216 if (!rdev->wiphy.pmsr_capa)
217 return -EOPNOTSUPP;
218
219 if (!reqattr)
220 return -EINVAL;
221
222 peers = nla_find(nla_data(reqattr), nla_len(reqattr),
223 NL80211_PMSR_ATTR_PEERS);
224 if (!peers)
225 return -EINVAL;
226
227 count = 0;
228 nla_for_each_nested(peer, peers, rem) {
229 count++;
230
231 if (count > rdev->wiphy.pmsr_capa->max_peers) {
232 NL_SET_ERR_MSG_ATTR(info->extack, peer,
233 "Too many peers used");
234 return -EINVAL;
235 }
236 }
237
238 req = kzalloc(struct_size(req, peers, count), GFP_KERNEL);
239 if (!req)
240 return -ENOMEM;
241
242 if (info->attrs[NL80211_ATTR_TIMEOUT])
243 req->timeout = nla_get_u32(info->attrs[NL80211_ATTR_TIMEOUT]);
244
245 if (info->attrs[NL80211_ATTR_MAC]) {
246 if (!rdev->wiphy.pmsr_capa->randomize_mac_addr) {
247 NL_SET_ERR_MSG_ATTR(info->extack,
248 info->attrs[NL80211_ATTR_MAC],
249 "device cannot randomize MAC address");
250 err = -EINVAL;
251 goto out_err;
252 }
253
254 err = nl80211_parse_random_mac(info->attrs, req->mac_addr,
255 req->mac_addr_mask);
256 if (err)
257 goto out_err;
258 } else {
259 memcpy(req->mac_addr, nla_data(info->attrs[NL80211_ATTR_MAC]),
260 ETH_ALEN);
261 memset(req->mac_addr_mask, 0xff, ETH_ALEN);
262 }
263
264 idx = 0;
265 nla_for_each_nested(peer, peers, rem) {
266 /* NB: this reuses info->attrs, but we no longer need it */
267 err = pmsr_parse_peer(rdev, peer, &req->peers[idx], info);
268 if (err)
269 goto out_err;
270 idx++;
271 }
272
273 req->n_peers = count;
274 req->cookie = cfg80211_assign_cookie(rdev);
275
276 err = rdev_start_pmsr(rdev, wdev, req);
277 if (err)
278 goto out_err;
279
280 list_add_tail(&req->list, &wdev->pmsr_list);
281
282 nl_set_extack_cookie_u64(info->extack, req->cookie);
283 return 0;
284out_err:
285 kfree(req);
286 return err;
287}
288
289void cfg80211_pmsr_complete(struct wireless_dev *wdev,
290 struct cfg80211_pmsr_request *req,
291 gfp_t gfp)
292{
293 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
294 struct sk_buff *msg;
295 void *hdr;
296
297 trace_cfg80211_pmsr_complete(wdev->wiphy, wdev, req->cookie);
298
299 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
300 if (!msg)
301 goto free_request;
302
303 hdr = nl80211hdr_put(msg, 0, 0, 0,
304 NL80211_CMD_PEER_MEASUREMENT_COMPLETE);
305 if (!hdr)
306 goto free_msg;
307
308 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
309 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
310 NL80211_ATTR_PAD))
311 goto free_msg;
312
313 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->cookie,
314 NL80211_ATTR_PAD))
315 goto free_msg;
316
317 genlmsg_end(msg, hdr);
318 genlmsg_unicast(wiphy_net(wdev->wiphy), msg, req->nl_portid);
319 goto free_request;
320free_msg:
321 nlmsg_free(msg);
322free_request:
323 spin_lock_bh(&wdev->pmsr_lock);
324 list_del(&req->list);
325 spin_unlock_bh(&wdev->pmsr_lock);
326 kfree(req);
327}
328EXPORT_SYMBOL_GPL(cfg80211_pmsr_complete);
329
330static int nl80211_pmsr_send_ftm_res(struct sk_buff *msg,
331 struct cfg80211_pmsr_result *res)
332{
333 if (res->status == NL80211_PMSR_STATUS_FAILURE) {
334 if (nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON,
335 res->ftm.failure_reason))
336 goto error;
337
338 if (res->ftm.failure_reason ==
339 NL80211_PMSR_FTM_FAILURE_PEER_BUSY &&
340 res->ftm.busy_retry_time &&
341 nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME,
342 res->ftm.busy_retry_time))
343 goto error;
344
345 return 0;
346 }
347
348#define PUT(tp, attr, val) \
349 do { \
350 if (nla_put_##tp(msg, \
351 NL80211_PMSR_FTM_RESP_ATTR_##attr, \
352 res->ftm.val)) \
353 goto error; \
354 } while (0)
355
356#define PUTOPT(tp, attr, val) \
357 do { \
358 if (res->ftm.val##_valid) \
359 PUT(tp, attr, val); \
360 } while (0)
361
362#define PUT_U64(attr, val) \
363 do { \
364 if (nla_put_u64_64bit(msg, \
365 NL80211_PMSR_FTM_RESP_ATTR_##attr,\
366 res->ftm.val, \
367 NL80211_PMSR_FTM_RESP_ATTR_PAD)) \
368 goto error; \
369 } while (0)
370
371#define PUTOPT_U64(attr, val) \
372 do { \
373 if (res->ftm.val##_valid) \
374 PUT_U64(attr, val); \
375 } while (0)
376
377 if (res->ftm.burst_index >= 0)
378 PUT(u32, BURST_INDEX, burst_index);
379 PUTOPT(u32, NUM_FTMR_ATTEMPTS, num_ftmr_attempts);
380 PUTOPT(u32, NUM_FTMR_SUCCESSES, num_ftmr_successes);
381 PUT(u8, NUM_BURSTS_EXP, num_bursts_exp);
382 PUT(u8, BURST_DURATION, burst_duration);
383 PUT(u8, FTMS_PER_BURST, ftms_per_burst);
384 PUTOPT(s32, RSSI_AVG, rssi_avg);
385 PUTOPT(s32, RSSI_SPREAD, rssi_spread);
386 if (res->ftm.tx_rate_valid &&
387 !nl80211_put_sta_rate(msg, &res->ftm.tx_rate,
388 NL80211_PMSR_FTM_RESP_ATTR_TX_RATE))
389 goto error;
390 if (res->ftm.rx_rate_valid &&
391 !nl80211_put_sta_rate(msg, &res->ftm.rx_rate,
392 NL80211_PMSR_FTM_RESP_ATTR_RX_RATE))
393 goto error;
394 PUTOPT_U64(RTT_AVG, rtt_avg);
395 PUTOPT_U64(RTT_VARIANCE, rtt_variance);
396 PUTOPT_U64(RTT_SPREAD, rtt_spread);
397 PUTOPT_U64(DIST_AVG, dist_avg);
398 PUTOPT_U64(DIST_VARIANCE, dist_variance);
399 PUTOPT_U64(DIST_SPREAD, dist_spread);
400 if (res->ftm.lci && res->ftm.lci_len &&
401 nla_put(msg, NL80211_PMSR_FTM_RESP_ATTR_LCI,
402 res->ftm.lci_len, res->ftm.lci))
403 goto error;
404 if (res->ftm.civicloc && res->ftm.civicloc_len &&
405 nla_put(msg, NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC,
406 res->ftm.civicloc_len, res->ftm.civicloc))
407 goto error;
408#undef PUT
409#undef PUTOPT
410#undef PUT_U64
411#undef PUTOPT_U64
412
413 return 0;
414error:
415 return -ENOSPC;
416}
417
418static int nl80211_pmsr_send_result(struct sk_buff *msg,
419 struct cfg80211_pmsr_result *res)
420{
421 struct nlattr *pmsr, *peers, *peer, *resp, *data, *typedata;
422
423 pmsr = nla_nest_start(msg, NL80211_ATTR_PEER_MEASUREMENTS);
424 if (!pmsr)
425 goto error;
426
427 peers = nla_nest_start(msg, NL80211_PMSR_ATTR_PEERS);
428 if (!peers)
429 goto error;
430
431 peer = nla_nest_start(msg, 1);
432 if (!peer)
433 goto error;
434
435 if (nla_put(msg, NL80211_PMSR_PEER_ATTR_ADDR, ETH_ALEN, res->addr))
436 goto error;
437
438 resp = nla_nest_start(msg, NL80211_PMSR_PEER_ATTR_RESP);
439 if (!resp)
440 goto error;
441
442 if (nla_put_u32(msg, NL80211_PMSR_RESP_ATTR_STATUS, res->status) ||
443 nla_put_u64_64bit(msg, NL80211_PMSR_RESP_ATTR_HOST_TIME,
444 res->host_time, NL80211_PMSR_RESP_ATTR_PAD))
445 goto error;
446
447 if (res->ap_tsf_valid &&
448 nla_put_u64_64bit(msg, NL80211_PMSR_RESP_ATTR_AP_TSF,
449 res->host_time, NL80211_PMSR_RESP_ATTR_PAD))
450 goto error;
451
452 if (res->final && nla_put_flag(msg, NL80211_PMSR_RESP_ATTR_FINAL))
453 goto error;
454
455 data = nla_nest_start(msg, NL80211_PMSR_RESP_ATTR_DATA);
456 if (!data)
457 goto error;
458
459 typedata = nla_nest_start(msg, res->type);
460 if (!typedata)
461 goto error;
462
463 switch (res->type) {
464 case NL80211_PMSR_TYPE_FTM:
465 if (nl80211_pmsr_send_ftm_res(msg, res))
466 goto error;
467 break;
468 default:
469 WARN_ON(1);
470 }
471
472 nla_nest_end(msg, typedata);
473 nla_nest_end(msg, data);
474 nla_nest_end(msg, resp);
475 nla_nest_end(msg, peer);
476 nla_nest_end(msg, peers);
477 nla_nest_end(msg, pmsr);
478
479 return 0;
480error:
481 return -ENOSPC;
482}
483
484void cfg80211_pmsr_report(struct wireless_dev *wdev,
485 struct cfg80211_pmsr_request *req,
486 struct cfg80211_pmsr_result *result,
487 gfp_t gfp)
488{
489 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
490 struct sk_buff *msg;
491 void *hdr;
492 int err;
493
494 trace_cfg80211_pmsr_report(wdev->wiphy, wdev, req->cookie,
495 result->addr);
496
497 /*
498 * Currently, only variable items are LCI and civic location,
499 * both of which are reasonably short so we don't need to
500 * worry about them here for the allocation.
501 */
502 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
503 if (!msg)
504 return;
505
506 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PEER_MEASUREMENT_RESULT);
507 if (!hdr)
508 goto free;
509
510 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
511 nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
512 NL80211_ATTR_PAD))
513 goto free;
514
515 if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->cookie,
516 NL80211_ATTR_PAD))
517 goto free;
518
519 err = nl80211_pmsr_send_result(msg, result);
520 if (err) {
521 pr_err_ratelimited("peer measurement result: message didn't fit!");
522 goto free;
523 }
524
525 genlmsg_end(msg, hdr);
526 genlmsg_unicast(wiphy_net(wdev->wiphy), msg, req->nl_portid);
527 return;
528free:
529 nlmsg_free(msg);
530}
531EXPORT_SYMBOL_GPL(cfg80211_pmsr_report);
532
533void cfg80211_pmsr_free_wk(struct work_struct *work)
534{
535 struct wireless_dev *wdev = container_of(work, struct wireless_dev,
536 pmsr_free_wk);
537 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
538 struct cfg80211_pmsr_request *req, *tmp;
539 LIST_HEAD(free_list);
540
541 spin_lock_bh(&wdev->pmsr_lock);
542 list_for_each_entry_safe(req, tmp, &wdev->pmsr_list, list) {
543 if (req->nl_portid)
544 continue;
545 list_move_tail(&req->list, &free_list);
546 }
547 spin_unlock_bh(&wdev->pmsr_lock);
548
549 list_for_each_entry_safe(req, tmp, &free_list, list) {
550 wdev_lock(wdev);
551 rdev_abort_pmsr(rdev, wdev, req);
552 wdev_unlock(wdev);
553
554 kfree(req);
555 }
556}
557
558void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
559{
560 struct cfg80211_pmsr_request *req;
561 bool found = false;
562
563 spin_lock_bh(&wdev->pmsr_lock);
564 list_for_each_entry(req, &wdev->pmsr_list, list) {
565 found = true;
566 req->nl_portid = 0;
567 }
568 spin_unlock_bh(&wdev->pmsr_lock);
569
570 if (found)
571 schedule_work(&wdev->pmsr_free_wk);
572 flush_work(&wdev->pmsr_free_wk);
573 WARN_ON(!list_empty(&wdev->pmsr_list));
574}
575
576void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid)
577{
578 struct cfg80211_pmsr_request *req;
579
580 spin_lock_bh(&wdev->pmsr_lock);
581 list_for_each_entry(req, &wdev->pmsr_list, list) {
582 if (req->nl_portid == portid) {
583 req->nl_portid = 0;
584 schedule_work(&wdev->pmsr_free_wk);
585 }
586 }
587 spin_unlock_bh(&wdev->pmsr_lock);
588}
589
590#endif /* __PMSR_H */
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 51380b5c32f2..5cb48d135fab 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1247,4 +1247,29 @@ rdev_get_ftm_responder_stats(struct cfg80211_registered_device *rdev,
1247 return ret; 1247 return ret;
1248} 1248}
1249 1249
1250static inline int
1251rdev_start_pmsr(struct cfg80211_registered_device *rdev,
1252 struct wireless_dev *wdev,
1253 struct cfg80211_pmsr_request *request)
1254{
1255 int ret = -EOPNOTSUPP;
1256
1257 trace_rdev_start_pmsr(&rdev->wiphy, wdev, request->cookie);
1258 if (rdev->ops->start_pmsr)
1259 ret = rdev->ops->start_pmsr(&rdev->wiphy, wdev, request);
1260 trace_rdev_return_int(&rdev->wiphy, ret);
1261 return ret;
1262}
1263
1264static inline void
1265rdev_abort_pmsr(struct cfg80211_registered_device *rdev,
1266 struct wireless_dev *wdev,
1267 struct cfg80211_pmsr_request *request)
1268{
1269 trace_rdev_abort_pmsr(&rdev->wiphy, wdev, request->cookie);
1270 if (rdev->ops->abort_pmsr)
1271 rdev->ops->abort_pmsr(&rdev->wiphy, wdev, request);
1272 trace_rdev_return_void(&rdev->wiphy);
1273}
1274
1250#endif /* __CFG80211_RDEV_OPS */ 1275#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index f7909867d8fb..44b2ce1bb13a 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -361,6 +361,24 @@ DECLARE_EVENT_CLASS(wiphy_wdev_evt,
361 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) 361 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
362); 362);
363 363
364DECLARE_EVENT_CLASS(wiphy_wdev_cookie_evt,
365 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
366 TP_ARGS(wiphy, wdev, cookie),
367 TP_STRUCT__entry(
368 WIPHY_ENTRY
369 WDEV_ENTRY
370 __field(u64, cookie)
371 ),
372 TP_fast_assign(
373 WIPHY_ASSIGN;
374 WDEV_ASSIGN;
375 __entry->cookie = cookie;
376 ),
377 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie: %lld",
378 WIPHY_PR_ARG, WDEV_PR_ARG,
379 (unsigned long long)__entry->cookie)
380);
381
364DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev, 382DEFINE_EVENT(wiphy_wdev_evt, rdev_return_wdev,
365 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), 383 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
366 TP_ARGS(wiphy, wdev) 384 TP_ARGS(wiphy, wdev)
@@ -2502,6 +2520,16 @@ TRACE_EVENT(rdev_get_ftm_responder_stats,
2502 __entry->out_of_window) 2520 __entry->out_of_window)
2503); 2521);
2504 2522
2523DEFINE_EVENT(wiphy_wdev_cookie_evt, rdev_start_pmsr,
2524 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
2525 TP_ARGS(wiphy, wdev, cookie)
2526);
2527
2528DEFINE_EVENT(wiphy_wdev_cookie_evt, rdev_abort_pmsr,
2529 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
2530 TP_ARGS(wiphy, wdev, cookie)
2531);
2532
2505/************************************************************* 2533/*************************************************************
2506 * cfg80211 exported functions traces * 2534 * cfg80211 exported functions traces *
2507 *************************************************************/ 2535 *************************************************************/
@@ -3294,6 +3322,46 @@ TRACE_EVENT(cfg80211_stop_iface,
3294 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, 3322 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
3295 WIPHY_PR_ARG, WDEV_PR_ARG) 3323 WIPHY_PR_ARG, WDEV_PR_ARG)
3296); 3324);
3325
3326TRACE_EVENT(cfg80211_pmsr_report,
3327 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
3328 u64 cookie, const u8 *addr),
3329 TP_ARGS(wiphy, wdev, cookie, addr),
3330 TP_STRUCT__entry(
3331 WIPHY_ENTRY
3332 WDEV_ENTRY
3333 __field(u64, cookie)
3334 MAC_ENTRY(addr)
3335 ),
3336 TP_fast_assign(
3337 WIPHY_ASSIGN;
3338 WDEV_ASSIGN;
3339 __entry->cookie = cookie;
3340 MAC_ASSIGN(addr, addr);
3341 ),
3342 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie:%lld, " MAC_PR_FMT,
3343 WIPHY_PR_ARG, WDEV_PR_ARG,
3344 (unsigned long long)__entry->cookie,
3345 MAC_PR_ARG(addr))
3346);
3347
3348TRACE_EVENT(cfg80211_pmsr_complete,
3349 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie),
3350 TP_ARGS(wiphy, wdev, cookie),
3351 TP_STRUCT__entry(
3352 WIPHY_ENTRY
3353 WDEV_ENTRY
3354 __field(u64, cookie)
3355 ),
3356 TP_fast_assign(
3357 WIPHY_ASSIGN;
3358 WDEV_ASSIGN;
3359 __entry->cookie = cookie;
3360 ),
3361 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie:%lld",
3362 WIPHY_PR_ARG, WDEV_PR_ARG,
3363 (unsigned long long)__entry->cookie)
3364);
3297#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ 3365#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
3298 3366
3299#undef TRACE_INCLUDE_PATH 3367#undef TRACE_INCLUDE_PATH