History

Merge tag 'mac80211-next-for-davem-2018-10-12' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says: ==================== Highlights: * merge net-next, so I can finish the hwsim workqueue removal * fix TXQ NULL pointer issue that was reported multiple times * minstrel cleanups from Felix * simplify lib80211 code by not using skcipher, note that this will conflict with the crypto tree (and this new code here should be used) * use new netlink policy validation in nl80211 * fix up SAE (part of WPA3) in client-mode * FTM responder support in the stack ====================

David S. Miller committed 8 years ago

Commit e32cf9a2 parents 9163a0f f8252e731 files · +1338 −1136Browse files

Unified · Split

31 files
  1. drivers/net/wireless/mac80211_hwsim.c +1 −10
  2. include/linux/ieee80211.h +1 −0
  3. include/net/cfg80211.h +59 −3
  4. include/net/mac80211.h +43 −0
  5. include/uapi/linux/nl80211.h +98 −0
  6. net/mac80211/Kconfig +1 −16
  7. net/mac80211/Makefile +6 −5
  8. net/mac80211/cfg.c +85 −0
  9. net/mac80211/driver-ops.h +16 −0
  10. net/mac80211/ieee80211_i.h +1 −0
  11. net/mac80211/main.c +3 −8
  12. net/mac80211/mlme.c +69 −38
  13. net/mac80211/rate.h +0 −13
  14. net/mac80211/rc80211_minstrel.c +0 −162
  15. net/mac80211/rc80211_minstrel.h +1 −34
  16. net/mac80211/rc80211_minstrel_debugfs.c +4 −64
  17. net/mac80211/rc80211_minstrel_ht.c +191 −107
  18. net/mac80211/rc80211_minstrel_ht.h +4 −16
  19. net/mac80211/rc80211_minstrel_ht_debugfs.c +33 −25
  20. net/mac80211/rx.c +6 −6
  21. net/mac80211/status.c +19 −0
  22. net/mac80211/trace.h +23 −0
  23. net/mac80211/util.c +8 −0
  24. net/wireless/core.c +47 −36
  25. net/wireless/core.h +14 −0
  26. net/wireless/lib80211_crypt_tkip.c +20 −39
  27. net/wireless/lib80211_crypt_wep.c +20 −32
  28. net/wireless/nl80211.c +407 −423
  29. net/wireless/rdev-ops.h +15 −0
  30. net/wireless/reg.c +9 −0
  31. net/wireless/trace.h +134 −99
drivers/net/wireless/mac80211_hwsim.c+1−10
@@ -495,7 +495,6 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = { · 494 unmodified lines
495495
496496 static spinlock_t hwsim_radio_lock;
497497 static LIST_HEAD(hwsim_radios);
498−static struct workqueue_struct *hwsim_wq;
499498 static struct rhashtable hwsim_radios_rht;
500499 static int hwsim_radio_idx;
501500 static int hwsim_radios_generation = 1;
@@ -3692,13 +3691,9 @@ static int __init init_mac80211_hwsim(void) · 3190 unmodified lines
36923691
36933692 spin_lock_init(&hwsim_radio_lock);
36943693
3695− hwsim_wq = alloc_workqueue("hwsim_wq", 0, 0);
3696− if (!hwsim_wq)
3697− return -ENOMEM;
3698−
36993694 err = rhashtable_init(&hwsim_radios_rht, &hwsim_rht_params);
37003695 if (err)
3701− goto out_free_wq;
3696+ return err;
37023697
37033698 err = register_pernet_device(&hwsim_net_ops);
37043699 if (err)
@@ -3829,8 +3824,6 @@ out_unregister_pernet: · 124 unmodified lines
38293824 unregister_pernet_device(&hwsim_net_ops);
38303825 out_free_rht:
38313826 rhashtable_destroy(&hwsim_radios_rht);
3832−out_free_wq:
3833− destroy_workqueue(hwsim_wq);
38343827 return err;
38353828 }
38363829 module_init(init_mac80211_hwsim);
@@ -3842,12 +3835,10 @@ static void __exit exit_mac80211_hwsim(void) · 5 unmodified lines
38423835 hwsim_exit_netlink();
38433836
38443837 mac80211_hwsim_free();
3845− flush_workqueue(hwsim_wq);
38463838
38473839 rhashtable_destroy(&hwsim_radios_rht);
38483840 unregister_netdev(hwsim_mon);
38493841 platform_driver_unregister(&mac80211_hwsim_driver);
38503842 unregister_pernet_device(&hwsim_net_ops);
3851− destroy_workqueue(hwsim_wq);
38523843 }
38533844 module_exit(exit_mac80211_hwsim);
include/linux/ieee80211.h+1−0
@@ -1670,6 +1670,7 @@ struct ieee80211_mu_edca_param_set { · 1669 unmodified lines
16701670 #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
16711671 #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
16721672 #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700
1673+#define IEEE80211_VHT_CAP_RXSTBC_SHIFT 8
16731674 #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
16741675 #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
16751676 #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13
include/net/cfg80211.h+59−3
@@ -775,6 +775,12 @@ struct cfg80211_crypto_settings { · 774 unmodified lines
775775 * @assocresp_ies_len: length of assocresp_ies in octets
776776 * @probe_resp_len: length of probe response template (@probe_resp)
777777 * @probe_resp: probe response template (AP mode only)
778+ * @ftm_responder: enable FTM responder functionality; -1 for no change
779+ * (which also implies no change in LCI/civic location data)
780+ * @lci: LCI subelement content
781+ * @civicloc: Civic location subelement content
782+ * @lci_len: LCI data length
783+ * @civicloc_len: Civic location data length
778784 */
779785 struct cfg80211_beacon_data {
780786 const u8 *head, *tail;
@@ -782,12 +788,17 @@ struct cfg80211_beacon_data { · 1 unmodified line
782788 const u8 *proberesp_ies;
783789 const u8 *assocresp_ies;
784790 const u8 *probe_resp;
791+ const u8 *lci;
792+ const u8 *civicloc;
793+ s8 ftm_responder;
785794
786795 size_t head_len, tail_len;
787796 size_t beacon_ies_len;
788797 size_t proberesp_ies_len;
789798 size_t assocresp_ies_len;
790799 size_t probe_resp_len;
800+ size_t lci_len;
801+ size_t civicloc_len;
791802 };
792803
793804 struct mac_address {
@@ -1292,6 +1303,10 @@ struct cfg80211_tid_stats { · 498 unmodified lines
12921303 * @ack_signal: signal strength (in dBm) of the last ACK frame.
12931304 * @avg_ack_signal: average rssi value of ack packet for the no of msdu's has
12941305 * been sent.
1306+ * @rx_mpdu_count: number of MPDUs received from this station
1307+ * @fcs_err_count: number of packets (MPDUs) received from this station with
1308+ * an FCS error. This counter should be incremented only when TA of the
1309+ * received packet with an FCS error matches the peer MAC address.
12951310 */
12961311 struct station_info {
12971312 u64 filled;
@@ -1338,6 +1353,9 @@ struct station_info { · 40 unmodified lines
13381353 struct cfg80211_tid_stats *pertid;
13391354 s8 ack_signal;
13401355 s8 avg_ack_signal;
1356+
1357+ u32 rx_mpdu_count;
1358+ u32 fcs_err_count;
13411359 };
13421360
13431361 #if IS_ENABLED(CONFIG_CFG80211)
@@ -2796,6 +2814,40 @@ struct cfg80211_external_auth_params { · 1452 unmodified lines
27962814 u16 status;
27972815 };
27982816
2817+/**
2818+ * cfg80211_ftm_responder_stats - FTM responder statistics
2819+ *
2820+ * @filled: bitflag of flags using the bits of &enum nl80211_ftm_stats to
2821+ * indicate the relevant values in this struct for them
2822+ * @success_num: number of FTM sessions in which all frames were successfully
2823+ * answered
2824+ * @partial_num: number of FTM sessions in which part of frames were
2825+ * successfully answered
2826+ * @failed_num: number of failed FTM sessions
2827+ * @asap_num: number of ASAP FTM sessions
2828+ * @non_asap_num: number of non-ASAP FTM sessions
2829+ * @total_duration_ms: total sessions durations - gives an indication
2830+ * of how much time the responder was busy
2831+ * @unknown_triggers_num: number of unknown FTM triggers - triggers from
2832+ * initiators that didn't finish successfully the negotiation phase with
2833+ * the responder
2834+ * @reschedule_requests_num: number of FTM reschedule requests - initiator asks
2835+ * for a new scheduling although it already has scheduled FTM slot
2836+ * @out_of_window_triggers_num: total FTM triggers out of scheduled window
2837+ */
2838+struct cfg80211_ftm_responder_stats {
2839+ u32 filled;
2840+ u32 success_num;
2841+ u32 partial_num;
2842+ u32 failed_num;
2843+ u32 asap_num;
2844+ u32 non_asap_num;
2845+ u64 total_duration_ms;
2846+ u32 unknown_triggers_num;
2847+ u32 reschedule_requests_num;
2848+ u32 out_of_window_triggers_num;
2849+};
2850+
27992851 /**
28002852 * struct cfg80211_ops - backend description for wireless configuration
28012853 *
@@ -3128,6 +3180,9 @@ struct cfg80211_external_auth_params { · 326 unmodified lines
31283180 *
31293181 * @tx_control_port: TX a control port frame (EAPoL). The noencrypt parameter
31303182 * tells the driver that the frame should not be encrypted.
3183+ *
3184+ * @get_ftm_responder_stats: Retrieve FTM responder statistics, if available.
3185+ * Statistics should be cumulative, currently no way to reset is provided.
31313186 */
31323187 struct cfg80211_ops {
31333188 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3433,6 +3488,10 @@ struct cfg80211_ops { · 299 unmodified lines
34333488 const u8 *buf, size_t len,
34343489 const u8 *dest, const __be16 proto,
34353490 const bool noencrypt);
3491+
3492+ int (*get_ftm_responder_stats)(struct wiphy *wiphy,
3493+ struct net_device *dev,
3494+ struct cfg80211_ftm_responder_stats *ftm_stats);
34363495 };
34373496
34383497 /*
@@ -3960,7 +4019,6 @@ struct wiphy_iftype_ext_capab { · 521 unmodified lines
39604019 * by the driver in the .connect() callback. The bit position maps to the
39614020 * attribute indices defined in &enum nl80211_bss_select_attr.
39624021 *
3963− * @cookie_counter: unique generic cookie counter, used to identify objects.
39644022 * @nan_supported_bands: bands supported by the device in NAN mode, a
39654023 * bitmap of &enum nl80211_band values. For instance, for
39664024 * NL80211_BAND_2GHZ, bit 0 would be set
@@ -4099,8 +4157,6 @@ struct wiphy { · 132 unmodified lines
40994157
41004158 u32 bss_select_support;
41014159
4102− u64 cookie_counter;
4103−
41044160 u8 nan_supported_bands;
41054161
41064162 u32 txq_limit;
include/net/mac80211.h+43−0
@@ -309,6 +309,8 @@ struct ieee80211_vif_chanctx_switch { · 308 unmodified lines
309309 * @BSS_CHANGED_KEEP_ALIVE: keep alive options (idle period or protected
310310 * keep alive) changed.
311311 * @BSS_CHANGED_MCAST_RATE: Multicast Rate setting changed for this interface
312+ * @BSS_CHANGED_FTM_RESPONDER: fime timing reasurement request responder
313+ * functionality changed for this BSS (AP mode).
312314 *
313315 */
314316 enum ieee80211_bss_change {
@@ -338,6 +340,7 @@ enum ieee80211_bss_change { · 23 unmodified lines
338340 BSS_CHANGED_MU_GROUPS = 1<<23,
339341 BSS_CHANGED_KEEP_ALIVE = 1<<24,
340342 BSS_CHANGED_MCAST_RATE = 1<<25,
343+ BSS_CHANGED_FTM_RESPONDER = 1<<26,
341344
342345 /* when adding here, make sure to change ieee80211_reconfig */
343346 };
@@ -463,6 +466,21 @@ struct ieee80211_mu_group_data { · 119 unmodified lines
463466 u8 position[WLAN_USER_POSITION_LEN];
464467 };
465468
469+/**
470+ * ieee80211_ftm_responder_params - FTM responder parameters
471+ *
472+ * @lci: LCI subelement content
473+ * @civicloc: CIVIC location subelement content
474+ * @lci_len: LCI data length
475+ * @civicloc_len: Civic data length
476+ */
477+struct ieee80211_ftm_responder_params {
478+ const u8 *lci;
479+ const u8 *civicloc;
480+ size_t lci_len;
481+ size_t civicloc_len;
482+};
483+
466484 /**
467485 * struct ieee80211_bss_conf - holds the BSS's changing parameters
468486 *
@@ -562,6 +580,9 @@ struct ieee80211_mu_group_data { · 93 unmodified lines
562580 * @protected_keep_alive: if set, indicates that the station should send an RSN
563581 * protected frame to the AP to reset the idle timer at the AP for the
564582 * station.
583+ * @ftm_responder: whether to enable or disable fine timing measurement FTM
584+ * responder functionality.
585+ * @ftmr_params: configurable lci/civic parameter when enabling FTM responder.
565586 */
566587 struct ieee80211_bss_conf {
567588 const u8 *bssid;
@@ -612,6 +633,8 @@ struct ieee80211_bss_conf { · 44 unmodified lines
612633 bool allow_p2p_go_ps;
613634 u16 max_idle_period;
614635 bool protected_keep_alive;
636+ bool ftm_responder;
637+ struct ieee80211_ftm_responder_params *ftmr_params;
615638 };
616639
617640 /**
@@ -3598,6 +3621,8 @@ enum ieee80211_reconfig_type { · 2980 unmodified lines
35983621 * aggregating two specific frames in the same A-MSDU. The relation
35993622 * between the skbs should be symmetric and transitive. Note that while
36003623 * skb is always a real frame, head may or may not be an A-MSDU.
3624+ * @get_ftm_responder_stats: Retrieve FTM responder statistics, if available.
3625+ * Statistics should be cumulative, currently no way to reset is provided.
36013626 */
36023627 struct ieee80211_ops {
36033628 void (*tx)(struct ieee80211_hw *hw,
@@ -3883,6 +3908,9 @@ struct ieee80211_ops { · 279 unmodified lines
38833908 bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *hw,
38843909 struct sk_buff *head,
38853910 struct sk_buff *skb);
3911+ int (*get_ftm_responder_stats)(struct ieee80211_hw *hw,
3912+ struct ieee80211_vif *vif,
3913+ struct cfg80211_ftm_responder_stats *ftm_stats);
38863914 };
38873915
38883916 /**
@@ -4351,6 +4379,21 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, · 462 unmodified lines
43514379 void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
43524380 u32 thr);
43534381
4382+/**
4383+ * ieee80211_tx_rate_update - transmit rate update callback
4384+ *
4385+ * Drivers should call this functions with a non-NULL pub sta
4386+ * This function can be used in drivers that does not have provision
4387+ * in updating the tx rate in data path.
4388+ *
4389+ * @hw: the hardware the frame was transmitted by
4390+ * @pubsta: the station to update the tx rate for.
4391+ * @info: tx status information
4392+ */
4393+void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
4394+ struct ieee80211_sta *pubsta,
4395+ struct ieee80211_tx_info *info);
4396+
43544397 /**
43554398 * ieee80211_tx_status - transmit status callback
43564399 *
include/uapi/linux/nl80211.h+98−0
@@ -1033,6 +1033,9 @@ · 1032 unmodified lines
10331033 * %NL80211_ATTR_CHANNEL_WIDTH,%NL80211_ATTR_NSS attributes with its
10341034 * address(specified in %NL80211_ATTR_MAC).
10351035 *
1036+ * @NL80211_CMD_GET_FTM_RESPONDER_STATS: Retrieve FTM responder statistics, in
1037+ * the %NL80211_ATTR_FTM_RESPONDER_STATS attribute.
1038+ *
10361039 * @NL80211_CMD_MAX: highest used command number
10371040 * @__NL80211_CMD_AFTER_LAST: internal use
10381041 */
@@ -1245,6 +1248,8 @@ enum nl80211_commands { · 206 unmodified lines
12451248
12461249 NL80211_CMD_CONTROL_PORT_FRAME,
12471250
1251+ NL80211_CMD_GET_FTM_RESPONDER_STATS,
1252+
12481253 /* add new commands above here */
12491254
12501255 /* used to define NL80211_CMD_MAX below */
@@ -2241,6 +2246,14 @@ enum nl80211_commands { · 990 unmodified lines
22412246 * association request when used with NL80211_CMD_NEW_STATION). Can be set
22422247 * only if %NL80211_STA_FLAG_WME is set.
22432248 *
2249+ * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include
2250+ * in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing
2251+ * measurement (FTM) responder functionality and containing parameters as
2252+ * possible, see &enum nl80211_ftm_responder_attr
2253+ *
2254+ * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder
2255+ * statistics, see &enum nl80211_ftm_responder_stats.
2256+ *
22442257 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
22452258 * @NL80211_ATTR_MAX: highest attribute number currently defined
22462259 * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2682,6 +2695,10 @@ enum nl80211_attrs { · 435 unmodified lines
26822695
26832696 NL80211_ATTR_HE_CAPABILITY,
26842697
2698+ NL80211_ATTR_FTM_RESPONDER,
2699+
2700+ NL80211_ATTR_FTM_RESPONDER_STATS,
2701+
26852702 /* add attributes here, update the policy in nl80211.c */
26862703
26872704 __NL80211_ATTR_AFTER_LAST,
@@ -3051,6 +3068,12 @@ enum nl80211_sta_bss_param { · 363 unmodified lines
30513068 * @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment
30523069 * @NL80211_STA_INFO_ACK_SIGNAL: signal strength of the last ACK frame(u8, dBm)
30533070 * @NL80211_STA_INFO_ACK_SIGNAL_AVG: avg signal strength of ACK frames (s8, dBm)
3071+ * @NL80211_STA_INFO_RX_MPDUS: total number of received packets (MPDUs)
3072+ * (u32, from this station)
3073+ * @NL80211_STA_INFO_FCS_ERROR_COUNT: total number of packets (MPDUs) received
3074+ * with an FCS error (u32, from this station). This count may not include
3075+ * some packets with an FCS error due to TA corruption. Hence this counter
3076+ * might not be fully accurate.
30543077 * @__NL80211_STA_INFO_AFTER_LAST: internal
30553078 * @NL80211_STA_INFO_MAX: highest possible station info attribute
30563079 */
@@ -3091,6 +3114,8 @@ enum nl80211_sta_info { · 34 unmodified lines
30913114 NL80211_STA_INFO_PAD,
30923115 NL80211_STA_INFO_ACK_SIGNAL,
30933116 NL80211_STA_INFO_ACK_SIGNAL_AVG,
3117+ NL80211_STA_INFO_RX_MPDUS,
3118+ NL80211_STA_INFO_FCS_ERROR_COUNT,
30943119
30953120 /* keep last */
30963121 __NL80211_STA_INFO_AFTER_LAST,
@@ -5225,6 +5250,8 @@ enum nl80211_feature_flags { · 2128 unmodified lines
52255250 * @NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT: Driver/device can omit all data
52265251 * except for supported rates from the probe request content if requested
52275252 * by the %NL80211_SCAN_FLAG_MIN_PREQ_CONTENT flag.
5253+ * @NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER: Driver supports enabling fine
5254+ * timing measurement responder role.
52285255 *
52295256 * @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0: Driver/device confirm that they are
52305257 * able to rekey an in-use key correctly. Userspace must not rekey PTK keys
@@ -5269,6 +5296,7 @@ enum nl80211_ext_feature_index { · 38 unmodified lines
52695296 NL80211_EXT_FEATURE_SCAN_RANDOM_SN,
52705297 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT,
52715298 NL80211_EXT_FEATURE_CAN_REPLACE_PTK0,
5299+ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
52725300
52735301 /* add new features before the definition below */
52745302 NUM_NL80211_EXT_FEATURES,
@@ -5808,4 +5836,74 @@ enum nl80211_external_auth_action { · 533 unmodified lines
58085836 NL80211_EXTERNAL_AUTH_ABORT,
58095837 };
58105838
5839+/**
5840+ * enum nl80211_ftm_responder_attributes - fine timing measurement
5841+ * responder attributes
5842+ * @__NL80211_FTM_RESP_ATTR_INVALID: Invalid
5843+ * @NL80211_FTM_RESP_ATTR_ENABLED: FTM responder is enabled
5844+ * @NL80211_FTM_RESP_ATTR_LCI: The content of Measurement Report Element
5845+ * (9.4.2.22 in 802.11-2016) with type 8 - LCI (9.4.2.22.10)
5846+ * @NL80211_FTM_RESP_ATTR_CIVIC: The content of Measurement Report Element
5847+ * (9.4.2.22 in 802.11-2016) with type 11 - Civic (Section 9.4.2.22.13)
5848+ * @__NL80211_FTM_RESP_ATTR_LAST: Internal
5849+ * @NL80211_FTM_RESP_ATTR_MAX: highest FTM responder attribute.
5850+ */
5851+enum nl80211_ftm_responder_attributes {
5852+ __NL80211_FTM_RESP_ATTR_INVALID,
5853+
5854+ NL80211_FTM_RESP_ATTR_ENABLED,
5855+ NL80211_FTM_RESP_ATTR_LCI,
5856+ NL80211_FTM_RESP_ATTR_CIVICLOC,
5857+
5858+ /* keep last */
5859+ __NL80211_FTM_RESP_ATTR_LAST,
5860+ NL80211_FTM_RESP_ATTR_MAX = __NL80211_FTM_RESP_ATTR_LAST - 1,
5861+};
5862+
5863+/*
5864+ * enum nl80211_ftm_responder_stats - FTM responder statistics
5865+ *
5866+ * These attribute types are used with %NL80211_ATTR_FTM_RESPONDER_STATS
5867+ * when getting FTM responder statistics.
5868+ *
5869+ * @__NL80211_FTM_STATS_INVALID: attribute number 0 is reserved
5870+ * @NL80211_FTM_STATS_SUCCESS_NUM: number of FTM sessions in which all frames
5871+ * were ssfully answered (u32)
5872+ * @NL80211_FTM_STATS_PARTIAL_NUM: number of FTM sessions in which part of the
5873+ * frames were successfully answered (u32)
5874+ * @NL80211_FTM_STATS_FAILED_NUM: number of failed FTM sessions (u32)
5875+ * @NL80211_FTM_STATS_ASAP_NUM: number of ASAP sessions (u32)
5876+ * @NL80211_FTM_STATS_NON_ASAP_NUM: number of non-ASAP sessions (u32)
5877+ * @NL80211_FTM_STATS_TOTAL_DURATION_MSEC: total sessions durations - gives an
5878+ * indication of how much time the responder was busy (u64, msec)
5879+ * @NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM: number of unknown FTM triggers -
5880+ * triggers from initiators that didn't finish successfully the negotiation
5881+ * phase with the responder (u32)
5882+ * @NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM: number of FTM reschedule requests
5883+ * - initiator asks for a new scheduling although it already has scheduled
5884+ * FTM slot (u32)
5885+ * @NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM: number of FTM triggers out of
5886+ * scheduled window (u32)
5887+ * @NL80211_FTM_STATS_PAD: used for padding, ignore
5888+ * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal
5889+ * @NL80211_FTM_STATS_MAX: highest possible FTM responder stats attribute
5890+ */
5891+enum nl80211_ftm_responder_stats {
5892+ __NL80211_FTM_STATS_INVALID,
5893+ NL80211_FTM_STATS_SUCCESS_NUM,
5894+ NL80211_FTM_STATS_PARTIAL_NUM,
5895+ NL80211_FTM_STATS_FAILED_NUM,
5896+ NL80211_FTM_STATS_ASAP_NUM,
5897+ NL80211_FTM_STATS_NON_ASAP_NUM,
5898+ NL80211_FTM_STATS_TOTAL_DURATION_MSEC,
5899+ NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM,
5900+ NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM,
5901+ NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM,
5902+ NL80211_FTM_STATS_PAD,
5903+
5904+ /* keep last */
5905+ __NL80211_FTM_STATS_AFTER_LAST,
5906+ NL80211_FTM_STATS_MAX = __NL80211_FTM_STATS_AFTER_LAST - 1
5907+};
5908+
58115909 #endif /* __LINUX_NL80211_H */
net/mac80211/Kconfig+1−16
@@ -27,20 +27,6 @@ config MAC80211_RC_MINSTREL · 26 unmodified lines
2727 ---help---
2828 This option enables the 'minstrel' TX rate control algorithm
2929
30−config MAC80211_RC_MINSTREL_HT
31− bool "Minstrel 802.11n support" if EXPERT
32− depends on MAC80211_RC_MINSTREL
33− default y
34− ---help---
35− This option enables the 'minstrel_ht' TX rate control algorithm
36−
37−config MAC80211_RC_MINSTREL_VHT
38− bool "Minstrel 802.11ac support" if EXPERT
39− depends on MAC80211_RC_MINSTREL_HT
40− default n
41− ---help---
42− This option enables VHT in the 'minstrel_ht' TX rate control algorithm
43−
4430 choice
4531 prompt "Default rate control algorithm"
4632 depends on MAC80211_HAS_RC
@@ -62,8 +48,7 @@ endchoice · 15 unmodified lines
6248
6349 config MAC80211_RC_DEFAULT
6450 string
65− default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT
66− default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
51+ default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL
6752 default ""
6853
6954 endif
net/mac80211/Makefile+6−5
@@ -53,13 +53,14 @@ mac80211-$(CONFIG_PM) += pm.o · 52 unmodified lines
5353
5454 CFLAGS_trace.o := -I$(src)
5555
56−rc80211_minstrel-y := rc80211_minstrel.o
57−rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o
56+rc80211_minstrel-y := \
57+ rc80211_minstrel.o \
58+ rc80211_minstrel_ht.o
5859
59−rc80211_minstrel_ht-y := rc80211_minstrel_ht.o
60−rc80211_minstrel_ht-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o
60+rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += \
61+ rc80211_minstrel_debugfs.o \
62+ rc80211_minstrel_ht_debugfs.o
6163
6264 mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
63−mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y)
6465
6566 ccflags-y += -DDEBUG
net/mac80211/cfg.c+85−0
@@ -790,6 +790,48 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, · 789 unmodified lines
790790 return 0;
791791 }
792792
793+static int ieee80211_set_ftm_responder_params(
794+ struct ieee80211_sub_if_data *sdata,
795+ const u8 *lci, size_t lci_len,
796+ const u8 *civicloc, size_t civicloc_len)
797+{
798+ struct ieee80211_ftm_responder_params *new, *old;
799+ struct ieee80211_bss_conf *bss_conf;
800+ u8 *pos;
801+ int len;
802+
803+ if ((!lci || !lci_len) && (!civicloc || !civicloc_len))
804+ return 1;
805+
806+ bss_conf = &sdata->vif.bss_conf;
807+ old = bss_conf->ftmr_params;
808+ len = lci_len + civicloc_len;
809+
810+ new = kzalloc(sizeof(*new) + len, GFP_KERNEL);
811+ if (!new)
812+ return -ENOMEM;
813+
814+ pos = (u8 *)(new + 1);
815+ if (lci_len) {
816+ new->lci_len = lci_len;
817+ new->lci = pos;
818+ memcpy(pos, lci, lci_len);
819+ pos += lci_len;
820+ }
821+
822+ if (civicloc_len) {
823+ new->civicloc_len = civicloc_len;
824+ new->civicloc = pos;
825+ memcpy(pos, civicloc, civicloc_len);
826+ pos += civicloc_len;
827+ }
828+
829+ bss_conf->ftmr_params = new;
830+ kfree(old);
831+
832+ return 0;
833+}
834+
793835 static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
794836 struct cfg80211_beacon_data *params,
795837 const struct ieee80211_csa_settings *csa)
@@ -863,6 +905,20 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, · 67 unmodified lines
863905 if (err == 0)
864906 changed |= BSS_CHANGED_AP_PROBE_RESP;
865907
908+ if (params->ftm_responder != -1) {
909+ sdata->vif.bss_conf.ftm_responder = params->ftm_responder;
910+ err = ieee80211_set_ftm_responder_params(sdata,
911+ params->lci,
912+ params->lci_len,
913+ params->civicloc,
914+ params->civicloc_len);
915+
916+ if (err < 0)
917+ return err;
918+
919+ changed |= BSS_CHANGED_FTM_RESPONDER;
920+ }
921+
866922 rcu_assign_pointer(sdata->u.ap.beacon, new);
867923
868924 if (old)
@@ -1063,6 +1119,9 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) · 194 unmodified lines
10631119 kfree_rcu(old_probe_resp, rcu_head);
10641120 sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
10651121
1122+ kfree(sdata->vif.bss_conf.ftmr_params);
1123+ sdata->vif.bss_conf.ftmr_params = NULL;
1124+
10661125 __sta_info_flush(sdata, true);
10671126 ieee80211_free_keys(sdata, true);
10681127
@@ -2875,6 +2934,20 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) · 1806 unmodified lines
28752934 memcpy(pos, beacon->probe_resp, beacon->probe_resp_len);
28762935 pos += beacon->probe_resp_len;
28772936 }
2937+ if (beacon->ftm_responder)
2938+ new_beacon->ftm_responder = beacon->ftm_responder;
2939+ if (beacon->lci) {
2940+ new_beacon->lci_len = beacon->lci_len;
2941+ new_beacon->lci = pos;
2942+ memcpy(pos, beacon->lci, beacon->lci_len);
2943+ pos += beacon->lci_len;
2944+ }
2945+ if (beacon->civicloc) {
2946+ new_beacon->civicloc_len = beacon->civicloc_len;
2947+ new_beacon->civicloc = pos;
2948+ memcpy(pos, beacon->civicloc, beacon->civicloc_len);
2949+ pos += beacon->civicloc_len;
2950+ }
28782951
28792952 return new_beacon;
28802953 }
@@ -3765,6 +3838,17 @@ out: · 884 unmodified lines
37653838 return ret;
37663839 }
37673840
3841+static int
3842+ieee80211_get_ftm_responder_stats(struct wiphy *wiphy,
3843+ struct net_device *dev,
3844+ struct cfg80211_ftm_responder_stats *ftm_stats)
3845+{
3846+ struct ieee80211_local *local = wiphy_priv(wiphy);
3847+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
3848+
3849+ return drv_get_ftm_responder_stats(local, sdata, ftm_stats);
3850+}
3851+
37683852 const struct cfg80211_ops mac80211_config_ops = {
37693853 .add_virtual_intf = ieee80211_add_iface,
37703854 .del_virtual_intf = ieee80211_del_iface,
@@ -3859,4 +3943,5 @@ const struct cfg80211_ops mac80211_config_ops = { · 88 unmodified lines
38593943 .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
38603944 .tx_control_port = ieee80211_tx_control_port,
38613945 .get_txq_stats = ieee80211_get_txq_stats,
3946+ .get_ftm_responder_stats = ieee80211_get_ftm_responder_stats,
38623947 };
net/mac80211/driver-ops.h+16−0
@@ -1183,6 +1183,22 @@ static inline int drv_can_aggregate_in_amsdu(struct ieee80211_local *local, · 1182 unmodified lines
11831183 return local->ops->can_aggregate_in_amsdu(&local->hw, head, skb);
11841184 }
11851185
1186+static inline int
1187+drv_get_ftm_responder_stats(struct ieee80211_local *local,
1188+ struct ieee80211_sub_if_data *sdata,
1189+ struct cfg80211_ftm_responder_stats *ftm_stats)
1190+{
1191+ u32 ret = -EOPNOTSUPP;
1192+
1193+ if (local->ops->get_ftm_responder_stats)
1194+ ret = local->ops->get_ftm_responder_stats(&local->hw,
1195+ &sdata->vif,
1196+ ftm_stats);
1197+ trace_drv_get_ftm_responder_stats(local, sdata, ftm_stats);
1198+
1199+ return ret;
1200+}
1201+
11861202 static inline int drv_start_nan(struct ieee80211_local *local,
11871203 struct ieee80211_sub_if_data *sdata,
11881204 struct cfg80211_nan_conf *conf)
net/mac80211/ieee80211_i.h+1−0
@@ -377,6 +377,7 @@ struct ieee80211_mgd_auth_data { · 376 unmodified lines
377377 u8 key[WLAN_KEY_LEN_WEP104];
378378 u8 key_len, key_idx;
379379 bool done;
380+ bool peer_confirmed;
380381 bool timeout_started;
381382
382383 u16 sae_trans, sae_status;
net/mac80211/main.c+3−8
@@ -1203,8 +1203,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) · 1202 unmodified lines
12031203 continue;
12041204
12051205 sband = kmemdup(sband, sizeof(*sband), GFP_KERNEL);
1206− if (!sband)
1206+ if (!sband) {
1207+ result = -ENOMEM;
12071208 goto fail_rate;
1209+ }
12081210
12091211 wiphy_dbg(hw->wiphy, "copying sband (band %d) due to VHT EXT NSS BW flag\n",
12101212 band);
@@ -1373,18 +1375,12 @@ static int __init ieee80211_init(void) · 162 unmodified lines
13731375 if (ret)
13741376 return ret;
13751377
1376− ret = rc80211_minstrel_ht_init();
1377− if (ret)
1378− goto err_minstrel;
1379−
13801378 ret = ieee80211_iface_init();
13811379 if (ret)
13821380 goto err_netdev;
13831381
13841382 return 0;
13851383 err_netdev:
1386− rc80211_minstrel_ht_exit();
1387− err_minstrel:
13881384 rc80211_minstrel_exit();
13891385
13901386 return ret;
@@ -1392,7 +1388,6 @@ static int __init ieee80211_init(void) · 1 unmodified line
13921388
13931389 static void __exit ieee80211_exit(void)
13941390 {
1395− rc80211_minstrel_ht_exit();
13961391 rc80211_minstrel_exit();
13971392
13981393 ieee80211s_stop();
net/mac80211/mlme.c+69−38
@@ -2761,13 +2761,40 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, · 2760 unmodified lines
27612761 auth_data->key_idx, tx_flags);
27622762 }
27632763
2764+static bool ieee80211_mark_sta_auth(struct ieee80211_sub_if_data *sdata,
2765+ const u8 *bssid)
2766+{
2767+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2768+ struct sta_info *sta;
2769+
2770+ sdata_info(sdata, "authenticated\n");
2771+ ifmgd->auth_data->done = true;
2772+ ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
2773+ ifmgd->auth_data->timeout_started = true;
2774+ run_again(sdata, ifmgd->auth_data->timeout);
2775+
2776+ /* move station state to auth */
2777+ mutex_lock(&sdata->local->sta_mtx);
2778+ sta = sta_info_get(sdata, bssid);
2779+ if (!sta) {
2780+ WARN_ONCE(1, "%s: STA %pM not found", sdata->name, bssid);
2781+ return false;
2782+ }
2783+ if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) {
2784+ sdata_info(sdata, "failed moving %pM to auth\n", bssid);
2785+ return false;
2786+ }
2787+ mutex_unlock(&sdata->local->sta_mtx);
2788+
2789+ return true;
2790+}
2791+
27642792 static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
27652793 struct ieee80211_mgmt *mgmt, size_t len)
27662794 {
27672795 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
27682796 u8 bssid[ETH_ALEN];
27692797 u16 auth_alg, auth_transaction, status_code;
2770− struct sta_info *sta;
27712798 struct ieee80211_event event = {
27722799 .type = MLME_EVENT,
27732800 .u.mlme.data = AUTH_EVENT,
@@ -2791,7 +2818,11 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, · 17 unmodified lines
27912818 status_code = le16_to_cpu(mgmt->u.auth.status_code);
27922819
27932820 if (auth_alg != ifmgd->auth_data->algorithm ||
2794− auth_transaction != ifmgd->auth_data->expected_transaction) {
2821+ (auth_alg != WLAN_AUTH_SAE &&
2822+ auth_transaction != ifmgd->auth_data->expected_transaction) ||
2823+ (auth_alg == WLAN_AUTH_SAE &&
2824+ (auth_transaction < ifmgd->auth_data->expected_transaction ||
2825+ auth_transaction > 2))) {
27952826 sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n",
27962827 mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
27972828 auth_transaction,
@@ -2834,35 +2865,17 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, · 36 unmodified lines
28342865
28352866 event.u.mlme.status = MLME_SUCCESS;
28362867 drv_event_callback(sdata->local, sdata, &event);
2837− sdata_info(sdata, "authenticated\n");
2838− ifmgd->auth_data->done = true;
2839− ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
2840− ifmgd->auth_data->timeout_started = true;
2841− run_again(sdata, ifmgd->auth_data->timeout);
2842−
2843− if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
2844− ifmgd->auth_data->expected_transaction != 2) {
2845− /*
2846− * Report auth frame to user space for processing since another
2847− * round of Authentication frames is still needed.
2848− */
2849− cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2850− return;
2868+ if (ifmgd->auth_data->algorithm != WLAN_AUTH_SAE ||
2869+ (auth_transaction == 2 &&
2870+ ifmgd->auth_data->expected_transaction == 2)) {
2871+ if (!ieee80211_mark_sta_auth(sdata, bssid))
2872+ goto out_err;
2873+ } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
2874+ auth_transaction == 2) {
2875+ sdata_info(sdata, "SAE peer confirmed\n");
2876+ ifmgd->auth_data->peer_confirmed = true;
28512877 }
28522878
2853− /* move station state to auth */
2854− mutex_lock(&sdata->local->sta_mtx);
2855− sta = sta_info_get(sdata, bssid);
2856− if (!sta) {
2857− WARN_ONCE(1, "%s: STA %pM not found", sdata->name, bssid);
2858− goto out_err;
2859− }
2860− if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) {
2861− sdata_info(sdata, "failed moving %pM to auth\n", bssid);
2862− goto out_err;
2863− }
2864− mutex_unlock(&sdata->local->sta_mtx);
2865−
28662879 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
28672880 return;
28682881 out_err:
@@ -4878,6 +4891,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 2009 unmodified lines
48784891 struct ieee80211_mgd_auth_data *auth_data;
48794892 u16 auth_alg;
48804893 int err;
4894+ bool cont_auth;
48814895
48824896 /* prepare auth data structure */
48834897
@@ -4912,6 +4926,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 28 unmodified lines
49124926 return -EOPNOTSUPP;
49134927 }
49144928
4929+ if (ifmgd->assoc_data)
4930+ return -EBUSY;
4931+
49154932 auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
49164933 req->ie_len, GFP_KERNEL);
49174934 if (!auth_data)
@@ -4931,6 +4948,13 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 13 unmodified lines
49314948 auth_data->data_len += req->auth_data_len - 4;
49324949 }
49334950
4951+ /* Check if continuing authentication or trying to authenticate with the
4952+ * same BSS that we were in the process of authenticating with and avoid
4953+ * removal and re-addition of the STA entry in
4954+ * ieee80211_prep_connection().
4955+ */
4956+ cont_auth = ifmgd->auth_data && req->bss == ifmgd->auth_data->bss;
4957+
49344958 if (req->ie && req->ie_len) {
49354959 memcpy(&auth_data->data[auth_data->data_len],
49364960 req->ie, req->ie_len);
@@ -4947,18 +4971,26 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 10 unmodified lines
49474971
49484972 /* try to authenticate/probe */
49494973
4950− if ((ifmgd->auth_data && !ifmgd->auth_data->done) ||
4951− ifmgd->assoc_data) {
4952− err = -EBUSY;
4953− goto err_free;
4974+ if (ifmgd->auth_data) {
4975+ if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE) {
4976+ auth_data->peer_confirmed =
4977+ ifmgd->auth_data->peer_confirmed;
4978+ }
4979+ ieee80211_destroy_auth_data(sdata, cont_auth);
49544980 }
49554981
4956− if (ifmgd->auth_data)
4957− ieee80211_destroy_auth_data(sdata, false);
4958−
49594982 /* prep auth_data so we don't go into idle on disassoc */
49604983 ifmgd->auth_data = auth_data;
49614984
4985+ /* If this is continuation of an ongoing SAE authentication exchange
4986+ * (i.e., request to send SAE Confirm) and the peer has already
4987+ * confirmed, mark authentication completed since we are about to send
4988+ * out SAE Confirm.
4989+ */
4990+ if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE &&
4991+ auth_data->peer_confirmed && auth_data->sae_trans == 2)
4992+ ieee80211_mark_sta_auth(sdata, req->bss->bssid);
4993+
49624994 if (ifmgd->associated) {
49634995 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
49644996
@@ -4976,7 +5008,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 11 unmodified lines
49765008
49775009 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
49785010
4979− err = ieee80211_prep_connection(sdata, req->bss, false, false);
5011+ err = ieee80211_prep_connection(sdata, req->bss, cont_auth, false);
49805012 if (err)
49815013 goto err_clear;
49825014
@@ -4997,7 +5029,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 14 unmodified lines
49975029 mutex_lock(&sdata->local->mtx);
49985030 ieee80211_vif_release_channel(sdata);
49995031 mutex_unlock(&sdata->local->mtx);
5000− err_free:
50015032 kfree(auth_data);
50025033 return err;
50035034 }
net/mac80211/rate.h+0−13
@@ -95,18 +95,5 @@ static inline void rc80211_minstrel_exit(void) · 94 unmodified lines
9595 }
9696 #endif
9797
98−#ifdef CONFIG_MAC80211_RC_MINSTREL_HT
99−int rc80211_minstrel_ht_init(void);
100−void rc80211_minstrel_ht_exit(void);
101−#else
102−static inline int rc80211_minstrel_ht_init(void)
103−{
104− return 0;
105−}
106−static inline void rc80211_minstrel_ht_exit(void)
107−{
108−}
109−#endif
110−
11198
11299 #endif /* IEEE80211_RATE_H */
net/mac80211/rc80211_minstrel.c+0−162
@@ -167,12 +167,6 @@ minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) · 166 unmodified lines
167167 if (unlikely(!mrs->att_hist)) {
168168 mrs->prob_ewma = cur_prob;
169169 } else {
170− /* update exponential weighted moving variance */
171− mrs->prob_ewmv = minstrel_ewmv(mrs->prob_ewmv,
172− cur_prob,
173− mrs->prob_ewma,
174− EWMA_LEVEL);
175−
176170 /*update exponential weighted moving avarage */
177171 mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
178172 cur_prob,
@@ -572,141 +566,6 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, · 393 unmodified lines
572566 minstrel_update_rates(mp, mi);
573567 }
574568
575−static void *
576−minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
577−{
578− struct ieee80211_supported_band *sband;
579− struct minstrel_sta_info *mi;
580− struct minstrel_priv *mp = priv;
581− struct ieee80211_hw *hw = mp->hw;
582− int max_rates = 0;
583− int i;
584−
585− mi = kzalloc(sizeof(struct minstrel_sta_info), gfp);
586− if (!mi)
587− return NULL;
588−
589− for (i = 0; i < NUM_NL80211_BANDS; i++) {
590− sband = hw->wiphy->bands[i];
591− if (sband && sband->n_bitrates > max_rates)
592− max_rates = sband->n_bitrates;
593− }
594−
595− mi->r = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp);
596− if (!mi->r)
597− goto error;
598−
599− mi->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp);
600− if (!mi->sample_table)
601− goto error1;
602−
603− mi->last_stats_update = jiffies;
604− return mi;
605−
606−error1:
607− kfree(mi->r);
608−error:
609− kfree(mi);
610− return NULL;
611−}
612−
613−static void
614−minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta)
615−{
616− struct minstrel_sta_info *mi = priv_sta;
617−
618− kfree(mi->sample_table);
619− kfree(mi->r);
620− kfree(mi);
621−}
622−
623−static void
624−minstrel_init_cck_rates(struct minstrel_priv *mp)
625−{
626− static const int bitrates[4] = { 10, 20, 55, 110 };
627− struct ieee80211_supported_band *sband;
628− u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
629− int i, j;
630−
631− sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ];
632− if (!sband)
633− return;
634−
635− for (i = 0, j = 0; i < sband->n_bitrates; i++) {
636− struct ieee80211_rate *rate = &sband->bitrates[i];
637−
638− if (rate->flags & IEEE80211_RATE_ERP_G)
639− continue;
640−
641− if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
642− continue;
643−
644− for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
645− if (rate->bitrate != bitrates[j])
646− continue;
647−
648− mp->cck_rates[j] = i;
649− break;
650− }
651− }
652−}
653−
654−static void *
655−minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
656−{
657− struct minstrel_priv *mp;
658−
659− mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
660− if (!mp)
661− return NULL;
662−
663− /* contention window settings
664− * Just an approximation. Using the per-queue values would complicate
665− * the calculations and is probably unnecessary */
666− mp->cw_min = 15;
667− mp->cw_max = 1023;
668−
669− /* number of packets (in %) to use for sampling other rates
670− * sample less often for non-mrr packets, because the overhead
671− * is much higher than with mrr */
672− mp->lookaround_rate = 5;
673− mp->lookaround_rate_mrr = 10;
674−
675− /* maximum time that the hw is allowed to stay in one MRR segment */
676− mp->segment_size = 6000;
677−
678− if (hw->max_rate_tries > 0)
679− mp->max_retry = hw->max_rate_tries;
680− else
681− /* safe default, does not necessarily have to match hw properties */
682− mp->max_retry = 7;
683−
684− if (hw->max_rates >= 4)
685− mp->has_mrr = true;
686−
687− mp->hw = hw;
688− mp->update_interval = 100;
689−
690−#ifdef CONFIG_MAC80211_DEBUGFS
691− mp->fixed_rate_idx = (u32) -1;
692− mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx",
693− 0666, debugfsdir, &mp->fixed_rate_idx);
694−#endif
695−
696− minstrel_init_cck_rates(mp);
697−
698− return mp;
699−}
700−
701−static void
702−minstrel_free(void *priv)
703−{
704−#ifdef CONFIG_MAC80211_DEBUGFS
705− debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate);
706−#endif
707− kfree(priv);
708−}
709−
710569 static u32 minstrel_get_expected_throughput(void *priv_sta)
711570 {
712571 struct minstrel_sta_info *mi = priv_sta;
@@ -725,29 +584,8 @@ static u32 minstrel_get_expected_throughput(void *priv_sta) · 12 unmodified lines
725584 }
726585
727586 const struct rate_control_ops mac80211_minstrel = {
728− .name = "minstrel",
729587 .tx_status_ext = minstrel_tx_status,
730588 .get_rate = minstrel_get_rate,
731589 .rate_init = minstrel_rate_init,
732− .alloc = minstrel_alloc,
733− .free = minstrel_free,
734− .alloc_sta = minstrel_alloc_sta,
735− .free_sta = minstrel_free_sta,
736−#ifdef CONFIG_MAC80211_DEBUGFS
737− .add_sta_debugfs = minstrel_add_sta_debugfs,
738− .remove_sta_debugfs = minstrel_remove_sta_debugfs,
739−#endif
740590 .get_expected_throughput = minstrel_get_expected_throughput,
741591 };
742−
743−int __init
744−rc80211_minstrel_init(void)
745−{
746− return ieee80211_rate_control_register(&mac80211_minstrel);
747−}
748−
749−void
750−rc80211_minstrel_exit(void)
751−{
752− ieee80211_rate_control_unregister(&mac80211_minstrel);
753−}
net/mac80211/rc80211_minstrel.h+1−34
@@ -35,19 +35,6 @@ minstrel_ewma(int old, int new, int weight) · 34 unmodified lines
3535 return old + incr;
3636 }
3737
38−/*
39− * Perform EWMV (Exponentially Weighted Moving Variance) calculation
40− */
41−static inline int
42−minstrel_ewmv(int old_ewmv, int cur_prob, int prob_ewma, int weight)
43−{
44− int diff, incr;
45−
46− diff = cur_prob - prob_ewma;
47− incr = (EWMA_DIV - weight) * diff / EWMA_DIV;
48− return weight * (old_ewmv + MINSTREL_TRUNC(diff * incr)) / EWMA_DIV;
49−}
50−
5138 struct minstrel_rate_stats {
5239 /* current / last sampling period attempts/success counters */
5340 u16 attempts, last_attempts;
@@ -56,11 +43,8 @@ struct minstrel_rate_stats { · 2 unmodified lines
5643 /* total attempts/success counters */
5744 u32 att_hist, succ_hist;
5845
59− /* statistis of packet delivery probability
60− * prob_ewma - exponential weighted moving average of prob
61− * prob_ewmsd - exp. weighted moving standard deviation of prob */
46+ /* prob_ewma - exponential weighted moving average of prob */
6247 u16 prob_ewma;
63− u16 prob_ewmv;
6448
6549 /* maximum retry counts */
6650 u8 retry_count;
@@ -109,11 +93,6 @@ struct minstrel_sta_info { · 42 unmodified lines
10993
11094 /* sampling table */
11195 u8 *sample_table;
112−
113−#ifdef CONFIG_MAC80211_DEBUGFS
114− struct dentry *dbg_stats;
115− struct dentry *dbg_stats_csv;
116−#endif
11796 };
11897
11998 struct minstrel_priv {
@@ -137,7 +116,6 @@ struct minstrel_priv { · 17 unmodified lines
137116 * - setting will be applied on next update
138117 */
139118 u32 fixed_rate_idx;
140− struct dentry *dbg_fixed_rate;
141119 #endif
142120 };
143121
@@ -146,17 +124,8 @@ struct minstrel_debugfs_info { · 2 unmodified lines
146124 char buf[];
147125 };
148126
149−/* Get EWMSD (Exponentially Weighted Moving Standard Deviation) * 10 */
150−static inline int
151−minstrel_get_ewmsd10(struct minstrel_rate_stats *mrs)
152−{
153− unsigned int ewmv = mrs->prob_ewmv;
154− return int_sqrt(MINSTREL_TRUNC(ewmv * 1000 * 1000));
155−}
156−
157127 extern const struct rate_control_ops mac80211_minstrel;
158128 void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
159−void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
160129
161130 /* Recalculate success probabilities and counters for a given rate using EWMA */
162131 void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
@@ -165,7 +134,5 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma); · 2 unmodified lines
165134 /* debugfs */
166135 int minstrel_stats_open(struct inode *inode, struct file *file);
167136 int minstrel_stats_csv_open(struct inode *inode, struct file *file);
168−ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos);
169−int minstrel_stats_release(struct inode *inode, struct file *file);
170137
171138 #endif
net/mac80211/rc80211_minstrel_debugfs.c+4−64
@@ -54,22 +54,6 @@ · 53 unmodified lines
5454 #include <net/mac80211.h>
5555 #include "rc80211_minstrel.h"
5656
57−ssize_t
58−minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
59−{
60− struct minstrel_debugfs_info *ms;
61−
62− ms = file->private_data;
63− return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
64−}
65−
66−int
67−minstrel_stats_release(struct inode *inode, struct file *file)
68−{
69− kfree(file->private_data);
70− return 0;
71−}
72−
7357 int
7458 minstrel_stats_open(struct inode *inode, struct file *file)
7559 {
@@ -86,14 +70,13 @@ minstrel_stats_open(struct inode *inode, struct file *file) · 10 unmodified lines
8670 p = ms->buf;
8771 p += sprintf(p, "\n");
8872 p += sprintf(p,
89− "best __________rate_________ ________statistics________ ____last_____ ______sum-of________\n");
73+ "best __________rate_________ ____statistics___ ____last_____ ______sum-of________\n");
9074 p += sprintf(p,
91− "rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [retry|suc|att] [#success | #attempts]\n");
75+ "rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]\n");
9276
9377 for (i = 0; i < mi->n_rates; i++) {
9478 struct minstrel_rate *mr = &mi->r[i];
9579 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
96− unsigned int prob_ewmsd;
9780
9881 *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' ';
9982 *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' ';
@@ -109,15 +92,13 @@ minstrel_stats_open(struct inode *inode, struct file *file) · 9 unmodified lines
10992 tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
11093 tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
11194 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
112− prob_ewmsd = minstrel_get_ewmsd10(mrs);
11395
114− p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
96+ p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u"
11597 " %3u %3u %-3u "
11698 "%9llu %-9llu\n",
11799 tp_max / 10, tp_max % 10,
118100 tp_avg / 10, tp_avg % 10,
119101 eprob / 10, eprob % 10,
120− prob_ewmsd / 10, prob_ewmsd % 10,
121102 mrs->retry_count,
122103 mrs->last_success,
123104 mrs->last_attempts,
@@ -135,14 +116,6 @@ minstrel_stats_open(struct inode *inode, struct file *file) · 11 unmodified lines
135116 return 0;
136117 }
137118
138−static const struct file_operations minstrel_stat_fops = {
139− .owner = THIS_MODULE,
140− .open = minstrel_stats_open,
141− .read = minstrel_stats_read,
142− .release = minstrel_stats_release,
143− .llseek = default_llseek,
144−};
145−
146119 int
147120 minstrel_stats_csv_open(struct inode *inode, struct file *file)
148121 {
@@ -161,7 +134,6 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) · 12 unmodified lines
161134 for (i = 0; i < mi->n_rates; i++) {
162135 struct minstrel_rate *mr = &mi->r[i];
163136 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
164− unsigned int prob_ewmsd;
165137
166138 p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : ""));
167139 p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : ""));
@@ -177,14 +149,12 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) · 9 unmodified lines
177149 tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
178150 tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
179151 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
180− prob_ewmsd = minstrel_get_ewmsd10(mrs);
181152
182− p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
153+ p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,"
183154 "%llu,%llu,%d,%d\n",
184155 tp_max / 10, tp_max % 10,
185156 tp_avg / 10, tp_avg % 10,
186157 eprob / 10, eprob % 10,
187− prob_ewmsd / 10, prob_ewmsd % 10,
188158 mrs->retry_count,
189159 mrs->last_success,
190160 mrs->last_attempts,
@@ -200,33 +170,3 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) · 9 unmodified lines
200170
201171 return 0;
202172 }
203−
204−static const struct file_operations minstrel_stat_csv_fops = {
205− .owner = THIS_MODULE,
206− .open = minstrel_stats_csv_open,
207− .read = minstrel_stats_read,
208− .release = minstrel_stats_release,
209− .llseek = default_llseek,
210−};
211−
212−void
213−minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
214−{
215− struct minstrel_sta_info *mi = priv_sta;
216−
217− mi->dbg_stats = debugfs_create_file("rc_stats", 0444, dir, mi,
218− &minstrel_stat_fops);
219−
220− mi->dbg_stats_csv = debugfs_create_file("rc_stats_csv", 0444, dir, mi,
221− &minstrel_stat_csv_fops);
222−}
223−
224−void
225−minstrel_remove_sta_debugfs(void *priv, void *priv_sta)
226−{
227− struct minstrel_sta_info *mi = priv_sta;
228−
229− debugfs_remove(mi->dbg_stats);
230−
231− debugfs_remove(mi->dbg_stats_csv);
232−}
net/mac80211/rc80211_minstrel_ht.c+191−107
@@ -52,22 +52,23 @@ · 51 unmodified lines
5252 _streams - 1
5353
5454 /* MCS rate information for an MCS group */
55−#define MCS_GROUP(_streams, _sgi, _ht40) \
55+#define MCS_GROUP(_streams, _sgi, _ht40, _s) \
5656 [GROUP_IDX(_streams, _sgi, _ht40)] = { \
5757 .streams = _streams, \
58+ .shift = _s, \
5859 .flags = \
5960 IEEE80211_TX_RC_MCS | \
6061 (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
6162 (_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
6263 .duration = { \
63− MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26), \
64− MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52), \
65− MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78), \
66− MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104), \
67− MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156), \
68− MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208), \
69− MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234), \
70− MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) \
64+ MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s, \
65+ MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s, \
66+ MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s, \
67+ MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s, \
68+ MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s, \
69+ MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s, \
70+ MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s, \
71+ MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s \
7172 } \
7273 }
7374
@@ -80,9 +81,10 @@ · 6 unmodified lines
8081 #define BW2VBPS(_bw, r3, r2, r1) \
8182 (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
8283
83−#define VHT_GROUP(_streams, _sgi, _bw) \
84+#define VHT_GROUP(_streams, _sgi, _bw, _s) \
8485 [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \
8586 .streams = _streams, \
87+ .shift = _s, \
8688 .flags = \
8789 IEEE80211_TX_RC_VHT_MCS | \
8890 (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
@@ -90,25 +92,25 @@ · 1 unmodified line
9092 _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
9193 .duration = { \
9294 MCS_DURATION(_streams, _sgi, \
93− BW2VBPS(_bw, 117, 54, 26)), \
95+ BW2VBPS(_bw, 117, 54, 26)) >> _s, \
9496 MCS_DURATION(_streams, _sgi, \
95− BW2VBPS(_bw, 234, 108, 52)), \
97+ BW2VBPS(_bw, 234, 108, 52)) >> _s, \
9698 MCS_DURATION(_streams, _sgi, \
97− BW2VBPS(_bw, 351, 162, 78)), \
99+ BW2VBPS(_bw, 351, 162, 78)) >> _s, \
98100 MCS_DURATION(_streams, _sgi, \
99− BW2VBPS(_bw, 468, 216, 104)), \
101+ BW2VBPS(_bw, 468, 216, 104)) >> _s, \
100102 MCS_DURATION(_streams, _sgi, \
101− BW2VBPS(_bw, 702, 324, 156)), \
103+ BW2VBPS(_bw, 702, 324, 156)) >> _s, \
102104 MCS_DURATION(_streams, _sgi, \
103− BW2VBPS(_bw, 936, 432, 208)), \
105+ BW2VBPS(_bw, 936, 432, 208)) >> _s, \
104106 MCS_DURATION(_streams, _sgi, \
105− BW2VBPS(_bw, 1053, 486, 234)), \
107+ BW2VBPS(_bw, 1053, 486, 234)) >> _s, \
106108 MCS_DURATION(_streams, _sgi, \
107− BW2VBPS(_bw, 1170, 540, 260)), \
109+ BW2VBPS(_bw, 1170, 540, 260)) >> _s, \
108110 MCS_DURATION(_streams, _sgi, \
109− BW2VBPS(_bw, 1404, 648, 312)), \
111+ BW2VBPS(_bw, 1404, 648, 312)) >> _s, \
110112 MCS_DURATION(_streams, _sgi, \
111− BW2VBPS(_bw, 1560, 720, 346)) \
113+ BW2VBPS(_bw, 1560, 720, 346)) >> _s \
112114 } \
113115 }
114116
@@ -121,28 +123,27 @@ · 6 unmodified lines
121123 (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \
122124 CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE))
123125
124−#define CCK_DURATION_LIST(_short) \
125− CCK_ACK_DURATION(10, _short), \
126− CCK_ACK_DURATION(20, _short), \
127− CCK_ACK_DURATION(55, _short), \
128− CCK_ACK_DURATION(110, _short)
126+#define CCK_DURATION_LIST(_short, _s) \
127+ CCK_ACK_DURATION(10, _short) >> _s, \
128+ CCK_ACK_DURATION(20, _short) >> _s, \
129+ CCK_ACK_DURATION(55, _short) >> _s, \
130+ CCK_ACK_DURATION(110, _short) >> _s
129131
130−#define CCK_GROUP \
132+#define CCK_GROUP(_s) \
131133 [MINSTREL_CCK_GROUP] = { \
132− .streams = 0, \
134+ .streams = 1, \
133135 .flags = 0, \
136+ .shift = _s, \
134137 .duration = { \
135− CCK_DURATION_LIST(false), \
136− CCK_DURATION_LIST(true) \
138+ CCK_DURATION_LIST(false, _s), \
139+ CCK_DURATION_LIST(true, _s) \
137140 } \
138141 }
139142
140−#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
141143 static bool minstrel_vht_only = true;
142144 module_param(minstrel_vht_only, bool, 0644);
143145 MODULE_PARM_DESC(minstrel_vht_only,
144146 "Use only VHT rates when VHT is supported by sta.");
145−#endif
146147
147148 /*
148149 * To enable sufficiently targeted rate sampling, MCS rates are divided into
@@ -153,49 +154,47 @@ MODULE_PARM_DESC(minstrel_vht_only, · 4 unmodified lines
153154 * BW -> SGI -> #streams
154155 */
155156 const struct mcs_group minstrel_mcs_groups[] = {
156− MCS_GROUP(1, 0, BW_20),
157− MCS_GROUP(2, 0, BW_20),
158− MCS_GROUP(3, 0, BW_20),
157+ MCS_GROUP(1, 0, BW_20, 5),
158+ MCS_GROUP(2, 0, BW_20, 4),
159+ MCS_GROUP(3, 0, BW_20, 4),
159160
160− MCS_GROUP(1, 1, BW_20),
161− MCS_GROUP(2, 1, BW_20),
162− MCS_GROUP(3, 1, BW_20),
161+ MCS_GROUP(1, 1, BW_20, 5),
162+ MCS_GROUP(2, 1, BW_20, 4),
163+ MCS_GROUP(3, 1, BW_20, 4),
163164
164− MCS_GROUP(1, 0, BW_40),
165− MCS_GROUP(2, 0, BW_40),
166− MCS_GROUP(3, 0, BW_40),
165+ MCS_GROUP(1, 0, BW_40, 4),
166+ MCS_GROUP(2, 0, BW_40, 4),
167+ MCS_GROUP(3, 0, BW_40, 4),
167168
168− MCS_GROUP(1, 1, BW_40),
169− MCS_GROUP(2, 1, BW_40),
170− MCS_GROUP(3, 1, BW_40),
169+ MCS_GROUP(1, 1, BW_40, 4),
170+ MCS_GROUP(2, 1, BW_40, 4),
171+ MCS_GROUP(3, 1, BW_40, 4),
171172
172− CCK_GROUP,
173+ CCK_GROUP(8),
173174
174−#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
175− VHT_GROUP(1, 0, BW_20),
176− VHT_GROUP(2, 0, BW_20),
177− VHT_GROUP(3, 0, BW_20),
175+ VHT_GROUP(1, 0, BW_20, 5),
176+ VHT_GROUP(2, 0, BW_20, 4),
177+ VHT_GROUP(3, 0, BW_20, 4),
178178
179− VHT_GROUP(1, 1, BW_20),
180− VHT_GROUP(2, 1, BW_20),
181− VHT_GROUP(3, 1, BW_20),
179+ VHT_GROUP(1, 1, BW_20, 5),
180+ VHT_GROUP(2, 1, BW_20, 4),
181+ VHT_GROUP(3, 1, BW_20, 4),
182182
183− VHT_GROUP(1, 0, BW_40),
184− VHT_GROUP(2, 0, BW_40),
185− VHT_GROUP(3, 0, BW_40),
183+ VHT_GROUP(1, 0, BW_40, 4),
184+ VHT_GROUP(2, 0, BW_40, 4),
185+ VHT_GROUP(3, 0, BW_40, 4),
186186
187− VHT_GROUP(1, 1, BW_40),
188− VHT_GROUP(2, 1, BW_40),
189− VHT_GROUP(3, 1, BW_40),
187+ VHT_GROUP(1, 1, BW_40, 4),
188+ VHT_GROUP(2, 1, BW_40, 4),
189+ VHT_GROUP(3, 1, BW_40, 4),
190190
191− VHT_GROUP(1, 0, BW_80),
192− VHT_GROUP(2, 0, BW_80),
193− VHT_GROUP(3, 0, BW_80),
191+ VHT_GROUP(1, 0, BW_80, 4),
192+ VHT_GROUP(2, 0, BW_80, 4),
193+ VHT_GROUP(3, 0, BW_80, 4),
194194
195− VHT_GROUP(1, 1, BW_80),
196− VHT_GROUP(2, 1, BW_80),
197− VHT_GROUP(3, 1, BW_80),
198−#endif
195+ VHT_GROUP(1, 1, BW_80, 4),
196+ VHT_GROUP(2, 1, BW_80, 4),
197+ VHT_GROUP(3, 1, BW_80, 4),
199198 };
200199
201200 static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
@@ -282,7 +281,8 @@ minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, · 80 unmodified lines
282281 break;
283282
284283 /* short preamble */
285− if (!(mi->supported[group] & BIT(idx)))
284+ if ((mi->supported[group] & BIT(idx + 4)) &&
285+ (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
286286 idx += 4;
287287 }
288288 return &mi->groups[group].rates[idx];
@@ -311,7 +311,8 @@ minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, · 22 unmodified lines
311311 if (group != MINSTREL_CCK_GROUP)
312312 nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
313313
314− nsecs += minstrel_mcs_groups[group].duration[rate];
314+ nsecs += minstrel_mcs_groups[group].duration[rate] <<
315+ minstrel_mcs_groups[group].shift;
315316
316317 /*
317318 * For the throughput calculation, limit the probability value to 90% to
@@ -759,12 +760,19 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, · 441 unmodified lines
759760 minstrel_ht_update_rates(mp, mi);
760761 }
761762
763+static inline int
764+minstrel_get_duration(int index)
765+{
766+ const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
767+ unsigned int duration = group->duration[index % MCS_GROUP_RATES];
768+ return duration << group->shift;
769+}
770+
762771 static void
763772 minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
764773 int index)
765774 {
766775 struct minstrel_rate_stats *mrs;
767− const struct mcs_group *group;
768776 unsigned int tx_time, tx_time_rtscts, tx_time_data;
769777 unsigned int cw = mp->cw_min;
770778 unsigned int ctime = 0;
@@ -783,8 +791,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, · 12 unmodified lines
783791 mrs->retry_count_rtscts = 2;
784792 mrs->retry_updated = true;
785793
786− group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
787− tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;
794+ tx_time_data = minstrel_get_duration(index) * ampdu_len / 1000;
788795
789796 /* Contention time for first 2 tries */
790797 ctime = (t_slot * cw) >> 1;
@@ -878,20 +885,24 @@ minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi) · 87 unmodified lines
878885 int group = mi->max_prob_rate / MCS_GROUP_RATES;
879886 const struct mcs_group *g = &minstrel_mcs_groups[group];
880887 int rate = mi->max_prob_rate % MCS_GROUP_RATES;
888+ unsigned int duration;
881889
882890 /* Disable A-MSDU if max_prob_rate is bad */
883891 if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))
884892 return 1;
885893
894+ duration = g->duration[rate];
895+ duration <<= g->shift;
896+
886897 /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */
887− if (g->duration[rate] > MCS_DURATION(1, 0, 52))
898+ if (duration > MCS_DURATION(1, 0, 52))
888899 return 500;
889900
890901 /*
891902 * If the rate is slower than single-stream MCS4, limit A-MSDU to usual
892903 * data packet size
893904 */
894− if (g->duration[rate] > MCS_DURATION(1, 0, 104))
905+ if (duration > MCS_DURATION(1, 0, 104))
895906 return 1600;
896907
897908 /*
@@ -899,7 +910,7 @@ minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi) · 1 unmodified line
899910 * rate success probability is less than 75%, limit A-MSDU to twice the usual
900911 * data packet size
901912 */
902− if (g->duration[rate] > MCS_DURATION(1, 0, 260) ||
913+ if (duration > MCS_DURATION(1, 0, 260) ||
903914 (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <
904915 MINSTREL_FRAC(75, 100)))
905916 return 3200;
@@ -946,13 +957,6 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) · 40 unmodified lines
946957 rate_control_set_rates(mp->hw, mi->sta, rates);
947958 }
948959
949−static inline int
950−minstrel_get_duration(int index)
951−{
952− const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
953− return group->duration[index % MCS_GROUP_RATES];
954−}
955−
956960 static int
957961 minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
958962 {
@@ -1000,10 +1004,13 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) · 41 unmodified lines
10001004 return -1;
10011005
10021006 /*
1003− * Do not sample if the probability is already higher than 95%
1004− * to avoid wasting airtime.
1007+ * Do not sample if the probability is already higher than 95%,
1008+ * or if the rate is 3 times slower than the current max probability
1009+ * rate, to avoid wasting airtime.
10051010 */
1006− if (mrs->prob_ewma > MINSTREL_FRAC(95, 100))
1011+ sample_dur = minstrel_get_duration(sample_idx);
1012+ if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
1013+ minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur)
10071014 return -1;
10081015
10091016 /*
@@ -1013,7 +1020,6 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) · 3 unmodified lines
10131020
10141021 cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 /
10151022 MCS_GROUP_RATES].streams;
1016− sample_dur = minstrel_get_duration(sample_idx);
10171023 if (sample_dur >= minstrel_get_duration(tp_rate2) &&
10181024 (cur_max_tp_streams - 1 <
10191025 minstrel_mcs_groups[sample_group].streams ||
@@ -1077,18 +1083,23 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, · 57 unmodified lines
10771083 return;
10781084
10791085 sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
1086+ sample_idx %= MCS_GROUP_RATES;
1087+
1088+ if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP] &&
1089+ (sample_idx >= 4) != txrc->short_preamble)
1090+ return;
1091+
10801092 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
10811093 rate->count = 1;
10821094
1083− if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
1095+ if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP]) {
10841096 int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
10851097 rate->idx = mp->cck_rates[idx];
10861098 } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) {
10871099 ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES,
10881100 sample_group->streams);
10891101 } else {
1090− rate->idx = sample_idx % MCS_GROUP_RATES +
1091− (sample_group->streams - 1) * 8;
1102+ rate->idx = sample_idx + (sample_group->streams - 1) * 8;
10921103 }
10931104
10941105 rate->flags = sample_group->flags;
@@ -1130,14 +1141,14 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 35 unmodified lines
11301141 struct minstrel_ht_sta_priv *msp = priv_sta;
11311142 struct minstrel_ht_sta *mi = &msp->ht;
11321143 struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
1133− u16 sta_cap = sta->ht_cap.cap;
1144+ u16 ht_cap = sta->ht_cap.cap;
11341145 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
1135− struct sta_info *sinfo = container_of(sta, struct sta_info, sta);
11361146 int use_vht;
11371147 int n_supported = 0;
11381148 int ack_dur;
11391149 int stbc;
11401150 int i;
1151+ bool ldpc;
11411152
11421153 /* fall back to the old minstrel for legacy stations */
11431154 if (!sta->ht_cap.ht_supported)
@@ -1145,12 +1156,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 1 unmodified line
11451156
11461157 BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB);
11471158
1148−#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
11491159 if (vht_cap->vht_supported)
11501160 use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0);
11511161 else
1152−#endif
1153− use_vht = 0;
1162+ use_vht = 0;
11541163
11551164 msp->is_ht = true;
11561165 memset(mi, 0, sizeof(*mi));
@@ -1175,16 +1184,22 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 18 unmodified lines
11751184 }
11761185 mi->sample_tries = 4;
11771186
1178− /* TODO tx_flags for vht - ATM the RC API is not fine-grained enough */
11791187 if (!use_vht) {
1180− stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>
1188+ stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >>
11811189 IEEE80211_HT_CAP_RX_STBC_SHIFT;
1182− mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
11831190
1184− if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)
1185− mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
1191+ ldpc = ht_cap & IEEE80211_HT_CAP_LDPC_CODING;
1192+ } else {
1193+ stbc = (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) >>
1194+ IEEE80211_VHT_CAP_RXSTBC_SHIFT;
1195+
1196+ ldpc = vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC;
11861197 }
11871198
1199+ mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
1200+ if (ldpc)
1201+ mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
1202+
11881203 for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
11891204 u32 gflags = minstrel_mcs_groups[i].flags;
11901205 int bw, nss;
@@ -1197,10 +1212,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 6 unmodified lines
11971212
11981213 if (gflags & IEEE80211_TX_RC_SHORT_GI) {
11991214 if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
1200− if (!(sta_cap & IEEE80211_HT_CAP_SGI_40))
1215+ if (!(ht_cap & IEEE80211_HT_CAP_SGI_40))
12011216 continue;
12021217 } else {
1203− if (!(sta_cap & IEEE80211_HT_CAP_SGI_20))
1218+ if (!(ht_cap & IEEE80211_HT_CAP_SGI_20))
12041219 continue;
12051220 }
12061221 }
@@ -1217,10 +1232,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 10 unmodified lines
12171232
12181233 /* HT rate */
12191234 if (gflags & IEEE80211_TX_RC_MCS) {
1220−#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
12211235 if (use_vht && minstrel_vht_only)
12221236 continue;
1223−#endif
1237+
12241238 mi->supported[i] = mcs->rx_mask[nss - 1];
12251239 if (mi->supported[i])
12261240 n_supported++;
@@ -1258,8 +1272,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 31 unmodified lines
12581272 if (!n_supported)
12591273 goto use_legacy;
12601274
1261− if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE))
1262− mi->cck_supported_short |= mi->cck_supported_short << 4;
1275+ mi->supported[MINSTREL_CCK_GROUP] |= mi->cck_supported_short << 4;
12631276
12641277 /* create an initial rate table with the lowest supported rates */
12651278 minstrel_ht_update_stats(mp, mi);
@@ -1340,16 +1353,88 @@ minstrel_ht_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) · 74 unmodified lines
13401353 kfree(msp);
13411354 }
13421355
1356+static void
1357+minstrel_ht_init_cck_rates(struct minstrel_priv *mp)
1358+{
1359+ static const int bitrates[4] = { 10, 20, 55, 110 };
1360+ struct ieee80211_supported_band *sband;
1361+ u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
1362+ int i, j;
1363+
1364+ sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ];
1365+ if (!sband)
1366+ return;
1367+
1368+ for (i = 0; i < sband->n_bitrates; i++) {
1369+ struct ieee80211_rate *rate = &sband->bitrates[i];
1370+
1371+ if (rate->flags & IEEE80211_RATE_ERP_G)
1372+ continue;
1373+
1374+ if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
1375+ continue;
1376+
1377+ for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
1378+ if (rate->bitrate != bitrates[j])
1379+ continue;
1380+
1381+ mp->cck_rates[j] = i;
1382+ break;
1383+ }
1384+ }
1385+}
1386+
13431387 static void *
13441388 minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
13451389 {
1346− return mac80211_minstrel.alloc(hw, debugfsdir);
1390+ struct minstrel_priv *mp;
1391+
1392+ mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
1393+ if (!mp)
1394+ return NULL;
1395+
1396+ /* contention window settings
1397+ * Just an approximation. Using the per-queue values would complicate
1398+ * the calculations and is probably unnecessary */
1399+ mp->cw_min = 15;
1400+ mp->cw_max = 1023;
1401+
1402+ /* number of packets (in %) to use for sampling other rates
1403+ * sample less often for non-mrr packets, because the overhead
1404+ * is much higher than with mrr */
1405+ mp->lookaround_rate = 5;
1406+ mp->lookaround_rate_mrr = 10;
1407+
1408+ /* maximum time that the hw is allowed to stay in one MRR segment */
1409+ mp->segment_size = 6000;
1410+
1411+ if (hw->max_rate_tries > 0)
1412+ mp->max_retry = hw->max_rate_tries;
1413+ else
1414+ /* safe default, does not necessarily have to match hw properties */
1415+ mp->max_retry = 7;
1416+
1417+ if (hw->max_rates >= 4)
1418+ mp->has_mrr = true;
1419+
1420+ mp->hw = hw;
1421+ mp->update_interval = 100;
1422+
1423+#ifdef CONFIG_MAC80211_DEBUGFS
1424+ mp->fixed_rate_idx = (u32) -1;
1425+ debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
1426+ &mp->fixed_rate_idx);
1427+#endif
1428+
1429+ minstrel_ht_init_cck_rates(mp);
1430+
1431+ return mp;
13471432 }
13481433
13491434 static void
13501435 minstrel_ht_free(void *priv)
13511436 {
1352− mac80211_minstrel.free(priv);
1437+ kfree(priv);
13531438 }
13541439
13551440 static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
@@ -1384,7 +1469,6 @@ static const struct rate_control_ops mac80211_minstrel_ht = { · 28 unmodified lines
13841469 .free = minstrel_ht_free,
13851470 #ifdef CONFIG_MAC80211_DEBUGFS
13861471 .add_sta_debugfs = minstrel_ht_add_sta_debugfs,
1387− .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
13881472 #endif
13891473 .get_expected_throughput = minstrel_ht_get_expected_throughput,
13901474 };
@@ -1409,14 +1493,14 @@ static void __init init_sample_table(void) · 18 unmodified lines
14091493 }
14101494
14111495 int __init
1412−rc80211_minstrel_ht_init(void)
1496+rc80211_minstrel_init(void)
14131497 {
14141498 init_sample_table();
14151499 return ieee80211_rate_control_register(&mac80211_minstrel_ht);
14161500 }
14171501
14181502 void
1419−rc80211_minstrel_ht_exit(void)
1503+rc80211_minstrel_exit(void)
14201504 {
14211505 ieee80211_rate_control_unregister(&mac80211_minstrel_ht);
14221506 }
net/mac80211/rc80211_minstrel_ht.h+4−16
@@ -15,11 +15,7 @@ · 14 unmodified lines
1515 */
1616 #define MINSTREL_MAX_STREAMS 3
1717 #define MINSTREL_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */
18−#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
1918 #define MINSTREL_VHT_STREAM_GROUPS 6 /* BW(=3) * SGI(=2) */
20−#else
21−#define MINSTREL_VHT_STREAM_GROUPS 0
22−#endif
2319
2420 #define MINSTREL_HT_GROUPS_NB (MINSTREL_MAX_STREAMS * \
2521 MINSTREL_HT_STREAM_GROUPS)
@@ -34,16 +30,13 @@ · 8 unmodified lines
3430 #define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB)
3531 #define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1)
3632
37−#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
3833 #define MCS_GROUP_RATES 10
39−#else
40−#define MCS_GROUP_RATES 8
41−#endif
4234
4335 struct mcs_group {
44− u32 flags;
45− unsigned int streams;
46− unsigned int duration[MCS_GROUP_RATES];
36+ u16 flags;
37+ u8 streams;
38+ u8 shift;
39+ u16 duration[MCS_GROUP_RATES];
4740 };
4841
4942 extern const struct mcs_group minstrel_mcs_groups[];
@@ -110,17 +103,12 @@ struct minstrel_ht_sta_priv { · 60 unmodified lines
110103 struct minstrel_ht_sta ht;
111104 struct minstrel_sta_info legacy;
112105 };
113−#ifdef CONFIG_MAC80211_DEBUGFS
114− struct dentry *dbg_stats;
115− struct dentry *dbg_stats_csv;
116−#endif
117106 void *ratelist;
118107 void *sample_table;
119108 bool is_ht;
120109 };
121110
122111 void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
123−void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
124112 int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
125113 int prob_ewma);
126114
net/mac80211/rc80211_minstrel_ht_debugfs.c+33−25
@@ -15,6 +15,22 @@ · 14 unmodified lines
1515 #include "rc80211_minstrel.h"
1616 #include "rc80211_minstrel_ht.h"
1717
18+static ssize_t
19+minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
20+{
21+ struct minstrel_debugfs_info *ms;
22+
23+ ms = file->private_data;
24+ return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
25+}
26+
27+static int
28+minstrel_stats_release(struct inode *inode, struct file *file)
29+{
30+ kfree(file->private_data);
31+ return 0;
32+}
33+
1834 static char *
1935 minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
2036 {
@@ -41,7 +57,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) · 20 unmodified lines
4157 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
4258 static const int bitrates[4] = { 10, 20, 55, 110 };
4359 int idx = i * MCS_GROUP_RATES + j;
44− unsigned int prob_ewmsd;
60+ unsigned int duration;
4561
4662 if (!(mi->supported[i] & BIT(j)))
4763 continue;
@@ -79,21 +95,21 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) · 31 unmodified lines
7995 p += sprintf(p, " %3u ", idx);
8096
8197 /* tx_time[rate(i)] in usec */
82− tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
98+ duration = mg->duration[j];
99+ duration <<= mg->shift;
100+ tx_time = DIV_ROUND_CLOSEST(duration, 1000);
83101 p += sprintf(p, "%6u ", tx_time);
84102
85103 tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
86104 tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
87105 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
88− prob_ewmsd = minstrel_get_ewmsd10(mrs);
89106
90− p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
107+ p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u"
91108 " %3u %3u %-3u "
92109 "%9llu %-9llu\n",
93110 tp_max / 10, tp_max % 10,
94111 tp_avg / 10, tp_avg % 10,
95112 eprob / 10, eprob % 10,
96− prob_ewmsd / 10, prob_ewmsd % 10,
97113 mrs->retry_count,
98114 mrs->last_success,
99115 mrs->last_attempts,
@@ -130,9 +146,9 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) · 30 unmodified lines
130146
131147 p += sprintf(p, "\n");
132148 p += sprintf(p,
133− " best ____________rate__________ ________statistics________ _____last____ ______sum-of________\n");
149+ " best ____________rate__________ ____statistics___ _____last____ ______sum-of________\n");
134150 p += sprintf(p,
135− "mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [retry|suc|att] [#success | #attempts]\n");
151+ "mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]\n");
136152
137153 p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
138154 for (i = 0; i < MINSTREL_CCK_GROUP; i++)
@@ -187,7 +203,7 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) · 48 unmodified lines
187203 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
188204 static const int bitrates[4] = { 10, 20, 55, 110 };
189205 int idx = i * MCS_GROUP_RATES + j;
190− unsigned int prob_ewmsd;
206+ unsigned int duration;
191207
192208 if (!(mi->supported[i] & BIT(j)))
193209 continue;
@@ -222,20 +238,21 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) · 28 unmodified lines
222238 }
223239
224240 p += sprintf(p, "%u,", idx);
225− tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
241+
242+ duration = mg->duration[j];
243+ duration <<= mg->shift;
244+ tx_time = DIV_ROUND_CLOSEST(duration, 1000);
226245 p += sprintf(p, "%u,", tx_time);
227246
228247 tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
229248 tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
230249 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
231− prob_ewmsd = minstrel_get_ewmsd10(mrs);
232250
233− p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
251+ p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,"
234252 "%u,%llu,%llu,",
235253 tp_max / 10, tp_max % 10,
236254 tp_avg / 10, tp_avg % 10,
237255 eprob / 10, eprob % 10,
238− prob_ewmsd / 10, prob_ewmsd % 10,
239256 mrs->retry_count,
240257 mrs->last_success,
241258 mrs->last_attempts,
@@ -303,17 +320,8 @@ minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) · 61 unmodified lines
303320 {
304321 struct minstrel_ht_sta_priv *msp = priv_sta;
305322
306− msp->dbg_stats = debugfs_create_file("rc_stats", 0444, dir, msp,
307− &minstrel_ht_stat_fops);
308− msp->dbg_stats_csv = debugfs_create_file("rc_stats_csv", 0444, dir, msp,
309− &minstrel_ht_stat_csv_fops);
310−}
311−
312−void
313−minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta)
314−{
315− struct minstrel_ht_sta_priv *msp = priv_sta;
316−
317− debugfs_remove(msp->dbg_stats);
318− debugfs_remove(msp->dbg_stats_csv);
323+ debugfs_create_file("rc_stats", 0444, dir, msp,
324+ &minstrel_ht_stat_fops);
325+ debugfs_create_file("rc_stats_csv", 0444, dir, msp,
326+ &minstrel_ht_stat_csv_fops);
319327 }
net/mac80211/rx.c+6−6
@@ -2458,8 +2458,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) · 2457 unmodified lines
24582458 if (!xmit_skb)
24592459 net_info_ratelimited("%s: failed to clone multicast frame\n",
24602460 dev->name);
2461− } else if (!is_multicast_ether_addr(ehdr->h_dest)) {
2462− dsta = sta_info_get(sdata, skb->data);
2461+ } else if (!is_multicast_ether_addr(ehdr->h_dest) &&
2462+ !ether_addr_equal(ehdr->h_dest, ehdr->h_source)) {
2463+ dsta = sta_info_get(sdata, ehdr->h_dest);
24632464 if (dsta) {
24642465 /*
24652466 * The destination station is associated to
@@ -4240,11 +4241,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, · 1774 unmodified lines
42404241
42414242 if (fast_rx->internal_forward) {
42424243 struct sk_buff *xmit_skb = NULL;
4243− bool multicast = is_multicast_ether_addr(skb->data);
4244−
4245− if (multicast) {
4244+ if (is_multicast_ether_addr(addrs.da)) {
42464245 xmit_skb = skb_copy(skb, GFP_ATOMIC);
4247− } else if (sta_info_get(rx->sdata, skb->data)) {
4246+ } else if (!ether_addr_equal(addrs.da, addrs.sa) &&
4247+ sta_info_get(rx->sdata, addrs.da)) {
42484248 xmit_skb = skb;
42494249 skb = NULL;
42504250 }
net/mac80211/status.c+19−0
@@ -987,6 +987,25 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw, · 986 unmodified lines
987987 }
988988 EXPORT_SYMBOL(ieee80211_tx_status_ext);
989989
990+void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
991+ struct ieee80211_sta *pubsta,
992+ struct ieee80211_tx_info *info)
993+{
994+ struct ieee80211_local *local = hw_to_local(hw);
995+ struct ieee80211_supported_band *sband = hw->wiphy->bands[info->band];
996+ struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
997+ struct ieee80211_tx_status status = {
998+ .info = info,
999+ .sta = pubsta,
1000+ };
1001+
1002+ rate_control_tx_status(local, sband, &status);
1003+
1004+ if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL))
1005+ sta->tx_stats.last_rate = info->status.rates[0];
1006+}
1007+EXPORT_SYMBOL(ieee80211_tx_rate_update);
1008+
9901009 void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
9911010 {
9921011 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
net/mac80211/trace.h+23−0
@@ -2600,6 +2600,29 @@ TRACE_EVENT(drv_wake_tx_queue, · 2599 unmodified lines
26002600 )
26012601 );
26022602
2603+TRACE_EVENT(drv_get_ftm_responder_stats,
2604+ TP_PROTO(struct ieee80211_local *local,
2605+ struct ieee80211_sub_if_data *sdata,
2606+ struct cfg80211_ftm_responder_stats *ftm_stats),
2607+
2608+ TP_ARGS(local, sdata, ftm_stats),
2609+
2610+ TP_STRUCT__entry(
2611+ LOCAL_ENTRY
2612+ VIF_ENTRY
2613+ ),
2614+
2615+ TP_fast_assign(
2616+ LOCAL_ASSIGN;
2617+ VIF_ASSIGN;
2618+ ),
2619+
2620+ TP_printk(
2621+ LOCAL_PR_FMT VIF_PR_FMT,
2622+ LOCAL_PR_ARG, VIF_PR_ARG
2623+ )
2624+);
2625+
26032626 #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
26042627
26052628 #undef TRACE_INCLUDE_PATH
net/mac80211/util.c+8−0
@@ -264,6 +264,9 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac) · 263 unmodified lines
264264 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
265265 struct ieee80211_txq *txq = sta->sta.txq[i];
266266
267+ if (!txq)
268+ continue;
269+
267270 txqi = to_txq_info(txq);
268271
269272 if (ac != txq->ac)
@@ -2175,6 +2178,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) · 1905 unmodified lines
21752178 case NL80211_IFTYPE_AP:
21762179 changed |= BSS_CHANGED_SSID | BSS_CHANGED_P2P_PS;
21772180
2181+ if (sdata->vif.bss_conf.ftm_responder == 1 &&
2182+ wiphy_ext_feature_isset(sdata->local->hw.wiphy,
2183+ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
2184+ changed |= BSS_CHANGED_FTM_RESPONDER;
2185+
21782186 if (sdata->vif.type == NL80211_IFTYPE_AP) {
21792187 changed |= BSS_CHANGED_AP_PROBE_RESP;
21802188
net/wireless/core.c+47−36
@@ -1019,36 +1019,49 @@ void cfg80211_cqm_config_free(struct wireless_dev *wdev) · 1018 unmodified lines
10191019 wdev->cqm_config = NULL;
10201020 }
10211021
1022−void cfg80211_unregister_wdev(struct wireless_dev *wdev)
1022+static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync)
10231023 {
10241024 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
10251025
10261026 ASSERT_RTNL();
10271027
1028− if (WARN_ON(wdev->netdev))
1029− return;
1030−
10311028 nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
10321029
10331030 list_del_rcu(&wdev->list);
1034− synchronize_rcu();
1031+ if (sync)
1032+ synchronize_rcu();
10351033 rdev->devlist_generation++;
10361034
1035+ cfg80211_mlme_purge_registrations(wdev);
1036+
10371037 switch (wdev->iftype) {
10381038 case NL80211_IFTYPE_P2P_DEVICE:
1039− cfg80211_mlme_purge_registrations(wdev);
10401039 cfg80211_stop_p2p_device(rdev, wdev);
10411040 break;
10421041 case NL80211_IFTYPE_NAN:
10431042 cfg80211_stop_nan(rdev, wdev);
10441043 break;
10451044 default:
1046− WARN_ON_ONCE(1);
10471045 break;
10481046 }
10491047
1048+#ifdef CONFIG_CFG80211_WEXT
1049+ kzfree(wdev->wext.keys);
1050+#endif
1051+ /* only initialized if we have a netdev */
1052+ if (wdev->netdev)
1053+ flush_work(&wdev->disconnect_wk);
1054+
10501055 cfg80211_cqm_config_free(wdev);
10511056 }
1057+
1058+void cfg80211_unregister_wdev(struct wireless_dev *wdev)
1059+{
1060+ if (WARN_ON(wdev->netdev))
1061+ return;
1062+
1063+ __cfg80211_unregister_wdev(wdev, true);
1064+}
10521065 EXPORT_SYMBOL(cfg80211_unregister_wdev);
10531066
10541067 static const struct device_type wiphy_type = {
@@ -1153,6 +1166,30 @@ void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, · 98 unmodified lines
11531166 }
11541167 EXPORT_SYMBOL(cfg80211_stop_iface);
11551168
1169+void cfg80211_init_wdev(struct cfg80211_registered_device *rdev,
1170+ struct wireless_dev *wdev)
1171+{
1172+ mutex_init(&wdev->mtx);
1173+ INIT_LIST_HEAD(&wdev->event_list);
1174+ spin_lock_init(&wdev->event_lock);
1175+ INIT_LIST_HEAD(&wdev->mgmt_registrations);
1176+ spin_lock_init(&wdev->mgmt_registrations_lock);
1177+
1178+ /*
1179+ * We get here also when the interface changes network namespaces,
1180+ * as it's registered into the new one, but we don't want it to
1181+ * change ID in that case. Checking if the ID is already assigned
1182+ * works, because 0 isn't considered a valid ID and the memory is
1183+ * 0-initialized.
1184+ */
1185+ if (!wdev->identifier)
1186+ wdev->identifier = ++rdev->wdev_id;
1187+ list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
1188+ rdev->devlist_generation++;
1189+
1190+ nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
1191+}
1192+
11561193 static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
11571194 unsigned long state, void *ptr)
11581195 {
@@ -1178,23 +1215,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 19 unmodified lines
11781215 * called within code protected by it when interfaces
11791216 * are added with nl80211.
11801217 */
1181− mutex_init(&wdev->mtx);
1182− INIT_LIST_HEAD(&wdev->event_list);
1183− spin_lock_init(&wdev->event_lock);
1184− INIT_LIST_HEAD(&wdev->mgmt_registrations);
1185− spin_lock_init(&wdev->mgmt_registrations_lock);
1186−
1187− /*
1188− * We get here also when the interface changes network namespaces,
1189− * as it's registered into the new one, but we don't want it to
1190− * change ID in that case. Checking if the ID is already assigned
1191− * works, because 0 isn't considered a valid ID and the memory is
1192− * 0-initialized.
1193− */
1194− if (!wdev->identifier)
1195− wdev->identifier = ++rdev->wdev_id;
1196− list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
1197− rdev->devlist_generation++;
11981218 /* can only change netns with wiphy */
11991219 dev->features |= NETIF_F_NETNS_LOCAL;
12001220
@@ -1223,7 +1243,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 22 unmodified lines
12231243
12241244 INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);
12251245
1226− nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
1246+ cfg80211_init_wdev(rdev, wdev);
12271247 break;
12281248 case NETDEV_GOING_DOWN:
12291249 cfg80211_leave(rdev, wdev);
@@ -1238,7 +1258,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 8 unmodified lines
12381258
12391259 list_for_each_entry_safe(pos, tmp,
12401260 &rdev->sched_scan_req_list, list) {
1241− if (WARN_ON(pos && pos->dev == wdev->netdev))
1261+ if (WARN_ON(pos->dev == wdev->netdev))
12421262 cfg80211_stop_sched_scan_req(rdev, pos, false);
12431263 }
12441264
@@ -1302,17 +1322,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 57 unmodified lines
13021322 * remove and clean it up.
13031323 */
13041324 if (!list_empty(&wdev->list)) {
1305− nl80211_notify_iface(rdev, wdev,
1306− NL80211_CMD_DEL_INTERFACE);
1325+ __cfg80211_unregister_wdev(wdev, false);
13071326 sysfs_remove_link(&dev->dev.kobj, "phy80211");
1308− list_del_rcu(&wdev->list);
1309− rdev->devlist_generation++;
1310− cfg80211_mlme_purge_registrations(wdev);
1311−#ifdef CONFIG_CFG80211_WEXT
1312− kzfree(wdev->wext.keys);
1313−#endif
1314− flush_work(&wdev->disconnect_wk);
1315− cfg80211_cqm_config_free(wdev);
13161327 }
13171328 /*
13181329 * synchronise (so that we won't find this netdev
net/wireless/core.h+14−0
@@ -66,6 +66,7 @@ struct cfg80211_registered_device { · 65 unmodified lines
6666 /* protected by RTNL only */
6767 int num_running_ifaces;
6868 int num_running_monitor_ifaces;
69+ u64 cookie_counter;
6970
7071 /* BSSes/scanning */
7172 spinlock_t bss_lock;
@@ -133,6 +134,16 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) · 61 unmodified lines
133134 #endif
134135 }
135136
137+static inline u64 cfg80211_assign_cookie(struct cfg80211_registered_device *rdev)
138+{
139+ u64 r = ++rdev->cookie_counter;
140+
141+ if (WARN_ON(r == 0))
142+ r = ++rdev->cookie_counter;
143+
144+ return r;
145+}
146+
136147 extern struct workqueue_struct *cfg80211_wq;
137148 extern struct list_head cfg80211_rdev_list;
138149 extern int cfg80211_rdev_list_generation;
@@ -187,6 +198,9 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); · 48 unmodified lines
187198 int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
188199 struct net *net);
189200
201+void cfg80211_init_wdev(struct cfg80211_registered_device *rdev,
202+ struct wireless_dev *wdev);
203+
190204 static inline void wdev_lock(struct wireless_dev *wdev)
191205 __acquires(wdev)
192206 {
net/wireless/lib80211_crypt_tkip.c+20−39
@@ -30,7 +30,7 @@ · 29 unmodified lines
3030 #include <net/iw_handler.h>
3131
3232 #include <crypto/hash.h>
33−#include <crypto/skcipher.h>
33+#include <linux/crypto.h>
3434 #include <linux/crc32.h>
3535
3636 #include <net/lib80211.h>
@@ -64,9 +64,9 @@ struct lib80211_tkip_data { · 27 unmodified lines
6464
6565 int key_idx;
6666
67− struct crypto_skcipher *rx_tfm_arc4;
67+ struct crypto_cipher *rx_tfm_arc4;
6868 struct crypto_shash *rx_tfm_michael;
69− struct crypto_skcipher *tx_tfm_arc4;
69+ struct crypto_cipher *tx_tfm_arc4;
7070 struct crypto_shash *tx_tfm_michael;
7171
7272 /* scratch buffers for virt_to_page() (crypto API) */
@@ -99,8 +99,7 @@ static void *lib80211_tkip_init(int key_idx) · 26 unmodified lines
9999
100100 priv->key_idx = key_idx;
101101
102− priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0,
103− CRYPTO_ALG_ASYNC);
102+ priv->tx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
104103 if (IS_ERR(priv->tx_tfm_arc4)) {
105104 priv->tx_tfm_arc4 = NULL;
106105 goto fail;
@@ -112,8 +111,7 @@ static void *lib80211_tkip_init(int key_idx) · 5 unmodified lines
112111 goto fail;
113112 }
114113
115− priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0,
116− CRYPTO_ALG_ASYNC);
114+ priv->rx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
117115 if (IS_ERR(priv->rx_tfm_arc4)) {
118116 priv->rx_tfm_arc4 = NULL;
119117 goto fail;
@@ -130,9 +128,9 @@ static void *lib80211_tkip_init(int key_idx) · 10 unmodified lines
130128 fail:
131129 if (priv) {
132130 crypto_free_shash(priv->tx_tfm_michael);
133− crypto_free_skcipher(priv->tx_tfm_arc4);
131+ crypto_free_cipher(priv->tx_tfm_arc4);
134132 crypto_free_shash(priv->rx_tfm_michael);
135− crypto_free_skcipher(priv->rx_tfm_arc4);
133+ crypto_free_cipher(priv->rx_tfm_arc4);
136134 kfree(priv);
137135 }
138136
@@ -144,9 +142,9 @@ static void lib80211_tkip_deinit(void *priv) · 5 unmodified lines
144142 struct lib80211_tkip_data *_priv = priv;
145143 if (_priv) {
146144 crypto_free_shash(_priv->tx_tfm_michael);
147− crypto_free_skcipher(_priv->tx_tfm_arc4);
145+ crypto_free_cipher(_priv->tx_tfm_arc4);
148146 crypto_free_shash(_priv->rx_tfm_michael);
149− crypto_free_skcipher(_priv->rx_tfm_arc4);
147+ crypto_free_cipher(_priv->rx_tfm_arc4);
150148 }
151149 kfree(priv);
152150 }
@@ -344,12 +342,10 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, · 191 unmodified lines
344342 static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
345343 {
346344 struct lib80211_tkip_data *tkey = priv;
347− SKCIPHER_REQUEST_ON_STACK(req, tkey->tx_tfm_arc4);
348345 int len;
349346 u8 rc4key[16], *pos, *icv;
350347 u32 crc;
351− struct scatterlist sg;
352− int err;
348+ int i;
353349
354350 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
355351 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -374,14 +370,10 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) · 18 unmodified lines
374370 icv[2] = crc >> 16;
375371 icv[3] = crc >> 24;
376372
377− crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
378− sg_init_one(&sg, pos, len + 4);
379− skcipher_request_set_tfm(req, tkey->tx_tfm_arc4);
380− skcipher_request_set_callback(req, 0, NULL, NULL);
381− skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL);
382− err = crypto_skcipher_encrypt(req);
383− skcipher_request_zero(req);
384− return err;
373+ crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
374+ for (i = 0; i < len + 4; i++)
375+ crypto_cipher_encrypt_one(tkey->tx_tfm_arc4, pos + i, pos + i);
376+ return 0;
385377 }
386378
387379 /*
@@ -400,7 +392,6 @@ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n, · 12 unmodified lines
400392 static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
401393 {
402394 struct lib80211_tkip_data *tkey = priv;
403− SKCIPHER_REQUEST_ON_STACK(req, tkey->rx_tfm_arc4);
404395 u8 rc4key[16];
405396 u8 keyidx, *pos;
406397 u32 iv32;
@@ -408,9 +399,8 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) · 1 unmodified line
408399 struct ieee80211_hdr *hdr;
409400 u8 icv[4];
410401 u32 crc;
411− struct scatterlist sg;
412402 int plen;
413− int err;
403+ int i;
414404
415405 hdr = (struct ieee80211_hdr *)skb->data;
416406
@@ -463,18 +453,9 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) · 46 unmodified lines
463453
464454 plen = skb->len - hdr_len - 12;
465455
466− crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
467− sg_init_one(&sg, pos, plen + 4);
468− skcipher_request_set_tfm(req, tkey->rx_tfm_arc4);
469− skcipher_request_set_callback(req, 0, NULL, NULL);
470− skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL);
471− err = crypto_skcipher_decrypt(req);
472− skcipher_request_zero(req);
473− if (err) {
474− net_dbg_ratelimited("TKIP: failed to decrypt received packet from %pM\n",
475− hdr->addr2);
476− return -7;
477− }
456+ crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
457+ for (i = 0; i < plen + 4; i++)
458+ crypto_cipher_decrypt_one(tkey->rx_tfm_arc4, pos + i, pos + i);
478459
479460 crc = ~crc32_le(~0, pos, plen);
480461 icv[0] = crc;
@@ -660,9 +641,9 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) · 179 unmodified lines
660641 struct lib80211_tkip_data *tkey = priv;
661642 int keyidx;
662643 struct crypto_shash *tfm = tkey->tx_tfm_michael;
663− struct crypto_skcipher *tfm2 = tkey->tx_tfm_arc4;
644+ struct crypto_cipher *tfm2 = tkey->tx_tfm_arc4;
664645 struct crypto_shash *tfm3 = tkey->rx_tfm_michael;
665− struct crypto_skcipher *tfm4 = tkey->rx_tfm_arc4;
646+ struct crypto_cipher *tfm4 = tkey->rx_tfm_arc4;
666647
667648 keyidx = tkey->key_idx;
668649 memset(tkey, 0, sizeof(*tkey));
net/wireless/lib80211_crypt_wep.c+20−32
@@ -22,7 +22,7 @@ · 21 unmodified lines
2222
2323 #include <net/lib80211.h>
2424
25−#include <crypto/skcipher.h>
25+#include <linux/crypto.h>
2626 #include <linux/crc32.h>
2727
2828 MODULE_AUTHOR("Jouni Malinen");
@@ -35,8 +35,8 @@ struct lib80211_wep_data { · 6 unmodified lines
3535 u8 key[WEP_KEY_LEN + 1];
3636 u8 key_len;
3737 u8 key_idx;
38− struct crypto_skcipher *tx_tfm;
39− struct crypto_skcipher *rx_tfm;
38+ struct crypto_cipher *tx_tfm;
39+ struct crypto_cipher *rx_tfm;
4040 };
4141
4242 static void *lib80211_wep_init(int keyidx)
@@ -48,13 +48,13 @@ static void *lib80211_wep_init(int keyidx) · 5 unmodified lines
4848 goto fail;
4949 priv->key_idx = keyidx;
5050
51− priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
51+ priv->tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
5252 if (IS_ERR(priv->tx_tfm)) {
5353 priv->tx_tfm = NULL;
5454 goto fail;
5555 }
5656
57− priv->rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
57+ priv->rx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
5858 if (IS_ERR(priv->rx_tfm)) {
5959 priv->rx_tfm = NULL;
6060 goto fail;
@@ -66,8 +66,8 @@ static void *lib80211_wep_init(int keyidx) · 5 unmodified lines
6666
6767 fail:
6868 if (priv) {
69− crypto_free_skcipher(priv->tx_tfm);
70− crypto_free_skcipher(priv->rx_tfm);
69+ crypto_free_cipher(priv->tx_tfm);
70+ crypto_free_cipher(priv->rx_tfm);
7171 kfree(priv);
7272 }
7373 return NULL;
@@ -77,8 +77,8 @@ static void lib80211_wep_deinit(void *priv) · 3 unmodified lines
7777 {
7878 struct lib80211_wep_data *_priv = priv;
7979 if (_priv) {
80− crypto_free_skcipher(_priv->tx_tfm);
81− crypto_free_skcipher(_priv->rx_tfm);
80+ crypto_free_cipher(_priv->tx_tfm);
81+ crypto_free_cipher(_priv->rx_tfm);
8282 }
8383 kfree(priv);
8484 }
@@ -129,12 +129,10 @@ static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len, · 44 unmodified lines
129129 static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
130130 {
131131 struct lib80211_wep_data *wep = priv;
132− SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm);
133132 u32 crc, klen, len;
134133 u8 *pos, *icv;
135− struct scatterlist sg;
136134 u8 key[WEP_KEY_LEN + 3];
137− int err;
135+ int i;
138136
139137 /* other checks are in lib80211_wep_build_iv */
140138 if (skb_tailroom(skb) < 4)
@@ -162,14 +160,12 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) · 21 unmodified lines
162160 icv[2] = crc >> 16;
163161 icv[3] = crc >> 24;
164162
165− crypto_skcipher_setkey(wep->tx_tfm, key, klen);
166− sg_init_one(&sg, pos, len + 4);
167− skcipher_request_set_tfm(req, wep->tx_tfm);
168− skcipher_request_set_callback(req, 0, NULL, NULL);
169− skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL);
170− err = crypto_skcipher_encrypt(req);
171− skcipher_request_zero(req);
172− return err;
163+ crypto_cipher_setkey(wep->tx_tfm, key, klen);
164+
165+ for (i = 0; i < len + 4; i++)
166+ crypto_cipher_encrypt_one(wep->tx_tfm, pos + i, pos + i);
167+
168+ return 0;
173169 }
174170
175171 /* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
@@ -182,12 +178,10 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) · 6 unmodified lines
182178 static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
183179 {
184180 struct lib80211_wep_data *wep = priv;
185− SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm);
186181 u32 crc, klen, plen;
187182 u8 key[WEP_KEY_LEN + 3];
188183 u8 keyidx, *pos, icv[4];
189− struct scatterlist sg;
190− int err;
184+ int i;
191185
192186 if (skb->len < hdr_len + 8)
193187 return -1;
@@ -208,15 +202,9 @@ static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) · 14 unmodified lines
208202 /* Apply RC4 to data and compute CRC32 over decrypted data */
209203 plen = skb->len - hdr_len - 8;
210204
211− crypto_skcipher_setkey(wep->rx_tfm, key, klen);
212− sg_init_one(&sg, pos, plen + 4);
213− skcipher_request_set_tfm(req, wep->rx_tfm);
214− skcipher_request_set_callback(req, 0, NULL, NULL);
215− skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL);
216− err = crypto_skcipher_decrypt(req);
217− skcipher_request_zero(req);
218− if (err)
219− return -7;
205+ crypto_cipher_setkey(wep->rx_tfm, key, klen);
206+ for (i = 0; i < plen + 4; i++)
207+ crypto_cipher_decrypt_one(wep->rx_tfm, pos + i, pos + i);
220208
221209 crc = ~crc32_le(~0, pos, plen);
222210 icv[0] = crc;
net/wireless/nl80211.c+407−423
@@ -200,7 +200,46 @@ cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) · 199 unmodified lines
200200 return __cfg80211_rdev_from_attrs(netns, info->attrs);
201201 }
202202
203+static int validate_ie_attr(const struct nlattr *attr,
204+ struct netlink_ext_ack *extack)
205+{
206+ const u8 *pos;
207+ int len;
208+
209+ pos = nla_data(attr);
210+ len = nla_len(attr);
211+
212+ while (len) {
213+ u8 elemlen;
214+
215+ if (len < 2)
216+ goto error;
217+ len -= 2;
218+
219+ elemlen = pos[1];
220+ if (elemlen > len)
221+ goto error;
222+
223+ len -= elemlen;
224+ pos += 2 + elemlen;
225+ }
226+
227+ return 0;
228+error:
229+ NL_SET_ERR_MSG_ATTR(extack, attr, "malformed information elements");
230+ return -EINVAL;
231+}
232+
203233 /* policy for the attributes */
234+static const struct nla_policy
235+nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
236+ [NL80211_FTM_RESP_ATTR_ENABLED] = { .type = NLA_FLAG, },
237+ [NL80211_FTM_RESP_ATTR_LCI] = { .type = NLA_BINARY,
238+ .len = U8_MAX },
239+ [NL80211_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_BINARY,
240+ .len = U8_MAX },
241+};
242+
204243 static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
205244 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
206245 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
@@ -213,14 +252,14 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 6 unmodified lines
213252 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
214253 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
215254
216− [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
217− [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
255+ [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
256+ [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
218257 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
219258 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
220259 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
221260 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
222261
223− [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
262+ [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
224263 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
225264 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
226265
@@ -230,24 +269,28 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 3 unmodified lines
230269 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
231270 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
232271 .len = WLAN_MAX_KEY_LEN },
233− [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
272+ [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 5),
234273 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
235274 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
236275 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
237− [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
276+ [NL80211_ATTR_KEY_TYPE] =
277+ NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES),
238278
239279 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
240280 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
241281 [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
242282 .len = IEEE80211_MAX_DATA_LEN },
243− [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
244− .len = IEEE80211_MAX_DATA_LEN },
245− [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
283+ [NL80211_ATTR_BEACON_TAIL] =
284+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
285+ IEEE80211_MAX_DATA_LEN),
286+ [NL80211_ATTR_STA_AID] =
287+ NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
246288 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
247289 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
248290 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
249291 .len = NL80211_MAX_SUPP_RATES },
250− [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
292+ [NL80211_ATTR_STA_PLINK_ACTION] =
293+ NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1),
251294 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
252295 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
253296 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
@@ -270,8 +313,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 16 unmodified lines
270313 [NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN },
271314
272315 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
273− [NL80211_ATTR_IE] = { .type = NLA_BINARY,
274− .len = IEEE80211_MAX_DATA_LEN },
316+ [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
317+ validate_ie_attr,
318+ IEEE80211_MAX_DATA_LEN),
275319 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
276320 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
277321
@@ -281,7 +325,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 3 unmodified lines
281325 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
282326 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
283327 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
284− [NL80211_ATTR_USE_MFP] = { .type = NLA_U32 },
328+ [NL80211_ATTR_USE_MFP] = NLA_POLICY_RANGE(NLA_U32,
329+ NL80211_MFP_NO,
330+ NL80211_MFP_OPTIONAL),
285331 [NL80211_ATTR_STA_FLAGS2] = {
286332 .len = sizeof(struct nl80211_sta_flag_update),
287333 },
@@ -301,7 +347,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 13 unmodified lines
301347 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
302348 .len = IEEE80211_MAX_DATA_LEN },
303349 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },
304− [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 },
350+ [NL80211_ATTR_PS_STATE] = NLA_POLICY_RANGE(NLA_U32,
351+ NL80211_PS_DISABLED,
352+ NL80211_PS_ENABLED),
305353 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
306354 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
307355 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
@@ -314,15 +362,23 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 6 unmodified lines
314362 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
315363 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
316364 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
317− [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
365+ [NL80211_ATTR_STA_PLINK_STATE] =
366+ NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
367+ [NL80211_ATTR_MESH_PEER_AID] =
368+ NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
318369 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
319370 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
320371 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
321− [NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 },
322− [NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY,
323− .len = IEEE80211_MAX_DATA_LEN },
324− [NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY,
325− .len = IEEE80211_MAX_DATA_LEN },
372+ [NL80211_ATTR_HIDDEN_SSID] =
373+ NLA_POLICY_RANGE(NLA_U32,
374+ NL80211_HIDDEN_SSID_NOT_IN_USE,
375+ NL80211_HIDDEN_SSID_ZERO_CONTENTS),
376+ [NL80211_ATTR_IE_PROBE_RESP] =
377+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
378+ IEEE80211_MAX_DATA_LEN),
379+ [NL80211_ATTR_IE_ASSOC_RESP] =
380+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
381+ IEEE80211_MAX_DATA_LEN),
326382 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
327383 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
328384 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },
@@ -348,9 +404,12 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 19 unmodified lines
348404 [NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, },
349405 [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
350406 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
351− [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
352− [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
353− [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 },
407+ [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
408+ [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
409+ [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
410+ NLA_POLICY_RANGE(NLA_U32,
411+ NL80211_MESH_POWER_UNKNOWN + 1,
412+ NL80211_MESH_POWER_MAX),
354413 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
355414 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
356415 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
@@ -363,7 +422,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 6 unmodified lines
363422 [NL80211_ATTR_MDID] = { .type = NLA_U16 },
364423 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
365424 .len = IEEE80211_MAX_DATA_LEN },
366− [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },
425+ [NL80211_ATTR_PEER_AID] =
426+ NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
367427 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
368428 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
369429 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
@@ -384,8 +444,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 14 unmodified lines
384444 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
385445 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
386446 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
387− [NL80211_ATTR_TSID] = { .type = NLA_U8 },
388− [NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
447+ [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
448+ [NL80211_ATTR_USER_PRIO] =
449+ NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
389450 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
390451 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
391452 [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },
@@ -395,12 +456,13 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 3 unmodified lines
395456 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
396457 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
397458 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
398− [NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 },
459+ [NL80211_ATTR_STA_SUPPORT_P2P_PS] =
460+ NLA_POLICY_MAX(NLA_U8, NUM_NL80211_P2P_PS_STATUS - 1),
399461 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
400462 .len = VHT_MUMIMO_GROUPS_DATA_LEN
401463 },
402464 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
403− [NL80211_ATTR_NAN_MASTER_PREF] = { .type = NLA_U8 },
465+ [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),
404466 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
405467 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
406468 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
@@ -430,6 +492,11 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 23 unmodified lines
430492 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
431493 [NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY,
432494 .len = NL80211_HE_MAX_CAPABILITY_LEN },
495+
496+ [NL80211_ATTR_FTM_RESPONDER] = {
497+ .type = NLA_NESTED,
498+ .validation_data = nl80211_ftm_responder_policy,
499+ },
433500 };
434501
435502 /* policy for the key attributes */
@@ -440,7 +507,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { · 4 unmodified lines
440507 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
441508 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
442509 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
443− [NL80211_KEY_TYPE] = { .type = NLA_U32 },
510+ [NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
444511 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
445512 };
446513
@@ -491,7 +558,10 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = { · 44 unmodified lines
491558 static const struct nla_policy
492559 nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
493560 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },
494− [NL80211_ATTR_COALESCE_RULE_CONDITION] = { .type = NLA_U32 },
561+ [NL80211_ATTR_COALESCE_RULE_CONDITION] =
562+ NLA_POLICY_RANGE(NLA_U32,
563+ NL80211_COALESCE_CONDITION_MATCH,
564+ NL80211_COALESCE_CONDITION_NO_MATCH),
495565 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
496566 };
497567
@@ -567,8 +637,7 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = { · 69 unmodified lines
567637 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
568638 };
569639
570−static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
571− struct netlink_callback *cb,
640+static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
572641 struct cfg80211_registered_device **rdev,
573642 struct wireless_dev **wdev)
574643 {
@@ -582,7 +651,7 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, · 7 unmodified lines
582651 return err;
583652
584653 *wdev = __cfg80211_wdev_from_attrs(
585− sock_net(skb->sk),
654+ sock_net(cb->skb->sk),
586655 genl_family_attrbuf(&nl80211_fam));
587656 if (IS_ERR(*wdev))
588657 return PTR_ERR(*wdev);
@@ -614,36 +683,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, · 25 unmodified lines
614683 return 0;
615684 }
616685
617−/* IE validation */
618−static bool is_valid_ie_attr(const struct nlattr *attr)
619−{
620− const u8 *pos;
621− int len;
622−
623− if (!attr)
624− return true;
625−
626− pos = nla_data(attr);
627− len = nla_len(attr);
628−
629− while (len) {
630− u8 elemlen;
631−
632− if (len < 2)
633− return false;
634− len -= 2;
635−
636− elemlen = pos[1];
637− if (elemlen > len)
638− return false;
639−
640− len -= elemlen;
641− pos += 2 + elemlen;
642− }
643−
644− return true;
645−}
646−
647686 /* message building helper */
648687 static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
649688 int flags, u8 cmd)
@@ -858,12 +897,8 @@ static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key, · 208 unmodified lines
858897 if (tb[NL80211_KEY_CIPHER])
859898 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
860899
861− if (tb[NL80211_KEY_TYPE]) {
900+ if (tb[NL80211_KEY_TYPE])
862901 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
863− if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
864− return genl_err_attr(info, -EINVAL,
865− tb[NL80211_KEY_TYPE]);
866− }
867902
868903 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
869904 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
@@ -910,13 +945,8 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k) · 40 unmodified lines
910945 if (k->defmgmt)
911946 k->def_multi = true;
912947
913− if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
948+ if (info->attrs[NL80211_ATTR_KEY_TYPE])
914949 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
915− if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) {
916− GENL_SET_ERR_MSG(info, "key type out of range");
917− return -EINVAL;
918− }
919− }
920950
921951 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
922952 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
@@ -2292,12 +2322,14 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, · 1369 unmodified lines
22922322 struct genl_info *info,
22932323 struct cfg80211_chan_def *chandef)
22942324 {
2325+ struct netlink_ext_ack *extack = info->extack;
2326+ struct nlattr **attrs = info->attrs;
22952327 u32 control_freq;
22962328
2297− if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
2329+ if (!attrs[NL80211_ATTR_WIPHY_FREQ])
22982330 return -EINVAL;
22992331
2300− control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
2332+ control_freq = nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ]);
23012333
23022334 chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);
23032335 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
@@ -2305,14 +2337,16 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, · 1 unmodified line
23052337 chandef->center_freq2 = 0;
23062338
23072339 /* Primary channel not allowed */
2308− if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED)
2340+ if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED) {
2341+ NL_SET_ERR_MSG_ATTR(extack, attrs[NL80211_ATTR_WIPHY_FREQ],
2342+ "Channel is disabled");
23092343 return -EINVAL;
2344+ }
23102345
2311− if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
2346+ if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
23122347 enum nl80211_channel_type chantype;
23132348
2314− chantype = nla_get_u32(
2315− info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
2349+ chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
23162350
23172351 switch (chantype) {
23182352 case NL80211_CHAN_NO_HT:
@@ -2322,42 +2356,56 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, · 3 unmodified lines
23222356 cfg80211_chandef_create(chandef, chandef->chan,
23232357 chantype);
23242358 /* user input for center_freq is incorrect */
2325− if (info->attrs[NL80211_ATTR_CENTER_FREQ1] &&
2326− chandef->center_freq1 != nla_get_u32(
2327− info->attrs[NL80211_ATTR_CENTER_FREQ1]))
2359+ if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
2360+ chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
2361+ NL_SET_ERR_MSG_ATTR(extack,
2362+ attrs[NL80211_ATTR_CENTER_FREQ1],
2363+ "bad center frequency 1");
23282364 return -EINVAL;
2365+ }
23292366 /* center_freq2 must be zero */
2330− if (info->attrs[NL80211_ATTR_CENTER_FREQ2] &&
2331− nla_get_u32(info->attrs[NL80211_ATTR_CENTER_FREQ2]))
2367+ if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
2368+ nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) {
2369+ NL_SET_ERR_MSG_ATTR(extack,
2370+ attrs[NL80211_ATTR_CENTER_FREQ2],
2371+ "center frequency 2 can't be used");
23322372 return -EINVAL;
2373+ }
23332374 break;
23342375 default:
2376+ NL_SET_ERR_MSG_ATTR(extack,
2377+ attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
2378+ "invalid channel type");
23352379 return -EINVAL;
23362380 }
2337− } else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
2381+ } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
23382382 chandef->width =
2339− nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
2340− if (info->attrs[NL80211_ATTR_CENTER_FREQ1])
2383+ nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
2384+ if (attrs[NL80211_ATTR_CENTER_FREQ1])
23412385 chandef->center_freq1 =
2342− nla_get_u32(
2343− info->attrs[NL80211_ATTR_CENTER_FREQ1]);
2344− if (info->attrs[NL80211_ATTR_CENTER_FREQ2])
2386+ nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
2387+ if (attrs[NL80211_ATTR_CENTER_FREQ2])
23452388 chandef->center_freq2 =
2346− nla_get_u32(
2347− info->attrs[NL80211_ATTR_CENTER_FREQ2]);
2389+ nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
23482390 }
23492391
2350− if (!cfg80211_chandef_valid(chandef))
2392+ if (!cfg80211_chandef_valid(chandef)) {
2393+ NL_SET_ERR_MSG(extack, "invalid channel definition");
23512394 return -EINVAL;
2395+ }
23522396
23532397 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
2354− IEEE80211_CHAN_DISABLED))
2398+ IEEE80211_CHAN_DISABLED)) {
2399+ NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
23552400 return -EINVAL;
2401+ }
23562402
23572403 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
23582404 chandef->width == NL80211_CHAN_WIDTH_10) &&
2359− !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ))
2405+ !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) {
2406+ NL_SET_ERR_MSG(extack, "5/10 MHz not supported");
23602407 return -EINVAL;
2408+ }
23612409
23622410 return 0;
23632411 }
@@ -2617,8 +2665,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) · 253 unmodified lines
26172665 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
26182666 retry_short = nla_get_u8(
26192667 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
2620− if (retry_short == 0)
2621− return -EINVAL;
26222668
26232669 changed |= WIPHY_PARAM_RETRY_SHORT;
26242670 }
@@ -2626,8 +2672,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line
26262672 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
26272673 retry_long = nla_get_u8(
26282674 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
2629− if (retry_long == 0)
2630− return -EINVAL;
26312675
26322676 changed |= WIPHY_PARAM_RETRY_LONG;
26332677 }
@@ -3119,8 +3163,6 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) · 485 unmodified lines
31193163 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
31203164 if (otype != ntype)
31213165 change = true;
3122− if (ntype > NL80211_IFTYPE_MAX)
3123− return -EINVAL;
31243166 }
31253167
31263168 if (info->attrs[NL80211_ATTR_MESH_ID]) {
@@ -3185,11 +3227,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) · 58 unmodified lines
31853227 if (!info->attrs[NL80211_ATTR_IFNAME])
31863228 return -EINVAL;
31873229
3188− if (info->attrs[NL80211_ATTR_IFTYPE]) {
3230+ if (info->attrs[NL80211_ATTR_IFTYPE])
31893231 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
3190− if (type > NL80211_IFTYPE_MAX)
3191− return -EINVAL;
3192− }
31933232
31943233 if (!rdev->ops->add_virtual_intf ||
31953234 !(rdev->wiphy.interface_modes & (1 << type)))
@@ -3252,15 +3291,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) · 56 unmodified lines
32523291 * P2P Device and NAN do not have a netdev, so don't go
32533292 * through the netdev notifier and must be added here
32543293 */
3255− mutex_init(&wdev->mtx);
3256− INIT_LIST_HEAD(&wdev->event_list);
3257− spin_lock_init(&wdev->event_lock);
3258− INIT_LIST_HEAD(&wdev->mgmt_registrations);
3259− spin_lock_init(&wdev->mgmt_registrations_lock);
3260−
3261− wdev->identifier = ++rdev->wdev_id;
3262− list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
3263− rdev->devlist_generation++;
3294+ cfg80211_init_wdev(rdev, wdev);
32643295 break;
32653296 default:
32663297 break;
@@ -3272,15 +3303,6 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) · 5 unmodified lines
32723303 return -ENOBUFS;
32733304 }
32743305
3275− /*
3276− * For wdevs which have no associated netdev object (e.g. of type
3277− * NL80211_IFTYPE_P2P_DEVICE), emit the NEW_INTERFACE event here.
3278− * For all other types, the event will be generated from the
3279− * netdev notifier
3280− */
3281− if (!wdev->netdev)
3282− nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
3283−
32843306 return genlmsg_reply(msg, info);
32853307 }
32863308
@@ -3359,7 +3381,7 @@ static void get_key_callback(void *c, struct key_params *params) · 72 unmodified lines
33593381 params->cipher)))
33603382 goto nla_put_failure;
33613383
3362− if (nla_put_u8(cookie->msg, NL80211_ATTR_KEY_IDX, cookie->idx))
3384+ if (nla_put_u8(cookie->msg, NL80211_KEY_IDX, cookie->idx))
33633385 goto nla_put_failure;
33643386
33653387 nla_nest_end(cookie->msg, key);
@@ -3386,9 +3408,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) · 20 unmodified lines
33863408 if (info->attrs[NL80211_ATTR_KEY_IDX])
33873409 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
33883410
3389− if (key_idx > 5)
3390− return -EINVAL;
3391−
33923411 if (info->attrs[NL80211_ATTR_MAC])
33933412 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
33943413
@@ -3396,8 +3415,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line
33963415 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
33973416 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
33983417
3399− if (kt >= NUM_NL80211_KEYTYPES)
3400− return -EINVAL;
34013418 if (kt != NL80211_KEYTYPE_GROUP &&
34023419 kt != NL80211_KEYTYPE_PAIRWISE)
34033420 return -EINVAL;
@@ -3998,16 +4015,12 @@ static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev, · 594 unmodified lines
39984015 return 0;
39994016 }
40004017
4001−static int nl80211_parse_beacon(struct nlattr *attrs[],
4018+static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
4019+ struct nlattr *attrs[],
40024020 struct cfg80211_beacon_data *bcn)
40034021 {
40044022 bool haveinfo = false;
4005−
4006− if (!is_valid_ie_attr(attrs[NL80211_ATTR_BEACON_TAIL]) ||
4007− !is_valid_ie_attr(attrs[NL80211_ATTR_IE]) ||
4008− !is_valid_ie_attr(attrs[NL80211_ATTR_IE_PROBE_RESP]) ||
4009− !is_valid_ie_attr(attrs[NL80211_ATTR_IE_ASSOC_RESP]))
4010− return -EINVAL;
4023+ int err;
40114024
40124025 memset(bcn, 0, sizeof(*bcn));
40134026
@@ -4052,6 +4065,35 @@ static int nl80211_parse_beacon(struct nlattr *attrs[], · 38 unmodified lines
40524065 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
40534066 }
40544067
4068+ if (attrs[NL80211_ATTR_FTM_RESPONDER]) {
4069+ struct nlattr *tb[NL80211_FTM_RESP_ATTR_MAX + 1];
4070+
4071+ err = nla_parse_nested(tb, NL80211_FTM_RESP_ATTR_MAX,
4072+ attrs[NL80211_ATTR_FTM_RESPONDER],
4073+ NULL, NULL);
4074+ if (err)
4075+ return err;
4076+
4077+ if (tb[NL80211_FTM_RESP_ATTR_ENABLED] &&
4078+ wiphy_ext_feature_isset(&rdev->wiphy,
4079+ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
4080+ bcn->ftm_responder = 1;
4081+ else
4082+ return -EOPNOTSUPP;
4083+
4084+ if (tb[NL80211_FTM_RESP_ATTR_LCI]) {
4085+ bcn->lci = nla_data(tb[NL80211_FTM_RESP_ATTR_LCI]);
4086+ bcn->lci_len = nla_len(tb[NL80211_FTM_RESP_ATTR_LCI]);
4087+ }
4088+
4089+ if (tb[NL80211_FTM_RESP_ATTR_CIVICLOC]) {
4090+ bcn->civicloc = nla_data(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
4091+ bcn->civicloc_len = nla_len(tb[NL80211_FTM_RESP_ATTR_CIVICLOC]);
4092+ }
4093+ } else {
4094+ bcn->ftm_responder = -1;
4095+ }
4096+
40554097 return 0;
40564098 }
40574099
@@ -4198,7 +4240,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 140 unmodified lines
41984240 !info->attrs[NL80211_ATTR_BEACON_HEAD])
41994241 return -EINVAL;
42004242
4201− err = nl80211_parse_beacon(info->attrs, &params.beacon);
4243+ err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon);
42024244 if (err)
42034245 return err;
42044246
@@ -4228,14 +4270,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 23 unmodified lines
42284270 return -EINVAL;
42294271 }
42304272
4231− if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) {
4273+ if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
42324274 params.hidden_ssid = nla_get_u32(
42334275 info->attrs[NL80211_ATTR_HIDDEN_SSID]);
4234− if (params.hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE &&
4235− params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_LEN &&
4236− params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_CONTENTS)
4237− return -EINVAL;
4238− }
42394276
42404277 params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
42414278
@@ -4265,8 +4302,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 23 unmodified lines
42654302 return -EINVAL;
42664303 params.p2p_ctwindow =
42674304 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
4268− if (params.p2p_ctwindow > 127)
4269− return -EINVAL;
42704305 if (params.p2p_ctwindow != 0 &&
42714306 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
42724307 return -EINVAL;
@@ -4278,8 +4313,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 5 unmodified lines
42784313 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
42794314 return -EINVAL;
42804315 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
4281− if (tmp > 1)
4282− return -EINVAL;
42834316 params.p2p_opp_ps = tmp;
42844317 if (params.p2p_opp_ps != 0 &&
42854318 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
@@ -4382,7 +4415,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) · 96 unmodified lines
43824415 if (!wdev->beacon_interval)
43834416 return -EINVAL;
43844417
4385− err = nl80211_parse_beacon(info->attrs, &params);
4418+ err = nl80211_parse_beacon(rdev, info->attrs, &params);
43864419 if (err)
43874420 return err;
43884421
@@ -4728,6 +4761,8 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, · 339 unmodified lines
47284761 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
47294762 PUT_SINFO_U64(BEACON_RX, rx_beacon);
47304763 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
4764+ PUT_SINFO(RX_MPDUS, rx_mpdu_count, u32);
4765+ PUT_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
47314766 if (wiphy_ext_feature_isset(&rdev->wiphy,
47324767 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
47334768 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
@@ -4811,7 +4846,7 @@ static int nl80211_dump_station(struct sk_buff *skb, · 77 unmodified lines
48114846 int err;
48124847
48134848 rtnl_lock();
4814− err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
4849+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
48154850 if (err)
48164851 goto out_err;
48174852
@@ -5216,17 +5251,11 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 398 unmodified lines
52165251 else
52175252 params.listen_interval = -1;
52185253
5219− if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
5220− u8 tmp;
5221−
5222− tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
5223− if (tmp >= NUM_NL80211_P2P_PS_STATUS)
5224− return -EINVAL;
5225−
5226− params.support_p2p_ps = tmp;
5227− } else {
5254+ if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
5255+ params.support_p2p_ps =
5256+ nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
5257+ else
52285258 params.support_p2p_ps = -1;
5229− }
52305259
52315260 if (!info->attrs[NL80211_ATTR_MAC])
52325261 return -EINVAL;
@@ -5256,38 +5285,23 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 23 unmodified lines
52565285 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
52575286 return -EINVAL;
52585287
5259− if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
5288+ if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
52605289 params.plink_action =
52615290 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
5262− if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
5263− return -EINVAL;
5264− }
52655291
52665292 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
52675293 params.plink_state =
52685294 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
5269− if (params.plink_state >= NUM_NL80211_PLINK_STATES)
5270− return -EINVAL;
5271− if (info->attrs[NL80211_ATTR_MESH_PEER_AID]) {
5295+ if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
52725296 params.peer_aid = nla_get_u16(
52735297 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
5274− if (params.peer_aid > IEEE80211_MAX_AID)
5275− return -EINVAL;
5276− }
52775298 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
52785299 }
52795300
5280− if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) {
5281− enum nl80211_mesh_power_mode pm = nla_get_u32(
5301+ if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
5302+ params.local_pm = nla_get_u32(
52825303 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
52835304
5284− if (pm <= NL80211_MESH_POWER_UNKNOWN ||
5285− pm > NL80211_MESH_POWER_MAX)
5286− return -EINVAL;
5287−
5288− params.local_pm = pm;
5289− }
5290−
52915305 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
52925306 params.opmode_notif_used = true;
52935307 params.opmode_notif =
@@ -5364,13 +5378,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 70 unmodified lines
53645378 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
53655379
53665380 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
5367− u8 tmp;
5368−
5369− tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
5370− if (tmp >= NUM_NL80211_P2P_PS_STATUS)
5371− return -EINVAL;
5372−
5373− params.support_p2p_ps = tmp;
5381+ params.support_p2p_ps =
5382+ nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
53745383 } else {
53755384 /*
53765385 * if not specified, assume it's supported for P2P GO interface,
@@ -5384,8 +5393,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 7 unmodified lines
53845393 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
53855394 else
53865395 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
5387− if (!params.aid || params.aid > IEEE80211_MAX_AID)
5388− return -EINVAL;
53895396
53905397 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
53915398 params.capability =
@@ -5425,12 +5432,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 33 unmodified lines
54255432 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
54265433 }
54275434
5428− if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {
5435+ if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
54295436 params.plink_action =
54305437 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
5431− if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
5432− return -EINVAL;
5433− }
54345438
54355439 err = nl80211_parse_sta_channel_info(info, &params);
54365440 if (err)
@@ -5662,7 +5666,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, · 225 unmodified lines
56625666 int err;
56635667
56645668 rtnl_lock();
5665− err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
5669+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
56665670 if (err)
56675671 goto out_err;
56685672
@@ -5858,7 +5862,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb, · 189 unmodified lines
58585862 int err;
58595863
58605864 rtnl_lock();
5861− err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
5865+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
58625866 if (err)
58635867 goto out_err;
58645868
@@ -5940,9 +5944,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) · 75 unmodified lines
59405944 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
59415945 return -EINVAL;
59425946 params.p2p_ctwindow =
5943− nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
5944− if (params.p2p_ctwindow < 0)
5945− return -EINVAL;
5947+ nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
59465948 if (params.p2p_ctwindow != 0 &&
59475949 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
59485950 return -EINVAL;
@@ -5954,8 +5956,6 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) · 5 unmodified lines
59545956 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
59555957 return -EINVAL;
59565958 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
5957− if (tmp > 1)
5958− return -EINVAL;
59595959 params.p2p_opp_ps = tmp;
59605960 if (params.p2p_opp_ps &&
59615961 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
@@ -6134,33 +6134,49 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, · 172 unmodified lines
61346134 return -ENOBUFS;
61356135 }
61366136
6137−static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
6138− [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 },
6139− [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 },
6140− [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 },
6141− [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 },
6142− [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 },
6143− [NL80211_MESHCONF_TTL] = { .type = NLA_U8 },
6144− [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 },
6145− [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },
6146− [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 },
6137+static const struct nla_policy
6138+nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
6139+ [NL80211_MESHCONF_RETRY_TIMEOUT] =
6140+ NLA_POLICY_RANGE(NLA_U16, 1, 255),
6141+ [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
6142+ NLA_POLICY_RANGE(NLA_U16, 1, 255),
6143+ [NL80211_MESHCONF_HOLDING_TIMEOUT] =
6144+ NLA_POLICY_RANGE(NLA_U16, 1, 255),
6145+ [NL80211_MESHCONF_MAX_PEER_LINKS] =
6146+ NLA_POLICY_RANGE(NLA_U16, 0, 255),
6147+ [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16),
6148+ [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
6149+ [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
6150+ [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1),
6151+ [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] =
6152+ NLA_POLICY_RANGE(NLA_U32, 1, 255),
61476153 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
61486154 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
6149− [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 },
6155+ [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = NLA_POLICY_MIN(NLA_U16, 1),
61506156 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
6151− [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
6152− [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 },
6153− [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
6154− [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 },
6155− [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
6156− [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
6157− [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
6158− [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32 },
6157+ [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
6158+ NLA_POLICY_MIN(NLA_U16, 1),
6159+ [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
6160+ NLA_POLICY_MIN(NLA_U16, 1),
6161+ [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
6162+ NLA_POLICY_MIN(NLA_U16, 1),
6163+ [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
6164+ [NL80211_MESHCONF_HWMP_RANN_INTERVAL] =
6165+ NLA_POLICY_MIN(NLA_U16, 1),
6166+ [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1),
6167+ [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1),
6168+ [NL80211_MESHCONF_RSSI_THRESHOLD] =
6169+ NLA_POLICY_RANGE(NLA_S32, -255, 0),
61596170 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
61606171 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
6161− [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 },
6162− [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 },
6163− [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 },
6172+ [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
6173+ NLA_POLICY_MIN(NLA_U16, 1),
6174+ [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] =
6175+ NLA_POLICY_MIN(NLA_U16, 1),
6176+ [NL80211_MESHCONF_POWER_MODE] =
6177+ NLA_POLICY_RANGE(NLA_U32,
6178+ NL80211_MESH_POWER_ACTIVE,
6179+ NL80211_MESH_POWER_MAX),
61646180 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
61656181 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
61666182 };
@@ -6173,68 +6189,12 @@ static const struct nla_policy · 6 unmodified lines
61736189 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
61746190 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
61756191 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
6176− [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
6177− .len = IEEE80211_MAX_DATA_LEN },
6192+ [NL80211_MESH_SETUP_IE] =
6193+ NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
6194+ IEEE80211_MAX_DATA_LEN),
61786195 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
61796196 };
61806197
6181−static int nl80211_check_bool(const struct nlattr *nla, u8 min, u8 max, bool *out)
6182−{
6183− u8 val = nla_get_u8(nla);
6184− if (val < min || val > max)
6185− return -EINVAL;
6186− *out = val;
6187− return 0;
6188−}
6189−
6190−static int nl80211_check_u8(const struct nlattr *nla, u8 min, u8 max, u8 *out)
6191−{
6192− u8 val = nla_get_u8(nla);
6193− if (val < min || val > max)
6194− return -EINVAL;
6195− *out = val;
6196− return 0;
6197−}
6198−
6199−static int nl80211_check_u16(const struct nlattr *nla, u16 min, u16 max, u16 *out)
6200−{
6201− u16 val = nla_get_u16(nla);
6202− if (val < min || val > max)
6203− return -EINVAL;
6204− *out = val;
6205− return 0;
6206−}
6207−
6208−static int nl80211_check_u32(const struct nlattr *nla, u32 min, u32 max, u32 *out)
6209−{
6210− u32 val = nla_get_u32(nla);
6211− if (val < min || val > max)
6212− return -EINVAL;
6213− *out = val;
6214− return 0;
6215−}
6216−
6217−static int nl80211_check_s32(const struct nlattr *nla, s32 min, s32 max, s32 *out)
6218−{
6219− s32 val = nla_get_s32(nla);
6220− if (val < min || val > max)
6221− return -EINVAL;
6222− *out = val;
6223− return 0;
6224−}
6225−
6226−static int nl80211_check_power_mode(const struct nlattr *nla,
6227− enum nl80211_mesh_power_mode min,
6228− enum nl80211_mesh_power_mode max,
6229− enum nl80211_mesh_power_mode *out)
6230−{
6231− u32 val = nla_get_u32(nla);
6232− if (val < min || val > max)
6233− return -EINVAL;
6234− *out = val;
6235− return 0;
6236−}
6237−
62386198 static int nl80211_parse_mesh_config(struct genl_info *info,
62396199 struct mesh_config *cfg,
62406200 u32 *mask_out)
@@ -6243,13 +6203,12 @@ static int nl80211_parse_mesh_config(struct genl_info *info, · 2 unmodified lines
62436203 u32 mask = 0;
62446204 u16 ht_opmode;
62456205
6246−#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \
6247−do { \
6248− if (tb[attr]) { \
6249− if (fn(tb[attr], min, max, &cfg->param)) \
6250− return -EINVAL; \
6251− mask |= (1 << (attr - 1)); \
6252− } \
6206+#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
6207+do { \
6208+ if (tb[attr]) { \
6209+ cfg->param = fn(tb[attr]); \
6210+ mask |= BIT((attr) - 1); \
6211+ } \
62536212 } while (0)
62546213
62556214 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
@@ -6264,75 +6223,73 @@ do { \ · 8 unmodified lines
62646223 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
62656224
62666225 /* Fill in the params struct */
6267− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255,
6268− mask, NL80211_MESHCONF_RETRY_TIMEOUT,
6269− nl80211_check_u16);
6270− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255,
6271− mask, NL80211_MESHCONF_CONFIRM_TIMEOUT,
6272− nl80211_check_u16);
6273− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255,
6274− mask, NL80211_MESHCONF_HOLDING_TIMEOUT,
6275− nl80211_check_u16);
6276− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255,
6277− mask, NL80211_MESHCONF_MAX_PEER_LINKS,
6278− nl80211_check_u16);
6279− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16,
6280− mask, NL80211_MESHCONF_MAX_RETRIES,
6281− nl80211_check_u8);
6282− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255,
6283− mask, NL80211_MESHCONF_TTL, nl80211_check_u8);
6284− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255,
6285− mask, NL80211_MESHCONF_ELEMENT_TTL,
6286− nl80211_check_u8);
6287− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1,
6288− mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
6289− nl80211_check_bool);
6226+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
6227+ NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
6228+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
6229+ NL80211_MESHCONF_CONFIRM_TIMEOUT,
6230+ nla_get_u16);
6231+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
6232+ NL80211_MESHCONF_HOLDING_TIMEOUT,
6233+ nla_get_u16);
6234+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
6235+ NL80211_MESHCONF_MAX_PEER_LINKS,
6236+ nla_get_u16);
6237+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
6238+ NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
6239+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
6240+ NL80211_MESHCONF_TTL, nla_get_u8);
6241+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
6242+ NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
6243+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
6244+ NL80211_MESHCONF_AUTO_OPEN_PLINKS,
6245+ nla_get_u8);
62906246 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
6291− 1, 255, mask,
6247+ mask,
62926248 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
6293− nl80211_check_u32);
6294− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255,
6295− mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
6296− nl80211_check_u8);
6297− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535,
6298− mask, NL80211_MESHCONF_PATH_REFRESH_TIME,
6299− nl80211_check_u32);
6300− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535,
6301− mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
6302− nl80211_check_u16);
6249+ nla_get_u32);
6250+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
6251+ NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
6252+ nla_get_u8);
6253+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
6254+ NL80211_MESHCONF_PATH_REFRESH_TIME,
6255+ nla_get_u32);
6256+ if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
6257+ (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
6258+ return -EINVAL;
6259+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask,
6260+ NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
6261+ nla_get_u16);
63036262 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
6304− 1, 65535, mask,
6263+ mask,
63056264 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
6306− nl80211_check_u32);
6307− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
6308− 1, 65535, mask,
6265+ nla_get_u32);
6266+ if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
6267+ (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
6268+ cfg->dot11MeshHWMPactivePathTimeout > 65535))
6269+ return -EINVAL;
6270+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
63096271 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
6310− nl80211_check_u16);
6311− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,
6312− 1, 65535, mask,
6272+ nla_get_u16);
6273+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
63136274 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
6314− nl80211_check_u16);
6275+ nla_get_u16);
63156276 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
6316− dot11MeshHWMPnetDiameterTraversalTime,
6317− 1, 65535, mask,
6277+ dot11MeshHWMPnetDiameterTraversalTime, mask,
63186278 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
6319− nl80211_check_u16);
6320− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4,
6321− mask, NL80211_MESHCONF_HWMP_ROOTMODE,
6322− nl80211_check_u8);
6323− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535,
6324− mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
6325− nl80211_check_u16);
6326− FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
6327− dot11MeshGateAnnouncementProtocol, 0, 1,
6279+ nla_get_u16);
6280+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
6281+ NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
6282+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
6283+ NL80211_MESHCONF_HWMP_RANN_INTERVAL,
6284+ nla_get_u16);
6285+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
63286286 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
6329− nl80211_check_bool);
6330− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
6331− mask, NL80211_MESHCONF_FORWARDING,
6332− nl80211_check_bool);
6333− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
6334− mask, NL80211_MESHCONF_RSSI_THRESHOLD,
6335− nl80211_check_s32);
6287+ nla_get_u8);
6288+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
6289+ NL80211_MESHCONF_FORWARDING, nla_get_u8);
6290+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
6291+ NL80211_MESHCONF_RSSI_THRESHOLD,
6292+ nla_get_s32);
63366293 /*
63376294 * Check HT operation mode based on
63386295 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
@@ -6351,29 +6308,27 @@ do { \ · 12 unmodified lines
63516308 cfg->ht_opmode = ht_opmode;
63526309 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
63536310 }
6354− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
6355− 1, 65535, mask,
6356− NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
6357− nl80211_check_u32);
6358− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535,
6359− mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
6360− nl80211_check_u16);
63616311 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
6362− dot11MeshHWMPconfirmationInterval,
6363− 1, 65535, mask,
6312+ dot11MeshHWMPactivePathToRootTimeout, mask,
6313+ NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
6314+ nla_get_u32);
6315+ if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) &&
6316+ (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 ||
6317+ cfg->dot11MeshHWMPactivePathToRootTimeout > 65535))
6318+ return -EINVAL;
6319+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask,
6320+ NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
6321+ nla_get_u16);
6322+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval,
6323+ mask,
63646324 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
6365− nl80211_check_u16);
6366− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode,
6367− NL80211_MESH_POWER_ACTIVE,
6368− NL80211_MESH_POWER_MAX,
6369− mask, NL80211_MESHCONF_POWER_MODE,
6370− nl80211_check_power_mode);
6371− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
6372− 0, 65535, mask,
6373− NL80211_MESHCONF_AWAKE_WINDOW, nl80211_check_u16);
6374− FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff,
6375− mask, NL80211_MESHCONF_PLINK_TIMEOUT,
6376− nl80211_check_u32);
6325+ nla_get_u16);
6326+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
6327+ NL80211_MESHCONF_POWER_MODE, nla_get_u32);
6328+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
6329+ NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
6330+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
6331+ NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
63776332 if (mask_out)
63786333 *mask_out = mask;
63796334
@@ -6416,8 +6371,6 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, · 36 unmodified lines
64166371 if (tb[NL80211_MESH_SETUP_IE]) {
64176372 struct nlattr *ieattr =
64186373 tb[NL80211_MESH_SETUP_IE];
6419− if (!is_valid_ie_attr(ieattr))
6420− return -EINVAL;
64216374 setup->ie = nla_data(ieattr);
64226375 setup->ie_len = nla_len(ieattr);
64236376 }
@@ -7050,9 +7003,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) · 626 unmodified lines
70507003 int err, tmp, n_ssids = 0, n_channels, i;
70517004 size_t ie_len;
70527005
7053− if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
7054− return -EINVAL;
7055−
70567006 wiphy = &rdev->wiphy;
70577007
70587008 if (wdev->iftype == NL80211_IFTYPE_NAN)
@@ -7406,9 +7356,6 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, · 347 unmodified lines
74067356 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
74077357 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
74087358
7409− if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
7410− return ERR_PTR(-EINVAL);
7411−
74127359 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
74137360 n_channels = validate_scan_freqs(
74147361 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
@@ -7768,7 +7715,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, · 353 unmodified lines
77687715 */
77697716 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1) {
77707717 while (!sched_scan_req->reqid)
7771− sched_scan_req->reqid = rdev->wiphy.cookie_counter++;
7718+ sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
77727719 }
77737720
77747721 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
@@ -7944,7 +7891,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) · 169 unmodified lines
79447891 if (!need_new_beacon)
79457892 goto skip_beacons;
79467893
7947− err = nl80211_parse_beacon(info->attrs, &params.beacon_after);
7894+ err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
79487895 if (err)
79497896 return err;
79507897
@@ -7954,7 +7901,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) · 3 unmodified lines
79547901 if (err)
79557902 return err;
79567903
7957− err = nl80211_parse_beacon(csa_attrs, &params.beacon_csa);
7904+ err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa);
79587905 if (err)
79597906 return err;
79607907
@@ -8191,7 +8138,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) · 230 unmodified lines
81918138 int err;
81928139
81938140 rtnl_lock();
8194− err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
8141+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
81958142 if (err) {
81968143 rtnl_unlock();
81978144 return err;
@@ -8312,7 +8259,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) · 114 unmodified lines
83128259 bool radio_stats;
83138260
83148261 rtnl_lock();
8315− res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
8262+ res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
83168263 if (res)
83178264 goto out_err;
83188265
@@ -8376,9 +8323,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) · 57 unmodified lines
83768323 struct key_parse key;
83778324 bool local_state_change;
83788325
8379− if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8380− return -EINVAL;
8381−
83828326 if (!info->attrs[NL80211_ATTR_MAC])
83838327 return -EINVAL;
83848328
@@ -8617,9 +8561,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) · 232 unmodified lines
86178561 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
86188562 return -EPERM;
86198563
8620− if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8621− return -EINVAL;
8622−
86238564 if (!info->attrs[NL80211_ATTR_MAC] ||
86248565 !info->attrs[NL80211_ATTR_SSID] ||
86258566 !info->attrs[NL80211_ATTR_WIPHY_FREQ])
@@ -8743,9 +8684,6 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) · 117 unmodified lines
87438684 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
87448685 return -EPERM;
87458686
8746− if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8747− return -EINVAL;
8748−
87498687 if (!info->attrs[NL80211_ATTR_MAC])
87508688 return -EINVAL;
87518689
@@ -8794,9 +8732,6 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) · 42 unmodified lines
87948732 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
87958733 return -EPERM;
87968734
8797− if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8798− return -EINVAL;
8799−
88008735 if (!info->attrs[NL80211_ATTR_MAC])
88018736 return -EINVAL;
88028737
@@ -8871,9 +8806,6 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) · 68 unmodified lines
88718806
88728807 memset(&ibss, 0, sizeof(ibss));
88738808
8874− if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8875− return -EINVAL;
8876−
88778809 if (!info->attrs[NL80211_ATTR_SSID] ||
88788810 !nla_len(info->attrs[NL80211_ATTR_SSID]))
88798811 return -EINVAL;
@@ -9311,9 +9243,6 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) · 431 unmodified lines
93119243
93129244 memset(&connect, 0, sizeof(connect));
93139245
9314− if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
9315− return -EINVAL;
9316−
93179246 if (!info->attrs[NL80211_ATTR_SSID] ||
93189247 !nla_len(info->attrs[NL80211_ATTR_SSID]))
93199248 return -EINVAL;
@@ -9372,11 +9301,6 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) · 52 unmodified lines
93729301 !wiphy_ext_feature_isset(&rdev->wiphy,
93739302 NL80211_EXT_FEATURE_MFP_OPTIONAL))
93749303 return -EOPNOTSUPP;
9375−
9376− if (connect.mfp != NL80211_MFP_REQUIRED &&
9377− connect.mfp != NL80211_MFP_NO &&
9378− connect.mfp != NL80211_MFP_OPTIONAL)
9379− return -EINVAL;
93809304 } else {
93819305 connect.mfp = NL80211_MFP_NO;
93829306 }
@@ -9549,8 +9473,6 @@ static int nl80211_update_connect_params(struct sk_buff *skb, · 166 unmodified lines
95499473 return -EOPNOTSUPP;
95509474
95519475 if (info->attrs[NL80211_ATTR_IE]) {
9552− if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
9553− return -EINVAL;
95549476 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
95559477 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
95569478 changed |= UPDATE_ASSOC_IES;
@@ -10135,9 +10057,6 @@ static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) · 578 unmodified lines
1013510057
1013610058 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
1013710059
10138− if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED)
10139− return -EINVAL;
10140−
1014110060 wdev = dev->ieee80211_ptr;
1014210061
1014310062 if (!rdev->ops->set_power_mgmt)
@@ -10700,8 +10619,7 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg, · 556 unmodified lines
1070010619 if (!scan_plan)
1070110620 return -ENOBUFS;
1070210621
10703− if (!scan_plan ||
10704− nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
10622+ if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
1070510623 req->scan_plans[i].interval) ||
1070610624 (req->scan_plans[i].iterations &&
1070710625 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
@@ -11299,9 +11217,6 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev, · 591 unmodified lines
1129911217 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
1130011218 new_rule->condition =
1130111219 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);
11302− if (new_rule->condition != NL80211_COALESCE_CONDITION_MATCH &&
11303− new_rule->condition != NL80211_COALESCE_CONDITION_NO_MATCH)
11304− return -EINVAL;
1130511220
1130611221 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
1130711222 return -EINVAL;
@@ -11654,8 +11569,6 @@ static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info) · 346 unmodified lines
1165411569
1165511570 conf.master_pref =
1165611571 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
11657− if (!conf.master_pref)
11658− return -EINVAL;
1165911572
1166011573 if (info->attrs[NL80211_ATTR_BANDS]) {
1166111574 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);
@@ -11773,7 +11686,7 @@ static int nl80211_nan_add_func(struct sk_buff *skb, · 111 unmodified lines
1177311686 if (!func)
1177411687 return -ENOMEM;
1177511688
11776− func->cookie = wdev->wiphy->cookie_counter++;
11689+ func->cookie = cfg80211_assign_cookie(rdev);
1177711690
1177811691 if (!tb[NL80211_NAN_FUNC_TYPE] ||
1177911692 nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]) > NL80211_NAN_FUNC_MAX_TYPE) {
@@ -12219,8 +12132,7 @@ static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info) · 439 unmodified lines
1221912132 return -EOPNOTSUPP;
1222012133
1222112134 if (!info->attrs[NL80211_ATTR_MDID] ||
12222− !info->attrs[NL80211_ATTR_IE] ||
12223− !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
12135+ !info->attrs[NL80211_ATTR_IE])
1222412136 return -EINVAL;
1222512137
1222612138 memset(&ft_params, 0, sizeof(ft_params));
@@ -12640,12 +12552,7 @@ static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info) · 413 unmodified lines
1264012552 return -EINVAL;
1264112553
1264212554 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
12643− if (tsid >= IEEE80211_NUM_TIDS)
12644− return -EINVAL;
12645−
1264612555 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
12647− if (up >= IEEE80211_NUM_UPS)
12648− return -EINVAL;
1264912556
1265012557 /* WMM uses TIDs 0-7 even for TSPEC */
1265112558 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
@@ -13003,6 +12910,76 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info) · 351 unmodified lines
1300312910 return err;
1300412911 }
1300512912
12913+static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
12914+ struct genl_info *info)
12915+{
12916+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
12917+ struct net_device *dev = info->user_ptr[1];
12918+ struct wireless_dev *wdev = dev->ieee80211_ptr;
12919+ struct cfg80211_ftm_responder_stats ftm_stats = {};
12920+ struct sk_buff *msg;
12921+ void *hdr;
12922+ struct nlattr *ftm_stats_attr;
12923+ int err;
12924+
12925+ if (wdev->iftype != NL80211_IFTYPE_AP || !wdev->beacon_interval)
12926+ return -EOPNOTSUPP;
12927+
12928+ err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats);
12929+ if (err)
12930+ return err;
12931+
12932+ if (!ftm_stats.filled)
12933+ return -ENODATA;
12934+
12935+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12936+ if (!msg)
12937+ return -ENOMEM;
12938+
12939+ hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
12940+ NL80211_CMD_GET_FTM_RESPONDER_STATS);
12941+ if (!hdr)
12942+ return -ENOBUFS;
12943+
12944+ if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
12945+ goto nla_put_failure;
12946+
12947+ ftm_stats_attr = nla_nest_start(msg, NL80211_ATTR_FTM_RESPONDER_STATS);
12948+ if (!ftm_stats_attr)
12949+ goto nla_put_failure;
12950+
12951+#define SET_FTM(field, name, type) \
12952+ do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
12953+ nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \
12954+ ftm_stats.field)) \
12955+ goto nla_put_failure; } while (0)
12956+#define SET_FTM_U64(field, name) \
12957+ do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \
12958+ nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \
12959+ ftm_stats.field, NL80211_FTM_STATS_PAD)) \
12960+ goto nla_put_failure; } while (0)
12961+
12962+ SET_FTM(success_num, SUCCESS_NUM, u32);
12963+ SET_FTM(partial_num, PARTIAL_NUM, u32);
12964+ SET_FTM(failed_num, FAILED_NUM, u32);
12965+ SET_FTM(asap_num, ASAP_NUM, u32);
12966+ SET_FTM(non_asap_num, NON_ASAP_NUM, u32);
12967+ SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC);
12968+ SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32);
12969+ SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32);
12970+ SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32);
12971+#undef SET_FTM
12972+
12973+ nla_nest_end(msg, ftm_stats_attr);
12974+
12975+ genlmsg_end(msg, hdr);
12976+ return genlmsg_reply(msg, info);
12977+
12978+nla_put_failure:
12979+ nlmsg_free(msg);
12980+ return -ENOBUFS;
12981+}
12982+
1300612983 #define NL80211_FLAG_NEED_WIPHY 0x01
1300712984 #define NL80211_FLAG_NEED_NETDEV 0x02
1300812985 #define NL80211_FLAG_NEED_RTNL 0x04
@@ -13914,6 +13891,13 @@ static const struct genl_ops nl80211_ops[] = { · 905 unmodified lines
1391413891 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
1391513892 NL80211_FLAG_NEED_RTNL,
1391613893 },
13894+ {
13895+ .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS,
13896+ .doit = nl80211_get_ftm_responder_stats,
13897+ .policy = nl80211_policy,
13898+ .internal_flags = NL80211_FLAG_NEED_NETDEV |
13899+ NL80211_FLAG_NEED_RTNL,
13900+ },
1391713901 };
1391813902
1391913903 static struct genl_family nl80211_fam __ro_after_init = {
net/wireless/rdev-ops.h+15−0
@@ -1232,4 +1232,19 @@ rdev_external_auth(struct cfg80211_registered_device *rdev, · 1231 unmodified lines
12321232 return ret;
12331233 }
12341234
1235+static inline int
1236+rdev_get_ftm_responder_stats(struct cfg80211_registered_device *rdev,
1237+ struct net_device *dev,
1238+ struct cfg80211_ftm_responder_stats *ftm_stats)
1239+{
1240+ int ret = -EOPNOTSUPP;
1241+
1242+ trace_rdev_get_ftm_responder_stats(&rdev->wiphy, dev, ftm_stats);
1243+ if (rdev->ops->get_ftm_responder_stats)
1244+ ret = rdev->ops->get_ftm_responder_stats(&rdev->wiphy, dev,
1245+ ftm_stats);
1246+ trace_rdev_return_int(&rdev->wiphy, ret);
1247+ return ret;
1248+}
1249+
12351250 #endif /* __CFG80211_RDEV_OPS */
net/wireless/reg.c+9−0
@@ -3831,6 +3831,15 @@ static int __init regulatory_init_db(void) · 3830 unmodified lines
38313831 {
38323832 int err;
38333833
3834+ /*
3835+ * It's possible that - due to other bugs/issues - cfg80211
3836+ * never called regulatory_init() below, or that it failed;
3837+ * in that case, don't try to do any further work here as
3838+ * it's doomed to lead to crashes.
3839+ */
3840+ if (IS_ERR_OR_NULL(reg_pdev))
3841+ return -EINVAL;
3842+
38343843 err = load_builtin_regdb_keys();
38353844 if (err)
38363845 return err;
net/wireless/trace.h+134−99
@@ -2368,6 +2368,140 @@ TRACE_EVENT(rdev_external_auth, · 2367 unmodified lines
23682368 __entry->bssid, __entry->ssid, __entry->status)
23692369 );
23702370
2371+TRACE_EVENT(rdev_start_radar_detection,
2372+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
2373+ struct cfg80211_chan_def *chandef,
2374+ u32 cac_time_ms),
2375+ TP_ARGS(wiphy, netdev, chandef, cac_time_ms),
2376+ TP_STRUCT__entry(
2377+ WIPHY_ENTRY
2378+ NETDEV_ENTRY
2379+ CHAN_DEF_ENTRY
2380+ __field(u32, cac_time_ms)
2381+ ),
2382+ TP_fast_assign(
2383+ WIPHY_ASSIGN;
2384+ NETDEV_ASSIGN;
2385+ CHAN_DEF_ASSIGN(chandef);
2386+ __entry->cac_time_ms = cac_time_ms;
2387+ ),
2388+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
2389+ ", cac_time_ms=%u",
2390+ WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
2391+ __entry->cac_time_ms)
2392+);
2393+
2394+TRACE_EVENT(rdev_set_mcast_rate,
2395+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
2396+ int *mcast_rate),
2397+ TP_ARGS(wiphy, netdev, mcast_rate),
2398+ TP_STRUCT__entry(
2399+ WIPHY_ENTRY
2400+ NETDEV_ENTRY
2401+ __array(int, mcast_rate, NUM_NL80211_BANDS)
2402+ ),
2403+ TP_fast_assign(
2404+ WIPHY_ASSIGN;
2405+ NETDEV_ASSIGN;
2406+ memcpy(__entry->mcast_rate, mcast_rate,
2407+ sizeof(int) * NUM_NL80211_BANDS);
2408+ ),
2409+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", "
2410+ "mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 60GHz=0x%x]",
2411+ WIPHY_PR_ARG, NETDEV_PR_ARG,
2412+ __entry->mcast_rate[NL80211_BAND_2GHZ],
2413+ __entry->mcast_rate[NL80211_BAND_5GHZ],
2414+ __entry->mcast_rate[NL80211_BAND_60GHZ])
2415+);
2416+
2417+TRACE_EVENT(rdev_set_coalesce,
2418+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_coalesce *coalesce),
2419+ TP_ARGS(wiphy, coalesce),
2420+ TP_STRUCT__entry(
2421+ WIPHY_ENTRY
2422+ __field(int, n_rules)
2423+ ),
2424+ TP_fast_assign(
2425+ WIPHY_ASSIGN;
2426+ __entry->n_rules = coalesce ? coalesce->n_rules : 0;
2427+ ),
2428+ TP_printk(WIPHY_PR_FMT ", n_rules=%d",
2429+ WIPHY_PR_ARG, __entry->n_rules)
2430+);
2431+
2432+DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan,
2433+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
2434+ TP_ARGS(wiphy, wdev)
2435+);
2436+
2437+TRACE_EVENT(rdev_set_multicast_to_unicast,
2438+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
2439+ const bool enabled),
2440+ TP_ARGS(wiphy, netdev, enabled),
2441+ TP_STRUCT__entry(
2442+ WIPHY_ENTRY
2443+ NETDEV_ENTRY
2444+ __field(bool, enabled)
2445+ ),
2446+ TP_fast_assign(
2447+ WIPHY_ASSIGN;
2448+ NETDEV_ASSIGN;
2449+ __entry->enabled = enabled;
2450+ ),
2451+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", unicast: %s",
2452+ WIPHY_PR_ARG, NETDEV_PR_ARG,
2453+ BOOL_TO_STR(__entry->enabled))
2454+);
2455+
2456+DEFINE_EVENT(wiphy_wdev_evt, rdev_get_txq_stats,
2457+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
2458+ TP_ARGS(wiphy, wdev)
2459+);
2460+
2461+TRACE_EVENT(rdev_get_ftm_responder_stats,
2462+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
2463+ struct cfg80211_ftm_responder_stats *ftm_stats),
2464+
2465+ TP_ARGS(wiphy, netdev, ftm_stats),
2466+
2467+ TP_STRUCT__entry(
2468+ WIPHY_ENTRY
2469+ NETDEV_ENTRY
2470+ __field(u64, timestamp)
2471+ __field(u32, success_num)
2472+ __field(u32, partial_num)
2473+ __field(u32, failed_num)
2474+ __field(u32, asap_num)
2475+ __field(u32, non_asap_num)
2476+ __field(u64, duration)
2477+ __field(u32, unknown_triggers)
2478+ __field(u32, reschedule)
2479+ __field(u32, out_of_window)
2480+ ),
2481+
2482+ TP_fast_assign(
2483+ WIPHY_ASSIGN;
2484+ NETDEV_ASSIGN;
2485+ __entry->success_num = ftm_stats->success_num;
2486+ __entry->partial_num = ftm_stats->partial_num;
2487+ __entry->failed_num = ftm_stats->failed_num;
2488+ __entry->asap_num = ftm_stats->asap_num;
2489+ __entry->non_asap_num = ftm_stats->non_asap_num;
2490+ __entry->duration = ftm_stats->total_duration_ms;
2491+ __entry->unknown_triggers = ftm_stats->unknown_triggers_num;
2492+ __entry->reschedule = ftm_stats->reschedule_requests_num;
2493+ __entry->out_of_window = ftm_stats->out_of_window_triggers_num;
2494+ ),
2495+
2496+ TP_printk(WIPHY_PR_FMT "Ftm responder stats: success %u, partial %u, "
2497+ "failed %u, asap %u, non asap %u, total duration %llu, unknown "
2498+ "triggers %u, rescheduled %u, out of window %u", WIPHY_PR_ARG,
2499+ __entry->success_num, __entry->partial_num, __entry->failed_num,
2500+ __entry->asap_num, __entry->non_asap_num, __entry->duration,
2501+ __entry->unknown_triggers, __entry->reschedule,
2502+ __entry->out_of_window)
2503+);
2504+
23712505 /*************************************************************
23722506 * cfg80211 exported functions traces *
23732507 *************************************************************/
@@ -3160,105 +3294,6 @@ TRACE_EVENT(cfg80211_stop_iface, · 786 unmodified lines
31603294 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
31613295 WIPHY_PR_ARG, WDEV_PR_ARG)
31623296 );
3163−
3164−TRACE_EVENT(rdev_start_radar_detection,
3165− TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
3166− struct cfg80211_chan_def *chandef,
3167− u32 cac_time_ms),
3168− TP_ARGS(wiphy, netdev, chandef, cac_time_ms),
3169− TP_STRUCT__entry(
3170− WIPHY_ENTRY
3171− NETDEV_ENTRY
3172− CHAN_DEF_ENTRY
3173− __field(u32, cac_time_ms)
3174− ),
3175− TP_fast_assign(
3176− WIPHY_ASSIGN;
3177− NETDEV_ASSIGN;
3178− CHAN_DEF_ASSIGN(chandef);
3179− __entry->cac_time_ms = cac_time_ms;
3180− ),
3181− TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
3182− ", cac_time_ms=%u",
3183− WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
3184− __entry->cac_time_ms)
3185−);
3186−
3187−TRACE_EVENT(rdev_set_mcast_rate,
3188− TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
3189− int *mcast_rate),
3190− TP_ARGS(wiphy, netdev, mcast_rate),
3191− TP_STRUCT__entry(
3192− WIPHY_ENTRY
3193− NETDEV_ENTRY
3194− __array(int, mcast_rate, NUM_NL80211_BANDS)
3195− ),
3196− TP_fast_assign(
3197− WIPHY_ASSIGN;
3198− NETDEV_ASSIGN;
3199− memcpy(__entry->mcast_rate, mcast_rate,
3200− sizeof(int) * NUM_NL80211_BANDS);
3201− ),
3202− TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", "
3203− "mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 60GHz=0x%x]",
3204− WIPHY_PR_ARG, NETDEV_PR_ARG,
3205− __entry->mcast_rate[NL80211_BAND_2GHZ],
3206− __entry->mcast_rate[NL80211_BAND_5GHZ],
3207− __entry->mcast_rate[NL80211_BAND_60GHZ])
3208−);
3209−
3210−TRACE_EVENT(rdev_set_coalesce,
3211− TP_PROTO(struct wiphy *wiphy, struct cfg80211_coalesce *coalesce),
3212− TP_ARGS(wiphy, coalesce),
3213− TP_STRUCT__entry(
3214− WIPHY_ENTRY
3215− __field(int, n_rules)
3216− ),
3217− TP_fast_assign(
3218− WIPHY_ASSIGN;
3219− __entry->n_rules = coalesce ? coalesce->n_rules : 0;
3220− ),
3221− TP_printk(WIPHY_PR_FMT ", n_rules=%d",
3222− WIPHY_PR_ARG, __entry->n_rules)
3223−);
3224−
3225−DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan,
3226− TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
3227− TP_ARGS(wiphy, wdev)
3228−);
3229−
3230−TRACE_EVENT(rdev_set_multicast_to_unicast,
3231− TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
3232− const bool enabled),
3233− TP_ARGS(wiphy, netdev, enabled),
3234− TP_STRUCT__entry(
3235− WIPHY_ENTRY
3236− NETDEV_ENTRY
3237− __field(bool, enabled)
3238− ),
3239− TP_fast_assign(
3240− WIPHY_ASSIGN;
3241− NETDEV_ASSIGN;
3242− __entry->enabled = enabled;
3243− ),
3244− TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", unicast: %s",
3245− WIPHY_PR_ARG, NETDEV_PR_ARG,
3246− BOOL_TO_STR(__entry->enabled))
3247−);
3248−
3249−TRACE_EVENT(rdev_get_txq_stats,
3250− TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
3251− TP_ARGS(wiphy, wdev),
3252− TP_STRUCT__entry(
3253− WIPHY_ENTRY
3254− WDEV_ENTRY
3255− ),
3256− TP_fast_assign(
3257− WIPHY_ASSIGN;
3258− WDEV_ASSIGN;
3259− ),
3260− TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
3261−);
32623297 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
32633298
32643299 #undef TRACE_INCLUDE_PATH