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
495 495
496static spinlock_t hwsim_radio_lock;496static spinlock_t hwsim_radio_lock;
497static LIST_HEAD(hwsim_radios);497static LIST_HEAD(hwsim_radios);
498static struct workqueue_struct *hwsim_wq;
499static struct rhashtable hwsim_radios_rht;498static struct rhashtable hwsim_radios_rht;
500static int hwsim_radio_idx;499static int hwsim_radio_idx;
501static int hwsim_radios_generation = 1;500static int hwsim_radios_generation = 1;
@@ -3692,13 +3691,9 @@ static int __init init_mac80211_hwsim(void) · 3190 unmodified lines
3692 3691
3693 spin_lock_init(&hwsim_radio_lock);3692 spin_lock_init(&hwsim_radio_lock);
3694 3693
3695 hwsim_wq = alloc_workqueue("hwsim_wq", 0, 0);
3696 if (!hwsim_wq)
3697 return -ENOMEM;
3698
3699 err = rhashtable_init(&hwsim_radios_rht, &hwsim_rht_params);3694 err = rhashtable_init(&hwsim_radios_rht, &hwsim_rht_params);
3700 if (err)3695 if (err)
3701 goto out_free_wq;3696 return err;
3702 3697
3703 err = register_pernet_device(&hwsim_net_ops);3698 err = register_pernet_device(&hwsim_net_ops);
3704 if (err)3699 if (err)
@@ -3829,8 +3824,6 @@ out_unregister_pernet: · 124 unmodified lines
3829 unregister_pernet_device(&hwsim_net_ops);3824 unregister_pernet_device(&hwsim_net_ops);
3830out_free_rht:3825out_free_rht:
3831 rhashtable_destroy(&hwsim_radios_rht);3826 rhashtable_destroy(&hwsim_radios_rht);
3832out_free_wq:
3833 destroy_workqueue(hwsim_wq);
3834 return err;3827 return err;
3835}3828}
3836module_init(init_mac80211_hwsim);3829module_init(init_mac80211_hwsim);
@@ -3842,12 +3835,10 @@ static void __exit exit_mac80211_hwsim(void) · 5 unmodified lines
3842 hwsim_exit_netlink();3835 hwsim_exit_netlink();
3843 3836
3844 mac80211_hwsim_free();3837 mac80211_hwsim_free();
3845 flush_workqueue(hwsim_wq);
3846 3838
3847 rhashtable_destroy(&hwsim_radios_rht);3839 rhashtable_destroy(&hwsim_radios_rht);
3848 unregister_netdev(hwsim_mon);3840 unregister_netdev(hwsim_mon);
3849 platform_driver_unregister(&mac80211_hwsim_driver);3841 platform_driver_unregister(&mac80211_hwsim_driver);
3850 unregister_pernet_device(&hwsim_net_ops);3842 unregister_pernet_device(&hwsim_net_ops);
3851 destroy_workqueue(hwsim_wq);
3852}3843}
3853module_exit(exit_mac80211_hwsim);3844module_exit(exit_mac80211_hwsim);
include/linux/ieee80211.h+1−0
@@ -1670,6 +1670,7 @@ struct ieee80211_mu_edca_param_set { · 1669 unmodified lines
1670#define IEEE80211_VHT_CAP_RXSTBC_3 0x000003001670#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
1671#define IEEE80211_VHT_CAP_RXSTBC_4 0x000004001671#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
1672#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x000007001672#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700
1673#define IEEE80211_VHT_CAP_RXSTBC_SHIFT 8
1673#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x000008001674#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
1674#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x000010001675#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
1675#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 131676#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
775 * @assocresp_ies_len: length of assocresp_ies in octets775 * @assocresp_ies_len: length of assocresp_ies in octets
776 * @probe_resp_len: length of probe response template (@probe_resp)776 * @probe_resp_len: length of probe response template (@probe_resp)
777 * @probe_resp: probe response template (AP mode only)777 * @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
778 */784 */
779struct cfg80211_beacon_data {785struct cfg80211_beacon_data {
780 const u8 *head, *tail;786 const u8 *head, *tail;
@@ -782,12 +788,17 @@ struct cfg80211_beacon_data { · 1 unmodified line
782 const u8 *proberesp_ies;788 const u8 *proberesp_ies;
783 const u8 *assocresp_ies;789 const u8 *assocresp_ies;
784 const u8 *probe_resp;790 const u8 *probe_resp;
791 const u8 *lci;
792 const u8 *civicloc;
793 s8 ftm_responder;
785 794
786 size_t head_len, tail_len;795 size_t head_len, tail_len;
787 size_t beacon_ies_len;796 size_t beacon_ies_len;
788 size_t proberesp_ies_len;797 size_t proberesp_ies_len;
789 size_t assocresp_ies_len;798 size_t assocresp_ies_len;
790 size_t probe_resp_len;799 size_t probe_resp_len;
800 size_t lci_len;
801 size_t civicloc_len;
791};802};
792 803
793struct mac_address {804struct mac_address {
@@ -1292,6 +1303,10 @@ struct cfg80211_tid_stats { · 498 unmodified lines
1292 * @ack_signal: signal strength (in dBm) of the last ACK frame.1303 * @ack_signal: signal strength (in dBm) of the last ACK frame.
1293 * @avg_ack_signal: average rssi value of ack packet for the no of msdu's has1304 * @avg_ack_signal: average rssi value of ack packet for the no of msdu's has
1294 * been sent.1305 * 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.
1295 */1310 */
1296struct station_info {1311struct station_info {
1297 u64 filled;1312 u64 filled;
@@ -1338,6 +1353,9 @@ struct station_info { · 40 unmodified lines
1338 struct cfg80211_tid_stats *pertid;1353 struct cfg80211_tid_stats *pertid;
1339 s8 ack_signal;1354 s8 ack_signal;
1340 s8 avg_ack_signal;1355 s8 avg_ack_signal;
1356
1357 u32 rx_mpdu_count;
1358 u32 fcs_err_count;
1341};1359};
1342 1360
1343#if IS_ENABLED(CONFIG_CFG80211)1361#if IS_ENABLED(CONFIG_CFG80211)
@@ -2796,6 +2814,40 @@ struct cfg80211_external_auth_params { · 1452 unmodified lines
2796 u16 status;2814 u16 status;
2797};2815};
2798 2816
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 */
2838struct 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
2799/**2851/**
2800 * struct cfg80211_ops - backend description for wireless configuration2852 * struct cfg80211_ops - backend description for wireless configuration
2801 *2853 *
@@ -3128,6 +3180,9 @@ struct cfg80211_external_auth_params { · 326 unmodified lines
3128 *3180 *
3129 * @tx_control_port: TX a control port frame (EAPoL). The noencrypt parameter3181 * @tx_control_port: TX a control port frame (EAPoL). The noencrypt parameter
3130 * tells the driver that the frame should not be encrypted.3182 * 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.
3131 */3186 */
3132struct cfg80211_ops {3187struct cfg80211_ops {
3133 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);3188 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3433,6 +3488,10 @@ struct cfg80211_ops { · 299 unmodified lines
3433 const u8 *buf, size_t len,3488 const u8 *buf, size_t len,
3434 const u8 *dest, const __be16 proto,3489 const u8 *dest, const __be16 proto,
3435 const bool noencrypt);3490 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);
3436};3495};
3437 3496
3438/*3497/*
@@ -3960,7 +4019,6 @@ struct wiphy_iftype_ext_capab { · 521 unmodified lines
3960 * by the driver in the .connect() callback. The bit position maps to the4019 * by the driver in the .connect() callback. The bit position maps to the
3961 * attribute indices defined in &enum nl80211_bss_select_attr.4020 * attribute indices defined in &enum nl80211_bss_select_attr.
3962 *4021 *
3963 * @cookie_counter: unique generic cookie counter, used to identify objects.
3964 * @nan_supported_bands: bands supported by the device in NAN mode, a4022 * @nan_supported_bands: bands supported by the device in NAN mode, a
3965 * bitmap of &enum nl80211_band values. For instance, for4023 * bitmap of &enum nl80211_band values. For instance, for
3966 * NL80211_BAND_2GHZ, bit 0 would be set4024 * NL80211_BAND_2GHZ, bit 0 would be set
@@ -4099,8 +4157,6 @@ struct wiphy { · 132 unmodified lines
4099 4157
4100 u32 bss_select_support;4158 u32 bss_select_support;
4101 4159
4102 u64 cookie_counter;
4103
4104 u8 nan_supported_bands;4160 u8 nan_supported_bands;
4105 4161
4106 u32 txq_limit;4162 u32 txq_limit;
include/net/mac80211.h+43−0
@@ -309,6 +309,8 @@ struct ieee80211_vif_chanctx_switch { · 308 unmodified lines
309 * @BSS_CHANGED_KEEP_ALIVE: keep alive options (idle period or protected309 * @BSS_CHANGED_KEEP_ALIVE: keep alive options (idle period or protected
310 * keep alive) changed.310 * keep alive) changed.
311 * @BSS_CHANGED_MCAST_RATE: Multicast Rate setting changed for this interface311 * @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).
312 *314 *
313 */315 */
314enum ieee80211_bss_change {316enum ieee80211_bss_change {
@@ -338,6 +340,7 @@ enum ieee80211_bss_change { · 23 unmodified lines
338 BSS_CHANGED_MU_GROUPS = 1<<23,340 BSS_CHANGED_MU_GROUPS = 1<<23,
339 BSS_CHANGED_KEEP_ALIVE = 1<<24,341 BSS_CHANGED_KEEP_ALIVE = 1<<24,
340 BSS_CHANGED_MCAST_RATE = 1<<25,342 BSS_CHANGED_MCAST_RATE = 1<<25,
343 BSS_CHANGED_FTM_RESPONDER = 1<<26,
341 344
342 /* when adding here, make sure to change ieee80211_reconfig */345 /* when adding here, make sure to change ieee80211_reconfig */
343};346};
@@ -463,6 +466,21 @@ struct ieee80211_mu_group_data { · 119 unmodified lines
463 u8 position[WLAN_USER_POSITION_LEN];466 u8 position[WLAN_USER_POSITION_LEN];
464};467};
465 468
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 */
477struct ieee80211_ftm_responder_params {
478 const u8 *lci;
479 const u8 *civicloc;
480 size_t lci_len;
481 size_t civicloc_len;
482};
483
466/**484/**
467 * struct ieee80211_bss_conf - holds the BSS's changing parameters485 * struct ieee80211_bss_conf - holds the BSS's changing parameters
468 *486 *
@@ -562,6 +580,9 @@ struct ieee80211_mu_group_data { · 93 unmodified lines
562 * @protected_keep_alive: if set, indicates that the station should send an RSN580 * @protected_keep_alive: if set, indicates that the station should send an RSN
563 * protected frame to the AP to reset the idle timer at the AP for the581 * protected frame to the AP to reset the idle timer at the AP for the
564 * station.582 * 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.
565 */586 */
566struct ieee80211_bss_conf {587struct ieee80211_bss_conf {
567 const u8 *bssid;588 const u8 *bssid;
@@ -612,6 +633,8 @@ struct ieee80211_bss_conf { · 44 unmodified lines
612 bool allow_p2p_go_ps;633 bool allow_p2p_go_ps;
613 u16 max_idle_period;634 u16 max_idle_period;
614 bool protected_keep_alive;635 bool protected_keep_alive;
636 bool ftm_responder;
637 struct ieee80211_ftm_responder_params *ftmr_params;
615};638};
616 639
617/**640/**
@@ -3598,6 +3621,8 @@ enum ieee80211_reconfig_type { · 2980 unmodified lines
3598 * aggregating two specific frames in the same A-MSDU. The relation3621 * aggregating two specific frames in the same A-MSDU. The relation
3599 * between the skbs should be symmetric and transitive. Note that while3622 * between the skbs should be symmetric and transitive. Note that while
3600 * skb is always a real frame, head may or may not be an A-MSDU.3623 * 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.
3601 */3626 */
3602struct ieee80211_ops {3627struct ieee80211_ops {
3603 void (*tx)(struct ieee80211_hw *hw,3628 void (*tx)(struct ieee80211_hw *hw,
@@ -3883,6 +3908,9 @@ struct ieee80211_ops { · 279 unmodified lines
3883 bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *hw,3908 bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *hw,
3884 struct sk_buff *head,3909 struct sk_buff *head,
3885 struct sk_buff *skb);3910 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);
3886};3914};
3887 3915
3888/**3916/**
@@ -4351,6 +4379,21 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, · 462 unmodified lines
4351void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,4379void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
4352 u32 thr);4380 u32 thr);
4353 4381
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 */
4393void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
4394 struct ieee80211_sta *pubsta,
4395 struct ieee80211_tx_info *info);
4396
4354/**4397/**
4355 * ieee80211_tx_status - transmit status callback4398 * ieee80211_tx_status - transmit status callback
4356 *4399 *
include/uapi/linux/nl80211.h+98−0
@@ -1033,6 +1033,9 @@ · 1032 unmodified lines
1033 * %NL80211_ATTR_CHANNEL_WIDTH,%NL80211_ATTR_NSS attributes with its1033 * %NL80211_ATTR_CHANNEL_WIDTH,%NL80211_ATTR_NSS attributes with its
1034 * address(specified in %NL80211_ATTR_MAC).1034 * address(specified in %NL80211_ATTR_MAC).
1035 *1035 *
1036 * @NL80211_CMD_GET_FTM_RESPONDER_STATS: Retrieve FTM responder statistics, in
1037 * the %NL80211_ATTR_FTM_RESPONDER_STATS attribute.
1038 *
1036 * @NL80211_CMD_MAX: highest used command number1039 * @NL80211_CMD_MAX: highest used command number
1037 * @__NL80211_CMD_AFTER_LAST: internal use1040 * @__NL80211_CMD_AFTER_LAST: internal use
1038 */1041 */
@@ -1245,6 +1248,8 @@ enum nl80211_commands { · 206 unmodified lines
1245 1248
1246 NL80211_CMD_CONTROL_PORT_FRAME,1249 NL80211_CMD_CONTROL_PORT_FRAME,
1247 1250
1251 NL80211_CMD_GET_FTM_RESPONDER_STATS,
1252
1248 /* add new commands above here */1253 /* add new commands above here */
1249 1254
1250 /* used to define NL80211_CMD_MAX below */1255 /* used to define NL80211_CMD_MAX below */
@@ -2241,6 +2246,14 @@ enum nl80211_commands { · 990 unmodified lines
2241 * association request when used with NL80211_CMD_NEW_STATION). Can be set2246 * association request when used with NL80211_CMD_NEW_STATION). Can be set
2242 * only if %NL80211_STA_FLAG_WME is set.2247 * only if %NL80211_STA_FLAG_WME is set.
2243 *2248 *
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 *
2244 * @NUM_NL80211_ATTR: total number of nl80211_attrs available2257 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
2245 * @NL80211_ATTR_MAX: highest attribute number currently defined2258 * @NL80211_ATTR_MAX: highest attribute number currently defined
2246 * @__NL80211_ATTR_AFTER_LAST: internal use2259 * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2682,6 +2695,10 @@ enum nl80211_attrs { · 435 unmodified lines
2682 2695
2683 NL80211_ATTR_HE_CAPABILITY,2696 NL80211_ATTR_HE_CAPABILITY,
2684 2697
2698 NL80211_ATTR_FTM_RESPONDER,
2699
2700 NL80211_ATTR_FTM_RESPONDER_STATS,
2701
2685 /* add attributes here, update the policy in nl80211.c */2702 /* add attributes here, update the policy in nl80211.c */
2686 2703
2687 __NL80211_ATTR_AFTER_LAST,2704 __NL80211_ATTR_AFTER_LAST,
@@ -3051,6 +3068,12 @@ enum nl80211_sta_bss_param { · 363 unmodified lines
3051 * @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment3068 * @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment
3052 * @NL80211_STA_INFO_ACK_SIGNAL: signal strength of the last ACK frame(u8, dBm)3069 * @NL80211_STA_INFO_ACK_SIGNAL: signal strength of the last ACK frame(u8, dBm)
3053 * @NL80211_STA_INFO_ACK_SIGNAL_AVG: avg signal strength of ACK frames (s8, dBm)3070 * @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.
3054 * @__NL80211_STA_INFO_AFTER_LAST: internal3077 * @__NL80211_STA_INFO_AFTER_LAST: internal
3055 * @NL80211_STA_INFO_MAX: highest possible station info attribute3078 * @NL80211_STA_INFO_MAX: highest possible station info attribute
3056 */3079 */
@@ -3091,6 +3114,8 @@ enum nl80211_sta_info { · 34 unmodified lines
3091 NL80211_STA_INFO_PAD,3114 NL80211_STA_INFO_PAD,
3092 NL80211_STA_INFO_ACK_SIGNAL,3115 NL80211_STA_INFO_ACK_SIGNAL,
3093 NL80211_STA_INFO_ACK_SIGNAL_AVG,3116 NL80211_STA_INFO_ACK_SIGNAL_AVG,
3117 NL80211_STA_INFO_RX_MPDUS,
3118 NL80211_STA_INFO_FCS_ERROR_COUNT,
3094 3119
3095 /* keep last */3120 /* keep last */
3096 __NL80211_STA_INFO_AFTER_LAST,3121 __NL80211_STA_INFO_AFTER_LAST,
@@ -5225,6 +5250,8 @@ enum nl80211_feature_flags { · 2128 unmodified lines
5225 * @NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT: Driver/device can omit all data5250 * @NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT: Driver/device can omit all data
5226 * except for supported rates from the probe request content if requested5251 * except for supported rates from the probe request content if requested
5227 * by the %NL80211_SCAN_FLAG_MIN_PREQ_CONTENT flag.5252 * 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.
5228 *5255 *
5229 * @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0: Driver/device confirm that they are5256 * @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0: Driver/device confirm that they are
5230 * able to rekey an in-use key correctly. Userspace must not rekey PTK keys5257 * 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
5269 NL80211_EXT_FEATURE_SCAN_RANDOM_SN,5296 NL80211_EXT_FEATURE_SCAN_RANDOM_SN,
5270 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT,5297 NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT,
5271 NL80211_EXT_FEATURE_CAN_REPLACE_PTK0,5298 NL80211_EXT_FEATURE_CAN_REPLACE_PTK0,
5299 NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
5272 5300
5273 /* add new features before the definition below */5301 /* add new features before the definition below */
5274 NUM_NL80211_EXT_FEATURES,5302 NUM_NL80211_EXT_FEATURES,
@@ -5808,4 +5836,74 @@ enum nl80211_external_auth_action { · 533 unmodified lines
5808 NL80211_EXTERNAL_AUTH_ABORT,5836 NL80211_EXTERNAL_AUTH_ABORT,
5809};5837};
5810 5838
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 */
5851enum 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 */
5891enum 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
5811#endif /* __LINUX_NL80211_H */5909#endif /* __LINUX_NL80211_H */
net/mac80211/Kconfig+1−16
@@ -27,20 +27,6 @@ config MAC80211_RC_MINSTREL · 26 unmodified lines
27 ---help---27 ---help---
28 This option enables the 'minstrel' TX rate control algorithm28 This option enables the 'minstrel' TX rate control algorithm
29 29
30config 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
37config 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
44choice30choice
45 prompt "Default rate control algorithm"31 prompt "Default rate control algorithm"
46 depends on MAC80211_HAS_RC32 depends on MAC80211_HAS_RC
@@ -62,8 +48,7 @@ endchoice · 15 unmodified lines
62 48
63config MAC80211_RC_DEFAULT49config MAC80211_RC_DEFAULT
64 string50 string
65 default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT51 default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL
66 default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
67 default ""52 default ""
68 53
69endif54endif
net/mac80211/Makefile+6−5
@@ -53,13 +53,14 @@ mac80211-$(CONFIG_PM) += pm.o · 52 unmodified lines
53 53
54CFLAGS_trace.o := -I$(src)54CFLAGS_trace.o := -I$(src)
55 55
56rc80211_minstrel-y := rc80211_minstrel.o56rc80211_minstrel-y := \
57rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o57 rc80211_minstrel.o \
58 rc80211_minstrel_ht.o
58 59
59rc80211_minstrel_ht-y := rc80211_minstrel_ht.o60rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += \
60rc80211_minstrel_ht-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o61 rc80211_minstrel_debugfs.o \
62 rc80211_minstrel_ht_debugfs.o
61 63
62mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)64mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
63mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y)
64 65
65ccflags-y += -DDEBUG66ccflags-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
790 return 0;790 return 0;
791}791}
792 792
793static 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
793static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,835static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
794 struct cfg80211_beacon_data *params,836 struct cfg80211_beacon_data *params,
795 const struct ieee80211_csa_settings *csa)837 const struct ieee80211_csa_settings *csa)
@@ -863,6 +905,20 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, · 67 unmodified lines
863 if (err == 0)905 if (err == 0)
864 changed |= BSS_CHANGED_AP_PROBE_RESP;906 changed |= BSS_CHANGED_AP_PROBE_RESP;
865 907
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
866 rcu_assign_pointer(sdata->u.ap.beacon, new);922 rcu_assign_pointer(sdata->u.ap.beacon, new);
867 923
868 if (old)924 if (old)
@@ -1063,6 +1119,9 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) · 194 unmodified lines
1063 kfree_rcu(old_probe_resp, rcu_head);1119 kfree_rcu(old_probe_resp, rcu_head);
1064 sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;1120 sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
1065 1121
1122 kfree(sdata->vif.bss_conf.ftmr_params);
1123 sdata->vif.bss_conf.ftmr_params = NULL;
1124
1066 __sta_info_flush(sdata, true);1125 __sta_info_flush(sdata, true);
1067 ieee80211_free_keys(sdata, true);1126 ieee80211_free_keys(sdata, true);
1068 1127
@@ -2875,6 +2934,20 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) · 1806 unmodified lines
2875 memcpy(pos, beacon->probe_resp, beacon->probe_resp_len);2934 memcpy(pos, beacon->probe_resp, beacon->probe_resp_len);
2876 pos += beacon->probe_resp_len;2935 pos += beacon->probe_resp_len;
2877 }2936 }
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 }
2878 2951
2879 return new_beacon;2952 return new_beacon;
2880}2953}
@@ -3765,6 +3838,17 @@ out: · 884 unmodified lines
3765 return ret;3838 return ret;
3766}3839}
3767 3840
3841static int
3842ieee80211_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
3768const struct cfg80211_ops mac80211_config_ops = {3852const struct cfg80211_ops mac80211_config_ops = {
3769 .add_virtual_intf = ieee80211_add_iface,3853 .add_virtual_intf = ieee80211_add_iface,
3770 .del_virtual_intf = ieee80211_del_iface,3854 .del_virtual_intf = ieee80211_del_iface,
@@ -3859,4 +3943,5 @@ const struct cfg80211_ops mac80211_config_ops = { · 88 unmodified lines
3859 .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,3943 .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
3860 .tx_control_port = ieee80211_tx_control_port,3944 .tx_control_port = ieee80211_tx_control_port,
3861 .get_txq_stats = ieee80211_get_txq_stats,3945 .get_txq_stats = ieee80211_get_txq_stats,
3946 .get_ftm_responder_stats = ieee80211_get_ftm_responder_stats,
3862};3947};
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
1183 return local->ops->can_aggregate_in_amsdu(&local->hw, head, skb);1183 return local->ops->can_aggregate_in_amsdu(&local->hw, head, skb);
1184}1184}
1185 1185
1186static inline int
1187drv_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
1186static inline int drv_start_nan(struct ieee80211_local *local,1202static inline int drv_start_nan(struct ieee80211_local *local,
1187 struct ieee80211_sub_if_data *sdata,1203 struct ieee80211_sub_if_data *sdata,
1188 struct cfg80211_nan_conf *conf)1204 struct cfg80211_nan_conf *conf)
net/mac80211/ieee80211_i.h+1−0
@@ -377,6 +377,7 @@ struct ieee80211_mgd_auth_data { · 376 unmodified lines
377 u8 key[WLAN_KEY_LEN_WEP104];377 u8 key[WLAN_KEY_LEN_WEP104];
378 u8 key_len, key_idx;378 u8 key_len, key_idx;
379 bool done;379 bool done;
380 bool peer_confirmed;
380 bool timeout_started;381 bool timeout_started;
381 382
382 u16 sae_trans, sae_status;383 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
1203 continue;1203 continue;
1204 1204
1205 sband = kmemdup(sband, sizeof(*sband), GFP_KERNEL);1205 sband = kmemdup(sband, sizeof(*sband), GFP_KERNEL);
1206 if (!sband)1206 if (!sband) {
1207 result = -ENOMEM;
1207 goto fail_rate;1208 goto fail_rate;
1209 }
1208 1210
1209 wiphy_dbg(hw->wiphy, "copying sband (band %d) due to VHT EXT NSS BW flag\n",1211 wiphy_dbg(hw->wiphy, "copying sband (band %d) due to VHT EXT NSS BW flag\n",
1210 band);1212 band);
@@ -1373,18 +1375,12 @@ static int __init ieee80211_init(void) · 162 unmodified lines
1373 if (ret)1375 if (ret)
1374 return ret;1376 return ret;
1375 1377
1376 ret = rc80211_minstrel_ht_init();
1377 if (ret)
1378 goto err_minstrel;
1379
1380 ret = ieee80211_iface_init();1378 ret = ieee80211_iface_init();
1381 if (ret)1379 if (ret)
1382 goto err_netdev;1380 goto err_netdev;
1383 1381
1384 return 0;1382 return 0;
1385 err_netdev:1383 err_netdev:
1386 rc80211_minstrel_ht_exit();
1387 err_minstrel:
1388 rc80211_minstrel_exit();1384 rc80211_minstrel_exit();
1389 1385
1390 return ret;1386 return ret;
@@ -1392,7 +1388,6 @@ static int __init ieee80211_init(void) · 1 unmodified line
1392 1388
1393static void __exit ieee80211_exit(void)1389static void __exit ieee80211_exit(void)
1394{1390{
1395 rc80211_minstrel_ht_exit();
1396 rc80211_minstrel_exit();1391 rc80211_minstrel_exit();
1397 1392
1398 ieee80211s_stop();1393 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
2761 auth_data->key_idx, tx_flags);2761 auth_data->key_idx, tx_flags);
2762}2762}
2763 2763
2764static 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
2764static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,2792static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
2765 struct ieee80211_mgmt *mgmt, size_t len)2793 struct ieee80211_mgmt *mgmt, size_t len)
2766{2794{
2767 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;2795 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2768 u8 bssid[ETH_ALEN];2796 u8 bssid[ETH_ALEN];
2769 u16 auth_alg, auth_transaction, status_code;2797 u16 auth_alg, auth_transaction, status_code;
2770 struct sta_info *sta;
2771 struct ieee80211_event event = {2798 struct ieee80211_event event = {
2772 .type = MLME_EVENT,2799 .type = MLME_EVENT,
2773 .u.mlme.data = AUTH_EVENT,2800 .u.mlme.data = AUTH_EVENT,
@@ -2791,7 +2818,11 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, · 17 unmodified lines
2791 status_code = le16_to_cpu(mgmt->u.auth.status_code);2818 status_code = le16_to_cpu(mgmt->u.auth.status_code);
2792 2819
2793 if (auth_alg != ifmgd->auth_data->algorithm ||2820 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))) {
2795 sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n",2826 sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n",
2796 mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,2827 mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
2797 auth_transaction,2828 auth_transaction,
@@ -2834,35 +2865,17 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, · 36 unmodified lines
2834 2865
2835 event.u.mlme.status = MLME_SUCCESS;2866 event.u.mlme.status = MLME_SUCCESS;
2836 drv_event_callback(sdata->local, sdata, &event);2867 drv_event_callback(sdata->local, sdata, &event);
2837 sdata_info(sdata, "authenticated\n");2868 if (ifmgd->auth_data->algorithm != WLAN_AUTH_SAE ||
2838 ifmgd->auth_data->done = true;2869 (auth_transaction == 2 &&
2839 ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;2870 ifmgd->auth_data->expected_transaction == 2)) {
2840 ifmgd->auth_data->timeout_started = true;2871 if (!ieee80211_mark_sta_auth(sdata, bssid))
2841 run_again(sdata, ifmgd->auth_data->timeout);2872 goto out_err;
2842 2873 } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
2843 if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&2874 auth_transaction == 2) {
2844 ifmgd->auth_data->expected_transaction != 2) {2875 sdata_info(sdata, "SAE peer confirmed\n");
2845 /*2876 ifmgd->auth_data->peer_confirmed = true;
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;
2851 }2877 }
2852 2878
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
2866 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);2879 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2867 return;2880 return;
2868 out_err:2881 out_err:
@@ -4878,6 +4891,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 2009 unmodified lines
4878 struct ieee80211_mgd_auth_data *auth_data;4891 struct ieee80211_mgd_auth_data *auth_data;
4879 u16 auth_alg;4892 u16 auth_alg;
4880 int err;4893 int err;
4894 bool cont_auth;
4881 4895
4882 /* prepare auth data structure */4896 /* prepare auth data structure */
4883 4897
@@ -4912,6 +4926,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 28 unmodified lines
4912 return -EOPNOTSUPP;4926 return -EOPNOTSUPP;
4913 }4927 }
4914 4928
4929 if (ifmgd->assoc_data)
4930 return -EBUSY;
4931
4915 auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +4932 auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
4916 req->ie_len, GFP_KERNEL);4933 req->ie_len, GFP_KERNEL);
4917 if (!auth_data)4934 if (!auth_data)
@@ -4931,6 +4948,13 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 13 unmodified lines
4931 auth_data->data_len += req->auth_data_len - 4;4948 auth_data->data_len += req->auth_data_len - 4;
4932 }4949 }
4933 4950
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
4934 if (req->ie && req->ie_len) {4958 if (req->ie && req->ie_len) {
4935 memcpy(&auth_data->data[auth_data->data_len],4959 memcpy(&auth_data->data[auth_data->data_len],
4936 req->ie, req->ie_len);4960 req->ie, req->ie_len);
@@ -4947,18 +4971,26 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 10 unmodified lines
4947 4971
4948 /* try to authenticate/probe */4972 /* try to authenticate/probe */
4949 4973
4950 if ((ifmgd->auth_data && !ifmgd->auth_data->done) ||4974 if (ifmgd->auth_data) {
4951 ifmgd->assoc_data) {4975 if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE) {
4952 err = -EBUSY;4976 auth_data->peer_confirmed =
4953 goto err_free;4977 ifmgd->auth_data->peer_confirmed;
4978 }
4979 ieee80211_destroy_auth_data(sdata, cont_auth);
4954 }4980 }
4955 4981
4956 if (ifmgd->auth_data)
4957 ieee80211_destroy_auth_data(sdata, false);
4958
4959 /* prep auth_data so we don't go into idle on disassoc */4982 /* prep auth_data so we don't go into idle on disassoc */
4960 ifmgd->auth_data = auth_data;4983 ifmgd->auth_data = auth_data;
4961 4984
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
4962 if (ifmgd->associated) {4994 if (ifmgd->associated) {
4963 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];4995 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
4964 4996
@@ -4976,7 +5008,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 11 unmodified lines
4976 5008
4977 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);5009 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
4978 5010
4979 err = ieee80211_prep_connection(sdata, req->bss, false, false);5011 err = ieee80211_prep_connection(sdata, req->bss, cont_auth, false);
4980 if (err)5012 if (err)
4981 goto err_clear;5013 goto err_clear;
4982 5014
@@ -4997,7 +5029,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 14 unmodified lines
4997 mutex_lock(&sdata->local->mtx);5029 mutex_lock(&sdata->local->mtx);
4998 ieee80211_vif_release_channel(sdata);5030 ieee80211_vif_release_channel(sdata);
4999 mutex_unlock(&sdata->local->mtx);5031 mutex_unlock(&sdata->local->mtx);
5000 err_free:
5001 kfree(auth_data);5032 kfree(auth_data);
5002 return err;5033 return err;
5003}5034}
net/mac80211/rate.h+0−13
@@ -95,18 +95,5 @@ static inline void rc80211_minstrel_exit(void) · 94 unmodified lines
95}95}
96#endif96#endif
97 97
98#ifdef CONFIG_MAC80211_RC_MINSTREL_HT
99int rc80211_minstrel_ht_init(void);
100void rc80211_minstrel_ht_exit(void);
101#else
102static inline int rc80211_minstrel_ht_init(void)
103{
104 return 0;
105}
106static inline void rc80211_minstrel_ht_exit(void)
107{
108}
109#endif
110
111 98
112#endif /* IEEE80211_RATE_H */99#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
167 if (unlikely(!mrs->att_hist)) {167 if (unlikely(!mrs->att_hist)) {
168 mrs->prob_ewma = cur_prob;168 mrs->prob_ewma = cur_prob;
169 } else {169 } 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
176 /*update exponential weighted moving avarage */170 /*update exponential weighted moving avarage */
177 mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,171 mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
178 cur_prob,172 cur_prob,
@@ -572,141 +566,6 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, · 393 unmodified lines
572 minstrel_update_rates(mp, mi);566 minstrel_update_rates(mp, mi);
573}567}
574 568
575static void *
576minstrel_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
606error1:
607 kfree(mi->r);
608error:
609 kfree(mi);
610 return NULL;
611}
612
613static void
614minstrel_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
623static void
624minstrel_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
654static void *
655minstrel_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
701static void
702minstrel_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
710static u32 minstrel_get_expected_throughput(void *priv_sta)569static u32 minstrel_get_expected_throughput(void *priv_sta)
711{570{
712 struct minstrel_sta_info *mi = priv_sta;571 struct minstrel_sta_info *mi = priv_sta;
@@ -725,29 +584,8 @@ static u32 minstrel_get_expected_throughput(void *priv_sta) · 12 unmodified lines
725}584}
726 585
727const struct rate_control_ops mac80211_minstrel = {586const struct rate_control_ops mac80211_minstrel = {
728 .name = "minstrel",
729 .tx_status_ext = minstrel_tx_status,587 .tx_status_ext = minstrel_tx_status,
730 .get_rate = minstrel_get_rate,588 .get_rate = minstrel_get_rate,
731 .rate_init = minstrel_rate_init,589 .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
740 .get_expected_throughput = minstrel_get_expected_throughput,590 .get_expected_throughput = minstrel_get_expected_throughput,
741};591};
742
743int __init
744rc80211_minstrel_init(void)
745{
746 return ieee80211_rate_control_register(&mac80211_minstrel);
747}
748
749void
750rc80211_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
35 return old + incr;35 return old + incr;
36}36}
37 37
38/*
39 * Perform EWMV (Exponentially Weighted Moving Variance) calculation
40 */
41static inline int
42minstrel_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
51struct minstrel_rate_stats {38struct minstrel_rate_stats {
52 /* current / last sampling period attempts/success counters */39 /* current / last sampling period attempts/success counters */
53 u16 attempts, last_attempts;40 u16 attempts, last_attempts;
@@ -56,11 +43,8 @@ struct minstrel_rate_stats { · 2 unmodified lines
56 /* total attempts/success counters */43 /* total attempts/success counters */
57 u32 att_hist, succ_hist;44 u32 att_hist, succ_hist;
58 45
59 /* statistis of packet delivery probability46 /* prob_ewma - exponential weighted moving average of prob */
60 * prob_ewma - exponential weighted moving average of prob
61 * prob_ewmsd - exp. weighted moving standard deviation of prob */
62 u16 prob_ewma;47 u16 prob_ewma;
63 u16 prob_ewmv;
64 48
65 /* maximum retry counts */49 /* maximum retry counts */
66 u8 retry_count;50 u8 retry_count;
@@ -109,11 +93,6 @@ struct minstrel_sta_info { · 42 unmodified lines
109 93
110 /* sampling table */94 /* sampling table */
111 u8 *sample_table;95 u8 *sample_table;
112
113#ifdef CONFIG_MAC80211_DEBUGFS
114 struct dentry *dbg_stats;
115 struct dentry *dbg_stats_csv;
116#endif
117};96};
118 97
119struct minstrel_priv {98struct minstrel_priv {
@@ -137,7 +116,6 @@ struct minstrel_priv { · 17 unmodified lines
137 * - setting will be applied on next update116 * - setting will be applied on next update
138 */117 */
139 u32 fixed_rate_idx;118 u32 fixed_rate_idx;
140 struct dentry *dbg_fixed_rate;
141#endif119#endif
142};120};
143 121
@@ -146,17 +124,8 @@ struct minstrel_debugfs_info { · 2 unmodified lines
146 char buf[];124 char buf[];
147};125};
148 126
149/* Get EWMSD (Exponentially Weighted Moving Standard Deviation) * 10 */
150static inline int
151minstrel_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
157extern const struct rate_control_ops mac80211_minstrel;127extern const struct rate_control_ops mac80211_minstrel;
158void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);128void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
159void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
160 129
161/* Recalculate success probabilities and counters for a given rate using EWMA */130/* Recalculate success probabilities and counters for a given rate using EWMA */
162void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);131void 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
165/* debugfs */134/* debugfs */
166int minstrel_stats_open(struct inode *inode, struct file *file);135int minstrel_stats_open(struct inode *inode, struct file *file);
167int minstrel_stats_csv_open(struct inode *inode, struct file *file);136int minstrel_stats_csv_open(struct inode *inode, struct file *file);
168ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos);
169int minstrel_stats_release(struct inode *inode, struct file *file);
170 137
171#endif138#endif
net/mac80211/rc80211_minstrel_debugfs.c+4−64
@@ -54,22 +54,6 @@ · 53 unmodified lines
54#include <net/mac80211.h>54#include <net/mac80211.h>
55#include "rc80211_minstrel.h"55#include "rc80211_minstrel.h"
56 56
57ssize_t
58minstrel_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
66int
67minstrel_stats_release(struct inode *inode, struct file *file)
68{
69 kfree(file->private_data);
70 return 0;
71}
72
73int57int
74minstrel_stats_open(struct inode *inode, struct file *file)58minstrel_stats_open(struct inode *inode, struct file *file)
75{59{
@@ -86,14 +70,13 @@ minstrel_stats_open(struct inode *inode, struct file *file) · 10 unmodified lines
86 p = ms->buf;70 p = ms->buf;
87 p += sprintf(p, "\n");71 p += sprintf(p, "\n");
88 p += sprintf(p,72 p += sprintf(p,
89 "best __________rate_________ ________statistics________ ____last_____ ______sum-of________\n");73 "best __________rate_________ ____statistics___ ____last_____ ______sum-of________\n");
90 p += sprintf(p,74 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");
92 76
93 for (i = 0; i < mi->n_rates; i++) {77 for (i = 0; i < mi->n_rates; i++) {
94 struct minstrel_rate *mr = &mi->r[i];78 struct minstrel_rate *mr = &mi->r[i];
95 struct minstrel_rate_stats *mrs = &mi->r[i].stats;79 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
96 unsigned int prob_ewmsd;
97 80
98 *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' ';81 *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' ';
99 *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' ';82 *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' ';
@@ -109,15 +92,13 @@ minstrel_stats_open(struct inode *inode, struct file *file) · 9 unmodified lines
109 tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));92 tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
110 tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);93 tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
111 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);94 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
112 prob_ewmsd = minstrel_get_ewmsd10(mrs);
113 95
114 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"96 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u"
115 " %3u %3u %-3u "97 " %3u %3u %-3u "
116 "%9llu %-9llu\n",98 "%9llu %-9llu\n",
117 tp_max / 10, tp_max % 10,99 tp_max / 10, tp_max % 10,
118 tp_avg / 10, tp_avg % 10,100 tp_avg / 10, tp_avg % 10,
119 eprob / 10, eprob % 10,101 eprob / 10, eprob % 10,
120 prob_ewmsd / 10, prob_ewmsd % 10,
121 mrs->retry_count,102 mrs->retry_count,
122 mrs->last_success,103 mrs->last_success,
123 mrs->last_attempts,104 mrs->last_attempts,
@@ -135,14 +116,6 @@ minstrel_stats_open(struct inode *inode, struct file *file) · 11 unmodified lines
135 return 0;116 return 0;
136}117}
137 118
138static 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
146int119int
147minstrel_stats_csv_open(struct inode *inode, struct file *file)120minstrel_stats_csv_open(struct inode *inode, struct file *file)
148{121{
@@ -161,7 +134,6 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) · 12 unmodified lines
161 for (i = 0; i < mi->n_rates; i++) {134 for (i = 0; i < mi->n_rates; i++) {
162 struct minstrel_rate *mr = &mi->r[i];135 struct minstrel_rate *mr = &mi->r[i];
163 struct minstrel_rate_stats *mrs = &mi->r[i].stats;136 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
164 unsigned int prob_ewmsd;
165 137
166 p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : ""));138 p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : ""));
167 p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : ""));139 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
177 tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));149 tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
178 tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);150 tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
179 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);151 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
180 prob_ewmsd = minstrel_get_ewmsd10(mrs);
181 152
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,"
183 "%llu,%llu,%d,%d\n",154 "%llu,%llu,%d,%d\n",
184 tp_max / 10, tp_max % 10,155 tp_max / 10, tp_max % 10,
185 tp_avg / 10, tp_avg % 10,156 tp_avg / 10, tp_avg % 10,
186 eprob / 10, eprob % 10,157 eprob / 10, eprob % 10,
187 prob_ewmsd / 10, prob_ewmsd % 10,
188 mrs->retry_count,158 mrs->retry_count,
189 mrs->last_success,159 mrs->last_success,
190 mrs->last_attempts,160 mrs->last_attempts,
@@ -200,33 +170,3 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) · 9 unmodified lines
200 170
201 return 0;171 return 0;
202}172}
203
204static 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
212void
213minstrel_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
224void
225minstrel_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
52 _streams - 152 _streams - 1
53 53
54/* MCS rate information for an MCS group */54/* MCS rate information for an MCS group */
55#define MCS_GROUP(_streams, _sgi, _ht40) \55#define MCS_GROUP(_streams, _sgi, _ht40, _s) \
56 [GROUP_IDX(_streams, _sgi, _ht40)] = { \56 [GROUP_IDX(_streams, _sgi, _ht40)] = { \
57 .streams = _streams, \57 .streams = _streams, \
58 .shift = _s, \
58 .flags = \59 .flags = \
59 IEEE80211_TX_RC_MCS | \60 IEEE80211_TX_RC_MCS | \
60 (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \61 (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
61 (_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \62 (_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
62 .duration = { \63 .duration = { \
63 MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26), \64 MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s, \
64 MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52), \65 MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s, \
65 MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78), \66 MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s, \
66 MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104), \67 MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s, \
67 MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156), \68 MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s, \
68 MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208), \69 MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s, \
69 MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234), \70 MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s, \
70 MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) \71 MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s \
71 } \72 } \
72}73}
73 74
@@ -80,9 +81,10 @@ · 6 unmodified lines
80#define BW2VBPS(_bw, r3, r2, r1) \81#define BW2VBPS(_bw, r3, r2, r1) \
81 (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)82 (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
82 83
83#define VHT_GROUP(_streams, _sgi, _bw) \84#define VHT_GROUP(_streams, _sgi, _bw, _s) \
84 [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \85 [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \
85 .streams = _streams, \86 .streams = _streams, \
87 .shift = _s, \
86 .flags = \88 .flags = \
87 IEEE80211_TX_RC_VHT_MCS | \89 IEEE80211_TX_RC_VHT_MCS | \
88 (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \90 (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
@@ -90,25 +92,25 @@ · 1 unmodified line
90 _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \92 _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
91 .duration = { \93 .duration = { \
92 MCS_DURATION(_streams, _sgi, \94 MCS_DURATION(_streams, _sgi, \
93 BW2VBPS(_bw, 117, 54, 26)), \95 BW2VBPS(_bw, 117, 54, 26)) >> _s, \
94 MCS_DURATION(_streams, _sgi, \96 MCS_DURATION(_streams, _sgi, \
95 BW2VBPS(_bw, 234, 108, 52)), \97 BW2VBPS(_bw, 234, 108, 52)) >> _s, \
96 MCS_DURATION(_streams, _sgi, \98 MCS_DURATION(_streams, _sgi, \
97 BW2VBPS(_bw, 351, 162, 78)), \99 BW2VBPS(_bw, 351, 162, 78)) >> _s, \
98 MCS_DURATION(_streams, _sgi, \100 MCS_DURATION(_streams, _sgi, \
99 BW2VBPS(_bw, 468, 216, 104)), \101 BW2VBPS(_bw, 468, 216, 104)) >> _s, \
100 MCS_DURATION(_streams, _sgi, \102 MCS_DURATION(_streams, _sgi, \
101 BW2VBPS(_bw, 702, 324, 156)), \103 BW2VBPS(_bw, 702, 324, 156)) >> _s, \
102 MCS_DURATION(_streams, _sgi, \104 MCS_DURATION(_streams, _sgi, \
103 BW2VBPS(_bw, 936, 432, 208)), \105 BW2VBPS(_bw, 936, 432, 208)) >> _s, \
104 MCS_DURATION(_streams, _sgi, \106 MCS_DURATION(_streams, _sgi, \
105 BW2VBPS(_bw, 1053, 486, 234)), \107 BW2VBPS(_bw, 1053, 486, 234)) >> _s, \
106 MCS_DURATION(_streams, _sgi, \108 MCS_DURATION(_streams, _sgi, \
107 BW2VBPS(_bw, 1170, 540, 260)), \109 BW2VBPS(_bw, 1170, 540, 260)) >> _s, \
108 MCS_DURATION(_streams, _sgi, \110 MCS_DURATION(_streams, _sgi, \
109 BW2VBPS(_bw, 1404, 648, 312)), \111 BW2VBPS(_bw, 1404, 648, 312)) >> _s, \
110 MCS_DURATION(_streams, _sgi, \112 MCS_DURATION(_streams, _sgi, \
111 BW2VBPS(_bw, 1560, 720, 346)) \113 BW2VBPS(_bw, 1560, 720, 346)) >> _s \
112 } \114 } \
113}115}
114 116
@@ -121,28 +123,27 @@ · 6 unmodified lines
121 (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \123 (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \
122 CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE))124 CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE))
123 125
124#define CCK_DURATION_LIST(_short) \126#define CCK_DURATION_LIST(_short, _s) \
125 CCK_ACK_DURATION(10, _short), \127 CCK_ACK_DURATION(10, _short) >> _s, \
126 CCK_ACK_DURATION(20, _short), \128 CCK_ACK_DURATION(20, _short) >> _s, \
127 CCK_ACK_DURATION(55, _short), \129 CCK_ACK_DURATION(55, _short) >> _s, \
128 CCK_ACK_DURATION(110, _short)130 CCK_ACK_DURATION(110, _short) >> _s
129 131
130#define CCK_GROUP \132#define CCK_GROUP(_s) \
131 [MINSTREL_CCK_GROUP] = { \133 [MINSTREL_CCK_GROUP] = { \
132 .streams = 0, \134 .streams = 1, \
133 .flags = 0, \135 .flags = 0, \
136 .shift = _s, \
134 .duration = { \137 .duration = { \
135 CCK_DURATION_LIST(false), \138 CCK_DURATION_LIST(false, _s), \
136 CCK_DURATION_LIST(true) \139 CCK_DURATION_LIST(true, _s) \
137 } \140 } \
138 }141 }
139 142
140#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
141static bool minstrel_vht_only = true;143static bool minstrel_vht_only = true;
142module_param(minstrel_vht_only, bool, 0644);144module_param(minstrel_vht_only, bool, 0644);
143MODULE_PARM_DESC(minstrel_vht_only,145MODULE_PARM_DESC(minstrel_vht_only,
144 "Use only VHT rates when VHT is supported by sta.");146 "Use only VHT rates when VHT is supported by sta.");
145#endif
146 147
147/*148/*
148 * To enable sufficiently targeted rate sampling, MCS rates are divided into149 * To enable sufficiently targeted rate sampling, MCS rates are divided into
@@ -153,49 +154,47 @@ MODULE_PARM_DESC(minstrel_vht_only, · 4 unmodified lines
153 * BW -> SGI -> #streams154 * BW -> SGI -> #streams
154 */155 */
155const struct mcs_group minstrel_mcs_groups[] = {156const struct mcs_group minstrel_mcs_groups[] = {
156 MCS_GROUP(1, 0, BW_20),157 MCS_GROUP(1, 0, BW_20, 5),
157 MCS_GROUP(2, 0, BW_20),158 MCS_GROUP(2, 0, BW_20, 4),
158 MCS_GROUP(3, 0, BW_20),159 MCS_GROUP(3, 0, BW_20, 4),
159 160
160 MCS_GROUP(1, 1, BW_20),161 MCS_GROUP(1, 1, BW_20, 5),
161 MCS_GROUP(2, 1, BW_20),162 MCS_GROUP(2, 1, BW_20, 4),
162 MCS_GROUP(3, 1, BW_20),163 MCS_GROUP(3, 1, BW_20, 4),
163 164
164 MCS_GROUP(1, 0, BW_40),165 MCS_GROUP(1, 0, BW_40, 4),
165 MCS_GROUP(2, 0, BW_40),166 MCS_GROUP(2, 0, BW_40, 4),
166 MCS_GROUP(3, 0, BW_40),167 MCS_GROUP(3, 0, BW_40, 4),
167 168
168 MCS_GROUP(1, 1, BW_40),169 MCS_GROUP(1, 1, BW_40, 4),
169 MCS_GROUP(2, 1, BW_40),170 MCS_GROUP(2, 1, BW_40, 4),
170 MCS_GROUP(3, 1, BW_40),171 MCS_GROUP(3, 1, BW_40, 4),
171 172
172 CCK_GROUP,173 CCK_GROUP(8),
173 174
174#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT175 VHT_GROUP(1, 0, BW_20, 5),
175 VHT_GROUP(1, 0, BW_20),176 VHT_GROUP(2, 0, BW_20, 4),
176 VHT_GROUP(2, 0, BW_20),177 VHT_GROUP(3, 0, BW_20, 4),
177 VHT_GROUP(3, 0, BW_20),
178 178
179 VHT_GROUP(1, 1, BW_20),179 VHT_GROUP(1, 1, BW_20, 5),
180 VHT_GROUP(2, 1, BW_20),180 VHT_GROUP(2, 1, BW_20, 4),
181 VHT_GROUP(3, 1, BW_20),181 VHT_GROUP(3, 1, BW_20, 4),
182 182
183 VHT_GROUP(1, 0, BW_40),183 VHT_GROUP(1, 0, BW_40, 4),
184 VHT_GROUP(2, 0, BW_40),184 VHT_GROUP(2, 0, BW_40, 4),
185 VHT_GROUP(3, 0, BW_40),185 VHT_GROUP(3, 0, BW_40, 4),
186 186
187 VHT_GROUP(1, 1, BW_40),187 VHT_GROUP(1, 1, BW_40, 4),
188 VHT_GROUP(2, 1, BW_40),188 VHT_GROUP(2, 1, BW_40, 4),
189 VHT_GROUP(3, 1, BW_40),189 VHT_GROUP(3, 1, BW_40, 4),
190 190
191 VHT_GROUP(1, 0, BW_80),191 VHT_GROUP(1, 0, BW_80, 4),
192 VHT_GROUP(2, 0, BW_80),192 VHT_GROUP(2, 0, BW_80, 4),
193 VHT_GROUP(3, 0, BW_80),193 VHT_GROUP(3, 0, BW_80, 4),
194 194
195 VHT_GROUP(1, 1, BW_80),195 VHT_GROUP(1, 1, BW_80, 4),
196 VHT_GROUP(2, 1, BW_80),196 VHT_GROUP(2, 1, BW_80, 4),
197 VHT_GROUP(3, 1, BW_80),197 VHT_GROUP(3, 1, BW_80, 4),
198#endif
199};198};
200 199
201static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;200static 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
282 break;281 break;
283 282
284 /* short preamble */283 /* 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))
286 idx += 4;286 idx += 4;
287 }287 }
288 return &mi->groups[group].rates[idx];288 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
311 if (group != MINSTREL_CCK_GROUP)311 if (group != MINSTREL_CCK_GROUP)
312 nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);312 nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
313 313
314 nsecs += minstrel_mcs_groups[group].duration[rate];314 nsecs += minstrel_mcs_groups[group].duration[rate] <<
315 minstrel_mcs_groups[group].shift;
315 316
316 /*317 /*
317 * For the throughput calculation, limit the probability value to 90% to318 * 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
759 minstrel_ht_update_rates(mp, mi);760 minstrel_ht_update_rates(mp, mi);
760}761}
761 762
763static inline int
764minstrel_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
762static void771static void
763minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,772minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
764 int index)773 int index)
765{774{
766 struct minstrel_rate_stats *mrs;775 struct minstrel_rate_stats *mrs;
767 const struct mcs_group *group;
768 unsigned int tx_time, tx_time_rtscts, tx_time_data;776 unsigned int tx_time, tx_time_rtscts, tx_time_data;
769 unsigned int cw = mp->cw_min;777 unsigned int cw = mp->cw_min;
770 unsigned int ctime = 0;778 unsigned int ctime = 0;
@@ -783,8 +791,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, · 12 unmodified lines
783 mrs->retry_count_rtscts = 2;791 mrs->retry_count_rtscts = 2;
784 mrs->retry_updated = true;792 mrs->retry_updated = true;
785 793
786 group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];794 tx_time_data = minstrel_get_duration(index) * ampdu_len / 1000;
787 tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;
788 795
789 /* Contention time for first 2 tries */796 /* Contention time for first 2 tries */
790 ctime = (t_slot * cw) >> 1;797 ctime = (t_slot * cw) >> 1;
@@ -878,20 +885,24 @@ minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi) · 87 unmodified lines
878 int group = mi->max_prob_rate / MCS_GROUP_RATES;885 int group = mi->max_prob_rate / MCS_GROUP_RATES;
879 const struct mcs_group *g = &minstrel_mcs_groups[group];886 const struct mcs_group *g = &minstrel_mcs_groups[group];
880 int rate = mi->max_prob_rate % MCS_GROUP_RATES;887 int rate = mi->max_prob_rate % MCS_GROUP_RATES;
888 unsigned int duration;
881 889
882 /* Disable A-MSDU if max_prob_rate is bad */890 /* Disable A-MSDU if max_prob_rate is bad */
883 if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))891 if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))
884 return 1;892 return 1;
885 893
894 duration = g->duration[rate];
895 duration <<= g->shift;
896
886 /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */897 /* 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))
888 return 500;899 return 500;
889 900
890 /*901 /*
891 * If the rate is slower than single-stream MCS4, limit A-MSDU to usual902 * If the rate is slower than single-stream MCS4, limit A-MSDU to usual
892 * data packet size903 * data packet size
893 */904 */
894 if (g->duration[rate] > MCS_DURATION(1, 0, 104))905 if (duration > MCS_DURATION(1, 0, 104))
895 return 1600;906 return 1600;
896 907
897 /*908 /*
@@ -899,7 +910,7 @@ minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi) · 1 unmodified line
899 * rate success probability is less than 75%, limit A-MSDU to twice the usual910 * rate success probability is less than 75%, limit A-MSDU to twice the usual
900 * data packet size911 * data packet size
901 */912 */
902 if (g->duration[rate] > MCS_DURATION(1, 0, 260) ||913 if (duration > MCS_DURATION(1, 0, 260) ||
903 (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <914 (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <
904 MINSTREL_FRAC(75, 100)))915 MINSTREL_FRAC(75, 100)))
905 return 3200;916 return 3200;
@@ -946,13 +957,6 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) · 40 unmodified lines
946 rate_control_set_rates(mp->hw, mi->sta, rates);957 rate_control_set_rates(mp->hw, mi->sta, rates);
947}958}
948 959
949static inline int
950minstrel_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
956static int960static int
957minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)961minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
958{962{
@@ -1000,10 +1004,13 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) · 41 unmodified lines
1000 return -1;1004 return -1;
1001 1005
1002 /*1006 /*
1003 * Do not sample if the probability is already higher than 95%1007 * Do not sample if the probability is already higher than 95%,
1004 * to avoid wasting airtime.1008 * or if the rate is 3 times slower than the current max probability
1009 * rate, to avoid wasting airtime.
1005 */1010 */
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)
1007 return -1;1014 return -1;
1008 1015
1009 /*1016 /*
@@ -1013,7 +1020,6 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) · 3 unmodified lines
1013 1020
1014 cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 /1021 cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 /
1015 MCS_GROUP_RATES].streams;1022 MCS_GROUP_RATES].streams;
1016 sample_dur = minstrel_get_duration(sample_idx);
1017 if (sample_dur >= minstrel_get_duration(tp_rate2) &&1023 if (sample_dur >= minstrel_get_duration(tp_rate2) &&
1018 (cur_max_tp_streams - 1 <1024 (cur_max_tp_streams - 1 <
1019 minstrel_mcs_groups[sample_group].streams ||1025 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
1077 return;1083 return;
1078 1084
1079 sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];1085 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
1080 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;1092 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
1081 rate->count = 1;1093 rate->count = 1;
1082 1094
1083 if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {1095 if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP]) {
1084 int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);1096 int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
1085 rate->idx = mp->cck_rates[idx];1097 rate->idx = mp->cck_rates[idx];
1086 } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) {1098 } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) {
1087 ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES,1099 ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES,
1088 sample_group->streams);1100 sample_group->streams);
1089 } else {1101 } else {
1090 rate->idx = sample_idx % MCS_GROUP_RATES +1102 rate->idx = sample_idx + (sample_group->streams - 1) * 8;
1091 (sample_group->streams - 1) * 8;
1092 }1103 }
1093 1104
1094 rate->flags = sample_group->flags;1105 rate->flags = sample_group->flags;
@@ -1130,14 +1141,14 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 35 unmodified lines
1130 struct minstrel_ht_sta_priv *msp = priv_sta;1141 struct minstrel_ht_sta_priv *msp = priv_sta;
1131 struct minstrel_ht_sta *mi = &msp->ht;1142 struct minstrel_ht_sta *mi = &msp->ht;
1132 struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;1143 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;
1134 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;1145 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
1135 struct sta_info *sinfo = container_of(sta, struct sta_info, sta);
1136 int use_vht;1146 int use_vht;
1137 int n_supported = 0;1147 int n_supported = 0;
1138 int ack_dur;1148 int ack_dur;
1139 int stbc;1149 int stbc;
1140 int i;1150 int i;
1151 bool ldpc;
1141 1152
1142 /* fall back to the old minstrel for legacy stations */1153 /* fall back to the old minstrel for legacy stations */
1143 if (!sta->ht_cap.ht_supported)1154 if (!sta->ht_cap.ht_supported)
@@ -1145,12 +1156,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 1 unmodified line
1145 1156
1146 BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB);1157 BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB);
1147 1158
1148#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
1149 if (vht_cap->vht_supported)1159 if (vht_cap->vht_supported)
1150 use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0);1160 use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0);
1151 else1161 else
1152#endif1162 use_vht = 0;
1153 use_vht = 0;
1154 1163
1155 msp->is_ht = true;1164 msp->is_ht = true;
1156 memset(mi, 0, sizeof(*mi));1165 memset(mi, 0, sizeof(*mi));
@@ -1175,16 +1184,22 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 18 unmodified lines
1175 }1184 }
1176 mi->sample_tries = 4;1185 mi->sample_tries = 4;
1177 1186
1178 /* TODO tx_flags for vht - ATM the RC API is not fine-grained enough */
1179 if (!use_vht) {1187 if (!use_vht) {
1180 stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>1188 stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >>
1181 IEEE80211_HT_CAP_RX_STBC_SHIFT;1189 IEEE80211_HT_CAP_RX_STBC_SHIFT;
1182 mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
1183 1190
1184 if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)1191 ldpc = ht_cap & IEEE80211_HT_CAP_LDPC_CODING;
1185 mi->tx_flags |= IEEE80211_TX_CTL_LDPC;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;
1186 }1197 }
1187 1198
1199 mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
1200 if (ldpc)
1201 mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
1202
1188 for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {1203 for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
1189 u32 gflags = minstrel_mcs_groups[i].flags;1204 u32 gflags = minstrel_mcs_groups[i].flags;
1190 int bw, nss;1205 int bw, nss;
@@ -1197,10 +1212,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 6 unmodified lines
1197 1212
1198 if (gflags & IEEE80211_TX_RC_SHORT_GI) {1213 if (gflags & IEEE80211_TX_RC_SHORT_GI) {
1199 if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) {1214 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))
1201 continue;1216 continue;
1202 } else {1217 } else {
1203 if (!(sta_cap & IEEE80211_HT_CAP_SGI_20))1218 if (!(ht_cap & IEEE80211_HT_CAP_SGI_20))
1204 continue;1219 continue;
1205 }1220 }
1206 }1221 }
@@ -1217,10 +1232,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 10 unmodified lines
1217 1232
1218 /* HT rate */1233 /* HT rate */
1219 if (gflags & IEEE80211_TX_RC_MCS) {1234 if (gflags & IEEE80211_TX_RC_MCS) {
1220#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
1221 if (use_vht && minstrel_vht_only)1235 if (use_vht && minstrel_vht_only)
1222 continue;1236 continue;
1223#endif1237
1224 mi->supported[i] = mcs->rx_mask[nss - 1];1238 mi->supported[i] = mcs->rx_mask[nss - 1];
1225 if (mi->supported[i])1239 if (mi->supported[i])
1226 n_supported++;1240 n_supported++;
@@ -1258,8 +1272,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 31 unmodified lines
1258 if (!n_supported)1272 if (!n_supported)
1259 goto use_legacy;1273 goto use_legacy;
1260 1274
1261 if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE))1275 mi->supported[MINSTREL_CCK_GROUP] |= mi->cck_supported_short << 4;
1262 mi->cck_supported_short |= mi->cck_supported_short << 4;
1263 1276
1264 /* create an initial rate table with the lowest supported rates */1277 /* create an initial rate table with the lowest supported rates */
1265 minstrel_ht_update_stats(mp, mi);1278 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
1340 kfree(msp);1353 kfree(msp);
1341}1354}
1342 1355
1356static void
1357minstrel_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
1343static void *1387static void *
1344minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)1388minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
1345{1389{
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;
1347}1432}
1348 1433
1349static void1434static void
1350minstrel_ht_free(void *priv)1435minstrel_ht_free(void *priv)
1351{1436{
1352 mac80211_minstrel.free(priv);1437 kfree(priv);
1353}1438}
1354 1439
1355static u32 minstrel_ht_get_expected_throughput(void *priv_sta)1440static 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
1384 .free = minstrel_ht_free,1469 .free = minstrel_ht_free,
1385#ifdef CONFIG_MAC80211_DEBUGFS1470#ifdef CONFIG_MAC80211_DEBUGFS
1386 .add_sta_debugfs = minstrel_ht_add_sta_debugfs,1471 .add_sta_debugfs = minstrel_ht_add_sta_debugfs,
1387 .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
1388#endif1472#endif
1389 .get_expected_throughput = minstrel_ht_get_expected_throughput,1473 .get_expected_throughput = minstrel_ht_get_expected_throughput,
1390};1474};
@@ -1409,14 +1493,14 @@ static void __init init_sample_table(void) · 18 unmodified lines
1409}1493}
1410 1494
1411int __init1495int __init
1412rc80211_minstrel_ht_init(void)1496rc80211_minstrel_init(void)
1413{1497{
1414 init_sample_table();1498 init_sample_table();
1415 return ieee80211_rate_control_register(&mac80211_minstrel_ht);1499 return ieee80211_rate_control_register(&mac80211_minstrel_ht);
1416}1500}
1417 1501
1418void1502void
1419rc80211_minstrel_ht_exit(void)1503rc80211_minstrel_exit(void)
1420{1504{
1421 ieee80211_rate_control_unregister(&mac80211_minstrel_ht);1505 ieee80211_rate_control_unregister(&mac80211_minstrel_ht);
1422}1506}
net/mac80211/rc80211_minstrel_ht.h+4−16
@@ -15,11 +15,7 @@ · 14 unmodified lines
15 */15 */
16#define MINSTREL_MAX_STREAMS 316#define MINSTREL_MAX_STREAMS 3
17#define MINSTREL_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */17#define MINSTREL_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */
18#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
19#define MINSTREL_VHT_STREAM_GROUPS 6 /* BW(=3) * SGI(=2) */18#define MINSTREL_VHT_STREAM_GROUPS 6 /* BW(=3) * SGI(=2) */
20#else
21#define MINSTREL_VHT_STREAM_GROUPS 0
22#endif
23 19
24#define MINSTREL_HT_GROUPS_NB (MINSTREL_MAX_STREAMS * \20#define MINSTREL_HT_GROUPS_NB (MINSTREL_MAX_STREAMS * \
25 MINSTREL_HT_STREAM_GROUPS)21 MINSTREL_HT_STREAM_GROUPS)
@@ -34,16 +30,13 @@ · 8 unmodified lines
34#define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB)30#define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB)
35#define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1)31#define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1)
36 32
37#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT
38#define MCS_GROUP_RATES 1033#define MCS_GROUP_RATES 10
39#else
40#define MCS_GROUP_RATES 8
41#endif
42 34
43struct mcs_group {35struct mcs_group {
44 u32 flags;36 u16 flags;
45 unsigned int streams;37 u8 streams;
46 unsigned int duration[MCS_GROUP_RATES];38 u8 shift;
39 u16 duration[MCS_GROUP_RATES];
47};40};
48 41
49extern const struct mcs_group minstrel_mcs_groups[];42extern const struct mcs_group minstrel_mcs_groups[];
@@ -110,17 +103,12 @@ struct minstrel_ht_sta_priv { · 60 unmodified lines
110 struct minstrel_ht_sta ht;103 struct minstrel_ht_sta ht;
111 struct minstrel_sta_info legacy;104 struct minstrel_sta_info legacy;
112 };105 };
113#ifdef CONFIG_MAC80211_DEBUGFS
114 struct dentry *dbg_stats;
115 struct dentry *dbg_stats_csv;
116#endif
117 void *ratelist;106 void *ratelist;
118 void *sample_table;107 void *sample_table;
119 bool is_ht;108 bool is_ht;
120};109};
121 110
122void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);111void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
123void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
124int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,112int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
125 int prob_ewma);113 int prob_ewma);
126 114
net/mac80211/rc80211_minstrel_ht_debugfs.c+33−25
@@ -15,6 +15,22 @@ · 14 unmodified lines
15#include "rc80211_minstrel.h"15#include "rc80211_minstrel.h"
16#include "rc80211_minstrel_ht.h"16#include "rc80211_minstrel_ht.h"
17 17
18static ssize_t
19minstrel_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
27static int
28minstrel_stats_release(struct inode *inode, struct file *file)
29{
30 kfree(file->private_data);
31 return 0;
32}
33
18static char *34static char *
19minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)35minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
20{36{
@@ -41,7 +57,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) · 20 unmodified lines
41 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];57 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
42 static const int bitrates[4] = { 10, 20, 55, 110 };58 static const int bitrates[4] = { 10, 20, 55, 110 };
43 int idx = i * MCS_GROUP_RATES + j;59 int idx = i * MCS_GROUP_RATES + j;
44 unsigned int prob_ewmsd;60 unsigned int duration;
45 61
46 if (!(mi->supported[i] & BIT(j)))62 if (!(mi->supported[i] & BIT(j)))
47 continue;63 continue;
@@ -79,21 +95,21 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) · 31 unmodified lines
79 p += sprintf(p, " %3u ", idx);95 p += sprintf(p, " %3u ", idx);
80 96
81 /* tx_time[rate(i)] in usec */97 /* 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);
83 p += sprintf(p, "%6u ", tx_time);101 p += sprintf(p, "%6u ", tx_time);
84 102
85 tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));103 tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
86 tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);104 tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
87 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);105 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
88 prob_ewmsd = minstrel_get_ewmsd10(mrs);
89 106
90 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"107 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u"
91 " %3u %3u %-3u "108 " %3u %3u %-3u "
92 "%9llu %-9llu\n",109 "%9llu %-9llu\n",
93 tp_max / 10, tp_max % 10,110 tp_max / 10, tp_max % 10,
94 tp_avg / 10, tp_avg % 10,111 tp_avg / 10, tp_avg % 10,
95 eprob / 10, eprob % 10,112 eprob / 10, eprob % 10,
96 prob_ewmsd / 10, prob_ewmsd % 10,
97 mrs->retry_count,113 mrs->retry_count,
98 mrs->last_success,114 mrs->last_success,
99 mrs->last_attempts,115 mrs->last_attempts,
@@ -130,9 +146,9 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) · 30 unmodified lines
130 146
131 p += sprintf(p, "\n");147 p += sprintf(p, "\n");
132 p += sprintf(p,148 p += sprintf(p,
133 " best ____________rate__________ ________statistics________ _____last____ ______sum-of________\n");149 " best ____________rate__________ ____statistics___ _____last____ ______sum-of________\n");
134 p += sprintf(p,150 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");
136 152
137 p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);153 p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
138 for (i = 0; i < MINSTREL_CCK_GROUP; i++)154 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
187 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];203 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
188 static const int bitrates[4] = { 10, 20, 55, 110 };204 static const int bitrates[4] = { 10, 20, 55, 110 };
189 int idx = i * MCS_GROUP_RATES + j;205 int idx = i * MCS_GROUP_RATES + j;
190 unsigned int prob_ewmsd;206 unsigned int duration;
191 207
192 if (!(mi->supported[i] & BIT(j)))208 if (!(mi->supported[i] & BIT(j)))
193 continue;209 continue;
@@ -222,20 +238,21 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) · 28 unmodified lines
222 }238 }
223 239
224 p += sprintf(p, "%u,", idx);240 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);
226 p += sprintf(p, "%u,", tx_time);245 p += sprintf(p, "%u,", tx_time);
227 246
228 tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));247 tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
229 tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);248 tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
230 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);249 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
231 prob_ewmsd = minstrel_get_ewmsd10(mrs);
232 250
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,"
234 "%u,%llu,%llu,",252 "%u,%llu,%llu,",
235 tp_max / 10, tp_max % 10,253 tp_max / 10, tp_max % 10,
236 tp_avg / 10, tp_avg % 10,254 tp_avg / 10, tp_avg % 10,
237 eprob / 10, eprob % 10,255 eprob / 10, eprob % 10,
238 prob_ewmsd / 10, prob_ewmsd % 10,
239 mrs->retry_count,256 mrs->retry_count,
240 mrs->last_success,257 mrs->last_success,
241 mrs->last_attempts,258 mrs->last_attempts,
@@ -303,17 +320,8 @@ minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) · 61 unmodified lines
303{320{
304 struct minstrel_ht_sta_priv *msp = priv_sta;321 struct minstrel_ht_sta_priv *msp = priv_sta;
305 322
306 msp->dbg_stats = debugfs_create_file("rc_stats", 0444, dir, msp,323 debugfs_create_file("rc_stats", 0444, dir, msp,
307 &minstrel_ht_stat_fops);324 &minstrel_ht_stat_fops);
308 msp->dbg_stats_csv = debugfs_create_file("rc_stats_csv", 0444, dir, msp,325 debugfs_create_file("rc_stats_csv", 0444, dir, msp,
309 &minstrel_ht_stat_csv_fops);326 &minstrel_ht_stat_csv_fops);
310}
311
312void
313minstrel_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);
319}327}
net/mac80211/rx.c+6−6
@@ -2458,8 +2458,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) · 2457 unmodified lines
2458 if (!xmit_skb)2458 if (!xmit_skb)
2459 net_info_ratelimited("%s: failed to clone multicast frame\n",2459 net_info_ratelimited("%s: failed to clone multicast frame\n",
2460 dev->name);2460 dev->name);
2461 } else if (!is_multicast_ether_addr(ehdr->h_dest)) {2461 } else if (!is_multicast_ether_addr(ehdr->h_dest) &&
2462 dsta = sta_info_get(sdata, skb->data);2462 !ether_addr_equal(ehdr->h_dest, ehdr->h_source)) {
2463 dsta = sta_info_get(sdata, ehdr->h_dest);
2463 if (dsta) {2464 if (dsta) {
2464 /*2465 /*
2465 * The destination station is associated to2466 * The destination station is associated to
@@ -4240,11 +4241,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, · 1774 unmodified lines
4240 4241
4241 if (fast_rx->internal_forward) {4242 if (fast_rx->internal_forward) {
4242 struct sk_buff *xmit_skb = NULL;4243 struct sk_buff *xmit_skb = NULL;
4243 bool multicast = is_multicast_ether_addr(skb->data);4244 if (is_multicast_ether_addr(addrs.da)) {
4244
4245 if (multicast) {
4246 xmit_skb = skb_copy(skb, GFP_ATOMIC);4245 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)) {
4248 xmit_skb = skb;4248 xmit_skb = skb;
4249 skb = NULL;4249 skb = NULL;
4250 }4250 }
net/mac80211/status.c+19−0
@@ -987,6 +987,25 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw, · 986 unmodified lines
987}987}
988EXPORT_SYMBOL(ieee80211_tx_status_ext);988EXPORT_SYMBOL(ieee80211_tx_status_ext);
989 989
990void 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}
1007EXPORT_SYMBOL(ieee80211_tx_rate_update);
1008
990void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)1009void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
991{1010{
992 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);1011 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
2600 )2600 )
2601);2601);
2602 2602
2603TRACE_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
2603#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */2626#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
2604 2627
2605#undef TRACE_INCLUDE_PATH2628#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
264 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {264 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
265 struct ieee80211_txq *txq = sta->sta.txq[i];265 struct ieee80211_txq *txq = sta->sta.txq[i];
266 266
267 if (!txq)
268 continue;
269
267 txqi = to_txq_info(txq);270 txqi = to_txq_info(txq);
268 271
269 if (ac != txq->ac)272 if (ac != txq->ac)
@@ -2175,6 +2178,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) · 1905 unmodified lines
2175 case NL80211_IFTYPE_AP:2178 case NL80211_IFTYPE_AP:
2176 changed |= BSS_CHANGED_SSID | BSS_CHANGED_P2P_PS;2179 changed |= BSS_CHANGED_SSID | BSS_CHANGED_P2P_PS;
2177 2180
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
2178 if (sdata->vif.type == NL80211_IFTYPE_AP) {2186 if (sdata->vif.type == NL80211_IFTYPE_AP) {
2179 changed |= BSS_CHANGED_AP_PROBE_RESP;2187 changed |= BSS_CHANGED_AP_PROBE_RESP;
2180 2188
net/wireless/core.c+47−36
@@ -1019,36 +1019,49 @@ void cfg80211_cqm_config_free(struct wireless_dev *wdev) · 1018 unmodified lines
1019 wdev->cqm_config = NULL;1019 wdev->cqm_config = NULL;
1020}1020}
1021 1021
1022void cfg80211_unregister_wdev(struct wireless_dev *wdev)1022static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync)
1023{1023{
1024 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);1024 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
1025 1025
1026 ASSERT_RTNL();1026 ASSERT_RTNL();
1027 1027
1028 if (WARN_ON(wdev->netdev))
1029 return;
1030
1031 nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);1028 nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
1032 1029
1033 list_del_rcu(&wdev->list);1030 list_del_rcu(&wdev->list);
1034 synchronize_rcu();1031 if (sync)
1032 synchronize_rcu();
1035 rdev->devlist_generation++;1033 rdev->devlist_generation++;
1036 1034
1035 cfg80211_mlme_purge_registrations(wdev);
1036
1037 switch (wdev->iftype) {1037 switch (wdev->iftype) {
1038 case NL80211_IFTYPE_P2P_DEVICE:1038 case NL80211_IFTYPE_P2P_DEVICE:
1039 cfg80211_mlme_purge_registrations(wdev);
1040 cfg80211_stop_p2p_device(rdev, wdev);1039 cfg80211_stop_p2p_device(rdev, wdev);
1041 break;1040 break;
1042 case NL80211_IFTYPE_NAN:1041 case NL80211_IFTYPE_NAN:
1043 cfg80211_stop_nan(rdev, wdev);1042 cfg80211_stop_nan(rdev, wdev);
1044 break;1043 break;
1045 default:1044 default:
1046 WARN_ON_ONCE(1);
1047 break;1045 break;
1048 }1046 }
1049 1047
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
1050 cfg80211_cqm_config_free(wdev);1055 cfg80211_cqm_config_free(wdev);
1051}1056}
1057
1058void cfg80211_unregister_wdev(struct wireless_dev *wdev)
1059{
1060 if (WARN_ON(wdev->netdev))
1061 return;
1062
1063 __cfg80211_unregister_wdev(wdev, true);
1064}
1052EXPORT_SYMBOL(cfg80211_unregister_wdev);1065EXPORT_SYMBOL(cfg80211_unregister_wdev);
1053 1066
1054static const struct device_type wiphy_type = {1067static const struct device_type wiphy_type = {
@@ -1153,6 +1166,30 @@ void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, · 98 unmodified lines
1153}1166}
1154EXPORT_SYMBOL(cfg80211_stop_iface);1167EXPORT_SYMBOL(cfg80211_stop_iface);
1155 1168
1169void 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
1156static int cfg80211_netdev_notifier_call(struct notifier_block *nb,1193static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
1157 unsigned long state, void *ptr)1194 unsigned long state, void *ptr)
1158{1195{
@@ -1178,23 +1215,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 19 unmodified lines
1178 * called within code protected by it when interfaces1215 * called within code protected by it when interfaces
1179 * are added with nl80211.1216 * are added with nl80211.
1180 */1217 */
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++;
1198 /* can only change netns with wiphy */1218 /* can only change netns with wiphy */
1199 dev->features |= NETIF_F_NETNS_LOCAL;1219 dev->features |= NETIF_F_NETNS_LOCAL;
1200 1220
@@ -1223,7 +1243,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 22 unmodified lines
1223 1243
1224 INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);1244 INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);
1225 1245
1226 nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);1246 cfg80211_init_wdev(rdev, wdev);
1227 break;1247 break;
1228 case NETDEV_GOING_DOWN:1248 case NETDEV_GOING_DOWN:
1229 cfg80211_leave(rdev, wdev);1249 cfg80211_leave(rdev, wdev);
@@ -1238,7 +1258,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 8 unmodified lines
1238 1258
1239 list_for_each_entry_safe(pos, tmp,1259 list_for_each_entry_safe(pos, tmp,
1240 &rdev->sched_scan_req_list, list) {1260 &rdev->sched_scan_req_list, list) {
1241 if (WARN_ON(pos && pos->dev == wdev->netdev))1261 if (WARN_ON(pos->dev == wdev->netdev))
1242 cfg80211_stop_sched_scan_req(rdev, pos, false);1262 cfg80211_stop_sched_scan_req(rdev, pos, false);
1243 }1263 }
1244 1264
@@ -1302,17 +1322,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 57 unmodified lines
1302 * remove and clean it up.1322 * remove and clean it up.
1303 */1323 */
1304 if (!list_empty(&wdev->list)) {1324 if (!list_empty(&wdev->list)) {
1305 nl80211_notify_iface(rdev, wdev,1325 __cfg80211_unregister_wdev(wdev, false);
1306 NL80211_CMD_DEL_INTERFACE);
1307 sysfs_remove_link(&dev->dev.kobj, "phy80211");1326 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);
1316 }1327 }
1317 /*1328 /*
1318 * synchronise (so that we won't find this netdev1329 * 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
66 /* protected by RTNL only */66 /* protected by RTNL only */
67 int num_running_ifaces;67 int num_running_ifaces;
68 int num_running_monitor_ifaces;68 int num_running_monitor_ifaces;
69 u64 cookie_counter;
69 70
70 /* BSSes/scanning */71 /* BSSes/scanning */
71 spinlock_t bss_lock;72 spinlock_t bss_lock;
@@ -133,6 +134,16 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) · 61 unmodified lines
133#endif134#endif
134}135}
135 136
137static 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
136extern struct workqueue_struct *cfg80211_wq;147extern struct workqueue_struct *cfg80211_wq;
137extern struct list_head cfg80211_rdev_list;148extern struct list_head cfg80211_rdev_list;
138extern int cfg80211_rdev_list_generation;149extern int cfg80211_rdev_list_generation;
@@ -187,6 +198,9 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); · 48 unmodified lines
187int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,198int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
188 struct net *net);199 struct net *net);
189 200
201void cfg80211_init_wdev(struct cfg80211_registered_device *rdev,
202 struct wireless_dev *wdev);
203
190static inline void wdev_lock(struct wireless_dev *wdev)204static inline void wdev_lock(struct wireless_dev *wdev)
191 __acquires(wdev)205 __acquires(wdev)
192{206{
net/wireless/lib80211_crypt_tkip.c+20−39
@@ -30,7 +30,7 @@ · 29 unmodified lines
30#include <net/iw_handler.h>30#include <net/iw_handler.h>
31 31
32#include <crypto/hash.h>32#include <crypto/hash.h>
33#include <crypto/skcipher.h>33#include <linux/crypto.h>
34#include <linux/crc32.h>34#include <linux/crc32.h>
35 35
36#include <net/lib80211.h>36#include <net/lib80211.h>
@@ -64,9 +64,9 @@ struct lib80211_tkip_data { · 27 unmodified lines
64 64
65 int key_idx;65 int key_idx;
66 66
67 struct crypto_skcipher *rx_tfm_arc4;67 struct crypto_cipher *rx_tfm_arc4;
68 struct crypto_shash *rx_tfm_michael;68 struct crypto_shash *rx_tfm_michael;
69 struct crypto_skcipher *tx_tfm_arc4;69 struct crypto_cipher *tx_tfm_arc4;
70 struct crypto_shash *tx_tfm_michael;70 struct crypto_shash *tx_tfm_michael;
71 71
72 /* scratch buffers for virt_to_page() (crypto API) */72 /* scratch buffers for virt_to_page() (crypto API) */
@@ -99,8 +99,7 @@ static void *lib80211_tkip_init(int key_idx) · 26 unmodified lines
99 99
100 priv->key_idx = key_idx;100 priv->key_idx = key_idx;
101 101
102 priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0,102 priv->tx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
103 CRYPTO_ALG_ASYNC);
104 if (IS_ERR(priv->tx_tfm_arc4)) {103 if (IS_ERR(priv->tx_tfm_arc4)) {
105 priv->tx_tfm_arc4 = NULL;104 priv->tx_tfm_arc4 = NULL;
106 goto fail;105 goto fail;
@@ -112,8 +111,7 @@ static void *lib80211_tkip_init(int key_idx) · 5 unmodified lines
112 goto fail;111 goto fail;
113 }112 }
114 113
115 priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0,114 priv->rx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
116 CRYPTO_ALG_ASYNC);
117 if (IS_ERR(priv->rx_tfm_arc4)) {115 if (IS_ERR(priv->rx_tfm_arc4)) {
118 priv->rx_tfm_arc4 = NULL;116 priv->rx_tfm_arc4 = NULL;
119 goto fail;117 goto fail;
@@ -130,9 +128,9 @@ static void *lib80211_tkip_init(int key_idx) · 10 unmodified lines
130 fail:128 fail:
131 if (priv) {129 if (priv) {
132 crypto_free_shash(priv->tx_tfm_michael);130 crypto_free_shash(priv->tx_tfm_michael);
133 crypto_free_skcipher(priv->tx_tfm_arc4);131 crypto_free_cipher(priv->tx_tfm_arc4);
134 crypto_free_shash(priv->rx_tfm_michael);132 crypto_free_shash(priv->rx_tfm_michael);
135 crypto_free_skcipher(priv->rx_tfm_arc4);133 crypto_free_cipher(priv->rx_tfm_arc4);
136 kfree(priv);134 kfree(priv);
137 }135 }
138 136
@@ -144,9 +142,9 @@ static void lib80211_tkip_deinit(void *priv) · 5 unmodified lines
144 struct lib80211_tkip_data *_priv = priv;142 struct lib80211_tkip_data *_priv = priv;
145 if (_priv) {143 if (_priv) {
146 crypto_free_shash(_priv->tx_tfm_michael);144 crypto_free_shash(_priv->tx_tfm_michael);
147 crypto_free_skcipher(_priv->tx_tfm_arc4);145 crypto_free_cipher(_priv->tx_tfm_arc4);
148 crypto_free_shash(_priv->rx_tfm_michael);146 crypto_free_shash(_priv->rx_tfm_michael);
149 crypto_free_skcipher(_priv->rx_tfm_arc4);147 crypto_free_cipher(_priv->rx_tfm_arc4);
150 }148 }
151 kfree(priv);149 kfree(priv);
152}150}
@@ -344,12 +342,10 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, · 191 unmodified lines
344static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)342static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
345{343{
346 struct lib80211_tkip_data *tkey = priv;344 struct lib80211_tkip_data *tkey = priv;
347 SKCIPHER_REQUEST_ON_STACK(req, tkey->tx_tfm_arc4);
348 int len;345 int len;
349 u8 rc4key[16], *pos, *icv;346 u8 rc4key[16], *pos, *icv;
350 u32 crc;347 u32 crc;
351 struct scatterlist sg;348 int i;
352 int err;
353 349
354 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {350 if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) {
355 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;351 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
374 icv[2] = crc >> 16;370 icv[2] = crc >> 16;
375 icv[3] = crc >> 24;371 icv[3] = crc >> 24;
376 372
377 crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);373 crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
378 sg_init_one(&sg, pos, len + 4);374 for (i = 0; i < len + 4; i++)
379 skcipher_request_set_tfm(req, tkey->tx_tfm_arc4);375 crypto_cipher_encrypt_one(tkey->tx_tfm_arc4, pos + i, pos + i);
380 skcipher_request_set_callback(req, 0, NULL, NULL);376 return 0;
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;
385}377}
386 378
387/*379/*
@@ -400,7 +392,6 @@ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n, · 12 unmodified lines
400static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)392static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
401{393{
402 struct lib80211_tkip_data *tkey = priv;394 struct lib80211_tkip_data *tkey = priv;
403 SKCIPHER_REQUEST_ON_STACK(req, tkey->rx_tfm_arc4);
404 u8 rc4key[16];395 u8 rc4key[16];
405 u8 keyidx, *pos;396 u8 keyidx, *pos;
406 u32 iv32;397 u32 iv32;
@@ -408,9 +399,8 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) · 1 unmodified line
408 struct ieee80211_hdr *hdr;399 struct ieee80211_hdr *hdr;
409 u8 icv[4];400 u8 icv[4];
410 u32 crc;401 u32 crc;
411 struct scatterlist sg;
412 int plen;402 int plen;
413 int err;403 int i;
414 404
415 hdr = (struct ieee80211_hdr *)skb->data;405 hdr = (struct ieee80211_hdr *)skb->data;
416 406
@@ -463,18 +453,9 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) · 46 unmodified lines
463 453
464 plen = skb->len - hdr_len - 12;454 plen = skb->len - hdr_len - 12;
465 455
466 crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);456 crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
467 sg_init_one(&sg, pos, plen + 4);457 for (i = 0; i < plen + 4; i++)
468 skcipher_request_set_tfm(req, tkey->rx_tfm_arc4);458 crypto_cipher_decrypt_one(tkey->rx_tfm_arc4, pos + i, pos + i);
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 }
478 459
479 crc = ~crc32_le(~0, pos, plen);460 crc = ~crc32_le(~0, pos, plen);
480 icv[0] = crc;461 icv[0] = crc;
@@ -660,9 +641,9 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) · 179 unmodified lines
660 struct lib80211_tkip_data *tkey = priv;641 struct lib80211_tkip_data *tkey = priv;
661 int keyidx;642 int keyidx;
662 struct crypto_shash *tfm = tkey->tx_tfm_michael;643 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;
664 struct crypto_shash *tfm3 = tkey->rx_tfm_michael;645 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;
666 647
667 keyidx = tkey->key_idx;648 keyidx = tkey->key_idx;
668 memset(tkey, 0, sizeof(*tkey));649 memset(tkey, 0, sizeof(*tkey));
net/wireless/lib80211_crypt_wep.c+20−32
@@ -22,7 +22,7 @@ · 21 unmodified lines
22 22
23#include <net/lib80211.h>23#include <net/lib80211.h>
24 24
25#include <crypto/skcipher.h>25#include <linux/crypto.h>
26#include <linux/crc32.h>26#include <linux/crc32.h>
27 27
28MODULE_AUTHOR("Jouni Malinen");28MODULE_AUTHOR("Jouni Malinen");
@@ -35,8 +35,8 @@ struct lib80211_wep_data { · 6 unmodified lines
35 u8 key[WEP_KEY_LEN + 1];35 u8 key[WEP_KEY_LEN + 1];
36 u8 key_len;36 u8 key_len;
37 u8 key_idx;37 u8 key_idx;
38 struct crypto_skcipher *tx_tfm;38 struct crypto_cipher *tx_tfm;
39 struct crypto_skcipher *rx_tfm;39 struct crypto_cipher *rx_tfm;
40};40};
41 41
42static void *lib80211_wep_init(int keyidx)42static void *lib80211_wep_init(int keyidx)
@@ -48,13 +48,13 @@ static void *lib80211_wep_init(int keyidx) · 5 unmodified lines
48 goto fail;48 goto fail;
49 priv->key_idx = keyidx;49 priv->key_idx = keyidx;
50 50
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);
52 if (IS_ERR(priv->tx_tfm)) {52 if (IS_ERR(priv->tx_tfm)) {
53 priv->tx_tfm = NULL;53 priv->tx_tfm = NULL;
54 goto fail;54 goto fail;
55 }55 }
56 56
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);
58 if (IS_ERR(priv->rx_tfm)) {58 if (IS_ERR(priv->rx_tfm)) {
59 priv->rx_tfm = NULL;59 priv->rx_tfm = NULL;
60 goto fail;60 goto fail;
@@ -66,8 +66,8 @@ static void *lib80211_wep_init(int keyidx) · 5 unmodified lines
66 66
67 fail:67 fail:
68 if (priv) {68 if (priv) {
69 crypto_free_skcipher(priv->tx_tfm);69 crypto_free_cipher(priv->tx_tfm);
70 crypto_free_skcipher(priv->rx_tfm);70 crypto_free_cipher(priv->rx_tfm);
71 kfree(priv);71 kfree(priv);
72 }72 }
73 return NULL;73 return NULL;
@@ -77,8 +77,8 @@ static void lib80211_wep_deinit(void *priv) · 3 unmodified lines
77{77{
78 struct lib80211_wep_data *_priv = priv;78 struct lib80211_wep_data *_priv = priv;
79 if (_priv) {79 if (_priv) {
80 crypto_free_skcipher(_priv->tx_tfm);80 crypto_free_cipher(_priv->tx_tfm);
81 crypto_free_skcipher(_priv->rx_tfm);81 crypto_free_cipher(_priv->rx_tfm);
82 }82 }
83 kfree(priv);83 kfree(priv);
84}84}
@@ -129,12 +129,10 @@ static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len, · 44 unmodified lines
129static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)129static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
130{130{
131 struct lib80211_wep_data *wep = priv;131 struct lib80211_wep_data *wep = priv;
132 SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm);
133 u32 crc, klen, len;132 u32 crc, klen, len;
134 u8 *pos, *icv;133 u8 *pos, *icv;
135 struct scatterlist sg;
136 u8 key[WEP_KEY_LEN + 3];134 u8 key[WEP_KEY_LEN + 3];
137 int err;135 int i;
138 136
139 /* other checks are in lib80211_wep_build_iv */137 /* other checks are in lib80211_wep_build_iv */
140 if (skb_tailroom(skb) < 4)138 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
162 icv[2] = crc >> 16;160 icv[2] = crc >> 16;
163 icv[3] = crc >> 24;161 icv[3] = crc >> 24;
164 162
165 crypto_skcipher_setkey(wep->tx_tfm, key, klen);163 crypto_cipher_setkey(wep->tx_tfm, key, klen);
166 sg_init_one(&sg, pos, len + 4);164
167 skcipher_request_set_tfm(req, wep->tx_tfm);165 for (i = 0; i < len + 4; i++)
168 skcipher_request_set_callback(req, 0, NULL, NULL);166 crypto_cipher_encrypt_one(wep->tx_tfm, pos + i, pos + i);
169 skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL);167
170 err = crypto_skcipher_encrypt(req);168 return 0;
171 skcipher_request_zero(req);
172 return err;
173}169}
174 170
175/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of171/* 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
182static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)178static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
183{179{
184 struct lib80211_wep_data *wep = priv;180 struct lib80211_wep_data *wep = priv;
185 SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm);
186 u32 crc, klen, plen;181 u32 crc, klen, plen;
187 u8 key[WEP_KEY_LEN + 3];182 u8 key[WEP_KEY_LEN + 3];
188 u8 keyidx, *pos, icv[4];183 u8 keyidx, *pos, icv[4];
189 struct scatterlist sg;184 int i;
190 int err;
191 185
192 if (skb->len < hdr_len + 8)186 if (skb->len < hdr_len + 8)
193 return -1;187 return -1;
@@ -208,15 +202,9 @@ static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) · 14 unmodified lines
208 /* Apply RC4 to data and compute CRC32 over decrypted data */202 /* Apply RC4 to data and compute CRC32 over decrypted data */
209 plen = skb->len - hdr_len - 8;203 plen = skb->len - hdr_len - 8;
210 204
211 crypto_skcipher_setkey(wep->rx_tfm, key, klen);205 crypto_cipher_setkey(wep->rx_tfm, key, klen);
212 sg_init_one(&sg, pos, plen + 4);206 for (i = 0; i < plen + 4; i++)
213 skcipher_request_set_tfm(req, wep->rx_tfm);207 crypto_cipher_decrypt_one(wep->rx_tfm, pos + i, pos + i);
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;
220 208
221 crc = ~crc32_le(~0, pos, plen);209 crc = ~crc32_le(~0, pos, plen);
222 icv[0] = crc;210 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
200 return __cfg80211_rdev_from_attrs(netns, info->attrs);200 return __cfg80211_rdev_from_attrs(netns, info->attrs);
201}201}
202 202
203static 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;
228error:
229 NL_SET_ERR_MSG_ATTR(extack, attr, "malformed information elements");
230 return -EINVAL;
231}
232
203/* policy for the attributes */233/* policy for the attributes */
234static const struct nla_policy
235nl80211_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
204static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {243static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
205 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },244 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
206 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,245 [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
213 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },252 [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
214 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },253 [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
215 254
216 [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },255 [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
217 [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },256 [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
218 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },257 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
219 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },258 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
220 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },259 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
221 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },260 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
222 261
223 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },262 [NL80211_ATTR_IFTYPE] = NLA_POLICY_MAX(NLA_U32, NL80211_IFTYPE_MAX),
224 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },263 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
225 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },264 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
226 265
@@ -230,24 +269,28 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 3 unmodified lines
230 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },269 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
231 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,270 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
232 .len = WLAN_MAX_KEY_LEN },271 .len = WLAN_MAX_KEY_LEN },
233 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },272 [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 5),
234 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },273 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
235 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },274 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
236 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },275 [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),
238 278
239 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },279 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
240 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },280 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
241 [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,281 [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
242 .len = IEEE80211_MAX_DATA_LEN },282 .len = IEEE80211_MAX_DATA_LEN },
243 [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,283 [NL80211_ATTR_BEACON_TAIL] =
244 .len = IEEE80211_MAX_DATA_LEN },284 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
245 [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },285 IEEE80211_MAX_DATA_LEN),
286 [NL80211_ATTR_STA_AID] =
287 NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
246 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },288 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
247 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },289 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
248 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,290 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
249 .len = NL80211_MAX_SUPP_RATES },291 .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),
251 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },294 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
252 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },295 [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
253 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,296 [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
@@ -270,8 +313,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 16 unmodified lines
270 [NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN },313 [NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN },
271 314
272 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },315 [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
273 [NL80211_ATTR_IE] = { .type = NLA_BINARY,316 [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
274 .len = IEEE80211_MAX_DATA_LEN },317 validate_ie_attr,
318 IEEE80211_MAX_DATA_LEN),
275 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },319 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
276 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },320 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
277 321
@@ -281,7 +325,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 3 unmodified lines
281 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },325 [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
282 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },326 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
283 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },327 [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),
285 [NL80211_ATTR_STA_FLAGS2] = {331 [NL80211_ATTR_STA_FLAGS2] = {
286 .len = sizeof(struct nl80211_sta_flag_update),332 .len = sizeof(struct nl80211_sta_flag_update),
287 },333 },
@@ -301,7 +347,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 13 unmodified lines
301 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,347 [NL80211_ATTR_FRAME] = { .type = NLA_BINARY,
302 .len = IEEE80211_MAX_DATA_LEN },348 .len = IEEE80211_MAX_DATA_LEN },
303 [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, },349 [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),
305 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },353 [NL80211_ATTR_CQM] = { .type = NLA_NESTED, },
306 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },354 [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG },
307 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },355 [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 },
@@ -314,15 +362,23 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 6 unmodified lines
314 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },362 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
315 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },363 [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
316 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },364 [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),
318 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },369 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
319 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },370 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
320 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },371 [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED },
321 [NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 },372 [NL80211_ATTR_HIDDEN_SSID] =
322 [NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY,373 NLA_POLICY_RANGE(NLA_U32,
323 .len = IEEE80211_MAX_DATA_LEN },374 NL80211_HIDDEN_SSID_NOT_IN_USE,
324 [NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY,375 NL80211_HIDDEN_SSID_ZERO_CONTENTS),
325 .len = IEEE80211_MAX_DATA_LEN },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),
326 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },382 [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
327 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },383 [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
328 [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG },384 [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
348 [NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, },404 [NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, },
349 [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },405 [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
350 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },406 [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
351 [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },407 [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
352 [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },408 [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1),
353 [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 },409 [NL80211_ATTR_LOCAL_MESH_POWER_MODE] =
410 NLA_POLICY_RANGE(NLA_U32,
411 NL80211_MESH_POWER_UNKNOWN + 1,
412 NL80211_MESH_POWER_MAX),
354 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },413 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
355 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },414 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
356 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },415 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
@@ -363,7 +422,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 6 unmodified lines
363 [NL80211_ATTR_MDID] = { .type = NLA_U16 },422 [NL80211_ATTR_MDID] = { .type = NLA_U16 },
364 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,423 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
365 .len = IEEE80211_MAX_DATA_LEN },424 .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),
367 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },427 [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
368 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },428 [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
369 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },429 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
@@ -384,8 +444,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 14 unmodified lines
384 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },444 [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
385 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },445 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
386 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },446 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
387 [NL80211_ATTR_TSID] = { .type = NLA_U8 },447 [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1),
388 [NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },448 [NL80211_ATTR_USER_PRIO] =
449 NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
389 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },450 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
390 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },451 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
391 [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },452 [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },
@@ -395,12 +456,13 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 3 unmodified lines
395 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },456 [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
396 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },457 [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
397 [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },458 [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),
399 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {461 [NL80211_ATTR_MU_MIMO_GROUP_DATA] = {
400 .len = VHT_MUMIMO_GROUPS_DATA_LEN462 .len = VHT_MUMIMO_GROUPS_DATA_LEN
401 },463 },
402 [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },464 [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),
404 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },466 [NL80211_ATTR_BANDS] = { .type = NLA_U32 },
405 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },467 [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
406 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,468 [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,
@@ -430,6 +492,11 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 23 unmodified lines
430 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },492 [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
431 [NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY,493 [NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY,
432 .len = NL80211_HE_MAX_CAPABILITY_LEN },494 .len = NL80211_HE_MAX_CAPABILITY_LEN },
495
496 [NL80211_ATTR_FTM_RESPONDER] = {
497 .type = NLA_NESTED,
498 .validation_data = nl80211_ftm_responder_policy,
499 },
433};500};
434 501
435/* policy for the key attributes */502/* policy for the key attributes */
@@ -440,7 +507,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { · 4 unmodified lines
440 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },507 [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
441 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },508 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
442 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },509 [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),
444 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },511 [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
445};512};
446 513
@@ -491,7 +558,10 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = { · 44 unmodified lines
491static const struct nla_policy558static const struct nla_policy
492nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {559nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {
493 [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 },560 [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),
495 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },565 [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED },
496};566};
497 567
@@ -567,8 +637,7 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = { · 69 unmodified lines
567 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },637 [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
568};638};
569 639
570static int nl80211_prepare_wdev_dump(struct sk_buff *skb,640static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
571 struct netlink_callback *cb,
572 struct cfg80211_registered_device **rdev,641 struct cfg80211_registered_device **rdev,
573 struct wireless_dev **wdev)642 struct wireless_dev **wdev)
574{643{
@@ -582,7 +651,7 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, · 7 unmodified lines
582 return err;651 return err;
583 652
584 *wdev = __cfg80211_wdev_from_attrs(653 *wdev = __cfg80211_wdev_from_attrs(
585 sock_net(skb->sk),654 sock_net(cb->skb->sk),
586 genl_family_attrbuf(&nl80211_fam));655 genl_family_attrbuf(&nl80211_fam));
587 if (IS_ERR(*wdev))656 if (IS_ERR(*wdev))
588 return PTR_ERR(*wdev);657 return PTR_ERR(*wdev);
@@ -614,36 +683,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, · 25 unmodified lines
614 return 0;683 return 0;
615}684}
616 685
617/* IE validation */
618static 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
647/* message building helper */686/* message building helper */
648static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,687static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
649 int flags, u8 cmd)688 int flags, u8 cmd)
@@ -858,12 +897,8 @@ static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key, · 208 unmodified lines
858 if (tb[NL80211_KEY_CIPHER])897 if (tb[NL80211_KEY_CIPHER])
859 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);898 k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]);
860 899
861 if (tb[NL80211_KEY_TYPE]) {900 if (tb[NL80211_KEY_TYPE])
862 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);901 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 }
867 902
868 if (tb[NL80211_KEY_DEFAULT_TYPES]) {903 if (tb[NL80211_KEY_DEFAULT_TYPES]) {
869 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];904 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
910 if (k->defmgmt)945 if (k->defmgmt)
911 k->def_multi = true;946 k->def_multi = true;
912 947
913 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {948 if (info->attrs[NL80211_ATTR_KEY_TYPE])
914 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);949 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 }
920 950
921 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {951 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
922 struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];952 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
2292 struct genl_info *info,2322 struct genl_info *info,
2293 struct cfg80211_chan_def *chandef)2323 struct cfg80211_chan_def *chandef)
2294{2324{
2325 struct netlink_ext_ack *extack = info->extack;
2326 struct nlattr **attrs = info->attrs;
2295 u32 control_freq;2327 u32 control_freq;
2296 2328
2297 if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])2329 if (!attrs[NL80211_ATTR_WIPHY_FREQ])
2298 return -EINVAL;2330 return -EINVAL;
2299 2331
2300 control_freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);2332 control_freq = nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ]);
2301 2333
2302 chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);2334 chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);
2303 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;2335 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
@@ -2305,14 +2337,16 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, · 1 unmodified line
2305 chandef->center_freq2 = 0;2337 chandef->center_freq2 = 0;
2306 2338
2307 /* Primary channel not allowed */2339 /* 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");
2309 return -EINVAL;2343 return -EINVAL;
2344 }
2310 2345
2311 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {2346 if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
2312 enum nl80211_channel_type chantype;2347 enum nl80211_channel_type chantype;
2313 2348
2314 chantype = nla_get_u32(2349 chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
2315 info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
2316 2350
2317 switch (chantype) {2351 switch (chantype) {
2318 case NL80211_CHAN_NO_HT:2352 case NL80211_CHAN_NO_HT:
@@ -2322,42 +2356,56 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, · 3 unmodified lines
2322 cfg80211_chandef_create(chandef, chandef->chan,2356 cfg80211_chandef_create(chandef, chandef->chan,
2323 chantype);2357 chantype);
2324 /* user input for center_freq is incorrect */2358 /* user input for center_freq is incorrect */
2325 if (info->attrs[NL80211_ATTR_CENTER_FREQ1] &&2359 if (attrs[NL80211_ATTR_CENTER_FREQ1] &&
2326 chandef->center_freq1 != nla_get_u32(2360 chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) {
2327 info->attrs[NL80211_ATTR_CENTER_FREQ1]))2361 NL_SET_ERR_MSG_ATTR(extack,
2362 attrs[NL80211_ATTR_CENTER_FREQ1],
2363 "bad center frequency 1");
2328 return -EINVAL;2364 return -EINVAL;
2365 }
2329 /* center_freq2 must be zero */2366 /* center_freq2 must be zero */
2330 if (info->attrs[NL80211_ATTR_CENTER_FREQ2] &&2367 if (attrs[NL80211_ATTR_CENTER_FREQ2] &&
2331 nla_get_u32(info->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");
2332 return -EINVAL;2372 return -EINVAL;
2373 }
2333 break;2374 break;
2334 default:2375 default:
2376 NL_SET_ERR_MSG_ATTR(extack,
2377 attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
2378 "invalid channel type");
2335 return -EINVAL;2379 return -EINVAL;
2336 }2380 }
2337 } else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) {2381 } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
2338 chandef->width =2382 chandef->width =
2339 nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);2383 nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]);
2340 if (info->attrs[NL80211_ATTR_CENTER_FREQ1])2384 if (attrs[NL80211_ATTR_CENTER_FREQ1])
2341 chandef->center_freq1 =2385 chandef->center_freq1 =
2342 nla_get_u32(2386 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]);
2343 info->attrs[NL80211_ATTR_CENTER_FREQ1]);2387 if (attrs[NL80211_ATTR_CENTER_FREQ2])
2344 if (info->attrs[NL80211_ATTR_CENTER_FREQ2])
2345 chandef->center_freq2 =2388 chandef->center_freq2 =
2346 nla_get_u32(2389 nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]);
2347 info->attrs[NL80211_ATTR_CENTER_FREQ2]);
2348 }2390 }
2349 2391
2350 if (!cfg80211_chandef_valid(chandef))2392 if (!cfg80211_chandef_valid(chandef)) {
2393 NL_SET_ERR_MSG(extack, "invalid channel definition");
2351 return -EINVAL;2394 return -EINVAL;
2395 }
2352 2396
2353 if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,2397 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");
2355 return -EINVAL;2400 return -EINVAL;
2401 }
2356 2402
2357 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||2403 if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
2358 chandef->width == NL80211_CHAN_WIDTH_10) &&2404 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");
2360 return -EINVAL;2407 return -EINVAL;
2408 }
2361 2409
2362 return 0;2410 return 0;
2363}2411}
@@ -2617,8 +2665,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) · 253 unmodified lines
2617 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {2665 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
2618 retry_short = nla_get_u8(2666 retry_short = nla_get_u8(
2619 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);2667 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
2620 if (retry_short == 0)
2621 return -EINVAL;
2622 2668
2623 changed |= WIPHY_PARAM_RETRY_SHORT;2669 changed |= WIPHY_PARAM_RETRY_SHORT;
2624 }2670 }
@@ -2626,8 +2672,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line
2626 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {2672 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
2627 retry_long = nla_get_u8(2673 retry_long = nla_get_u8(
2628 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);2674 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
2629 if (retry_long == 0)
2630 return -EINVAL;
2631 2675
2632 changed |= WIPHY_PARAM_RETRY_LONG;2676 changed |= WIPHY_PARAM_RETRY_LONG;
2633 }2677 }
@@ -3119,8 +3163,6 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) · 485 unmodified lines
3119 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);3163 ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
3120 if (otype != ntype)3164 if (otype != ntype)
3121 change = true;3165 change = true;
3122 if (ntype > NL80211_IFTYPE_MAX)
3123 return -EINVAL;
3124 }3166 }
3125 3167
3126 if (info->attrs[NL80211_ATTR_MESH_ID]) {3168 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
3185 if (!info->attrs[NL80211_ATTR_IFNAME])3227 if (!info->attrs[NL80211_ATTR_IFNAME])
3186 return -EINVAL;3228 return -EINVAL;
3187 3229
3188 if (info->attrs[NL80211_ATTR_IFTYPE]) {3230 if (info->attrs[NL80211_ATTR_IFTYPE])
3189 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);3231 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
3190 if (type > NL80211_IFTYPE_MAX)
3191 return -EINVAL;
3192 }
3193 3232
3194 if (!rdev->ops->add_virtual_intf ||3233 if (!rdev->ops->add_virtual_intf ||
3195 !(rdev->wiphy.interface_modes & (1 << type)))3234 !(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
3252 * P2P Device and NAN do not have a netdev, so don't go3291 * P2P Device and NAN do not have a netdev, so don't go
3253 * through the netdev notifier and must be added here3292 * through the netdev notifier and must be added here
3254 */3293 */
3255 mutex_init(&wdev->mtx);3294 cfg80211_init_wdev(rdev, wdev);
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++;
3264 break;3295 break;
3265 default:3296 default:
3266 break;3297 break;
@@ -3272,15 +3303,6 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) · 5 unmodified lines
3272 return -ENOBUFS;3303 return -ENOBUFS;
3273 }3304 }
3274 3305
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
3284 return genlmsg_reply(msg, info);3306 return genlmsg_reply(msg, info);
3285}3307}
3286 3308
@@ -3359,7 +3381,7 @@ static void get_key_callback(void *c, struct key_params *params) · 72 unmodified lines
3359 params->cipher)))3381 params->cipher)))
3360 goto nla_put_failure;3382 goto nla_put_failure;
3361 3383
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))
3363 goto nla_put_failure;3385 goto nla_put_failure;
3364 3386
3365 nla_nest_end(cookie->msg, key);3387 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
3386 if (info->attrs[NL80211_ATTR_KEY_IDX])3408 if (info->attrs[NL80211_ATTR_KEY_IDX])
3387 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);3409 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
3388 3410
3389 if (key_idx > 5)
3390 return -EINVAL;
3391
3392 if (info->attrs[NL80211_ATTR_MAC])3411 if (info->attrs[NL80211_ATTR_MAC])
3393 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);3412 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
3394 3413
@@ -3396,8 +3415,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line
3396 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {3415 if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
3397 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);3416 u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
3398 3417
3399 if (kt >= NUM_NL80211_KEYTYPES)
3400 return -EINVAL;
3401 if (kt != NL80211_KEYTYPE_GROUP &&3418 if (kt != NL80211_KEYTYPE_GROUP &&
3402 kt != NL80211_KEYTYPE_PAIRWISE)3419 kt != NL80211_KEYTYPE_PAIRWISE)
3403 return -EINVAL;3420 return -EINVAL;
@@ -3998,16 +4015,12 @@ static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev, · 594 unmodified lines
3998 return 0;4015 return 0;
3999}4016}
4000 4017
4001static int nl80211_parse_beacon(struct nlattr *attrs[],4018static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
4019 struct nlattr *attrs[],
4002 struct cfg80211_beacon_data *bcn)4020 struct cfg80211_beacon_data *bcn)
4003{4021{
4004 bool haveinfo = false;4022 bool haveinfo = false;
4005 4023 int err;
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;
4011 4024
4012 memset(bcn, 0, sizeof(*bcn));4025 memset(bcn, 0, sizeof(*bcn));
4013 4026
@@ -4052,6 +4065,35 @@ static int nl80211_parse_beacon(struct nlattr *attrs[], · 38 unmodified lines
4052 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);4065 bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]);
4053 }4066 }
4054 4067
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
4055 return 0;4097 return 0;
4056}4098}
4057 4099
@@ -4198,7 +4240,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 140 unmodified lines
4198 !info->attrs[NL80211_ATTR_BEACON_HEAD])4240 !info->attrs[NL80211_ATTR_BEACON_HEAD])
4199 return -EINVAL;4241 return -EINVAL;
4200 4242
4201 err = nl80211_parse_beacon(info->attrs, &params.beacon);4243 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon);
4202 if (err)4244 if (err)
4203 return err;4245 return err;
4204 4246
@@ -4228,14 +4270,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 23 unmodified lines
4228 return -EINVAL;4270 return -EINVAL;
4229 }4271 }
4230 4272
4231 if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) {4273 if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
4232 params.hidden_ssid = nla_get_u32(4274 params.hidden_ssid = nla_get_u32(
4233 info->attrs[NL80211_ATTR_HIDDEN_SSID]);4275 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 }
4239 4276
4240 params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];4277 params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
4241 4278
@@ -4265,8 +4302,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 23 unmodified lines
4265 return -EINVAL;4302 return -EINVAL;
4266 params.p2p_ctwindow =4303 params.p2p_ctwindow =
4267 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);4304 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
4268 if (params.p2p_ctwindow > 127)
4269 return -EINVAL;
4270 if (params.p2p_ctwindow != 0 &&4305 if (params.p2p_ctwindow != 0 &&
4271 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))4306 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
4272 return -EINVAL;4307 return -EINVAL;
@@ -4278,8 +4313,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 5 unmodified lines
4278 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)4313 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4279 return -EINVAL;4314 return -EINVAL;
4280 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);4315 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
4281 if (tmp > 1)
4282 return -EINVAL;
4283 params.p2p_opp_ps = tmp;4316 params.p2p_opp_ps = tmp;
4284 if (params.p2p_opp_ps != 0 &&4317 if (params.p2p_opp_ps != 0 &&
4285 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))4318 !(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
4382 if (!wdev->beacon_interval)4415 if (!wdev->beacon_interval)
4383 return -EINVAL;4416 return -EINVAL;
4384 4417
4385 err = nl80211_parse_beacon(info->attrs, &params);4418 err = nl80211_parse_beacon(rdev, info->attrs, &params);
4386 if (err)4419 if (err)
4387 return err;4420 return err;
4388 4421
@@ -4728,6 +4761,8 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, · 339 unmodified lines
4728 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);4761 PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
4729 PUT_SINFO_U64(BEACON_RX, rx_beacon);4762 PUT_SINFO_U64(BEACON_RX, rx_beacon);
4730 PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);4763 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);
4731 if (wiphy_ext_feature_isset(&rdev->wiphy,4766 if (wiphy_ext_feature_isset(&rdev->wiphy,
4732 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {4767 NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
4733 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);4768 PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
@@ -4811,7 +4846,7 @@ static int nl80211_dump_station(struct sk_buff *skb, · 77 unmodified lines
4811 int err;4846 int err;
4812 4847
4813 rtnl_lock();4848 rtnl_lock();
4814 err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);4849 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
4815 if (err)4850 if (err)
4816 goto out_err;4851 goto out_err;
4817 4852
@@ -5216,17 +5251,11 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 398 unmodified lines
5216 else5251 else
5217 params.listen_interval = -1;5252 params.listen_interval = -1;
5218 5253
5219 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {5254 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS])
5220 u8 tmp;5255 params.support_p2p_ps =
5221 5256 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
5222 tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);5257 else
5223 if (tmp >= NUM_NL80211_P2P_PS_STATUS)
5224 return -EINVAL;
5225
5226 params.support_p2p_ps = tmp;
5227 } else {
5228 params.support_p2p_ps = -1;5258 params.support_p2p_ps = -1;
5229 }
5230 5259
5231 if (!info->attrs[NL80211_ATTR_MAC])5260 if (!info->attrs[NL80211_ATTR_MAC])
5232 return -EINVAL;5261 return -EINVAL;
@@ -5256,38 +5285,23 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 23 unmodified lines
5256 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))5285 if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
5257 return -EINVAL;5286 return -EINVAL;
5258 5287
5259 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {5288 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
5260 params.plink_action =5289 params.plink_action =
5261 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);5290 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
5262 if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
5263 return -EINVAL;
5264 }
5265 5291
5266 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {5292 if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) {
5267 params.plink_state =5293 params.plink_state =
5268 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);5294 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
5269 if (params.plink_state >= NUM_NL80211_PLINK_STATES)5295 if (info->attrs[NL80211_ATTR_MESH_PEER_AID])
5270 return -EINVAL;
5271 if (info->attrs[NL80211_ATTR_MESH_PEER_AID]) {
5272 params.peer_aid = nla_get_u16(5296 params.peer_aid = nla_get_u16(
5273 info->attrs[NL80211_ATTR_MESH_PEER_AID]);5297 info->attrs[NL80211_ATTR_MESH_PEER_AID]);
5274 if (params.peer_aid > IEEE80211_MAX_AID)
5275 return -EINVAL;
5276 }
5277 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;5298 params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE;
5278 }5299 }
5279 5300
5280 if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) {5301 if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE])
5281 enum nl80211_mesh_power_mode pm = nla_get_u32(5302 params.local_pm = nla_get_u32(
5282 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);5303 info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
5283 5304
5284 if (pm <= NL80211_MESH_POWER_UNKNOWN ||
5285 pm > NL80211_MESH_POWER_MAX)
5286 return -EINVAL;
5287
5288 params.local_pm = pm;
5289 }
5290
5291 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {5305 if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
5292 params.opmode_notif_used = true;5306 params.opmode_notif_used = true;
5293 params.opmode_notif =5307 params.opmode_notif =
@@ -5364,13 +5378,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 70 unmodified lines
5364 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);5378 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
5365 5379
5366 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {5380 if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
5367 u8 tmp;5381 params.support_p2p_ps =
5368 5382 nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
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;
5374 } else {5383 } else {
5375 /*5384 /*
5376 * if not specified, assume it's supported for P2P GO interface,5385 * 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
5384 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);5393 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
5385 else5394 else
5386 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);5395 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
5387 if (!params.aid || params.aid > IEEE80211_MAX_AID)
5388 return -EINVAL;
5389 5396
5390 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {5397 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
5391 params.capability =5398 params.capability =
@@ -5425,12 +5432,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 33 unmodified lines
5425 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);5432 nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
5426 }5433 }
5427 5434
5428 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) {5435 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
5429 params.plink_action =5436 params.plink_action =
5430 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);5437 nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
5431 if (params.plink_action >= NUM_NL80211_PLINK_ACTIONS)
5432 return -EINVAL;
5433 }
5434 5438
5435 err = nl80211_parse_sta_channel_info(info, &params);5439 err = nl80211_parse_sta_channel_info(info, &params);
5436 if (err)5440 if (err)
@@ -5662,7 +5666,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, · 225 unmodified lines
5662 int err;5666 int err;
5663 5667
5664 rtnl_lock();5668 rtnl_lock();
5665 err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);5669 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
5666 if (err)5670 if (err)
5667 goto out_err;5671 goto out_err;
5668 5672
@@ -5858,7 +5862,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb, · 189 unmodified lines
5858 int err;5862 int err;
5859 5863
5860 rtnl_lock();5864 rtnl_lock();
5861 err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);5865 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
5862 if (err)5866 if (err)
5863 goto out_err;5867 goto out_err;
5864 5868
@@ -5940,9 +5944,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) · 75 unmodified lines
5940 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)5944 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5941 return -EINVAL;5945 return -EINVAL;
5942 params.p2p_ctwindow =5946 params.p2p_ctwindow =
5943 nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);5947 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
5944 if (params.p2p_ctwindow < 0)
5945 return -EINVAL;
5946 if (params.p2p_ctwindow != 0 &&5948 if (params.p2p_ctwindow != 0 &&
5947 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))5949 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
5948 return -EINVAL;5950 return -EINVAL;
@@ -5954,8 +5956,6 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) · 5 unmodified lines
5954 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)5956 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
5955 return -EINVAL;5957 return -EINVAL;
5956 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);5958 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
5957 if (tmp > 1)
5958 return -EINVAL;
5959 params.p2p_opp_ps = tmp;5959 params.p2p_opp_ps = tmp;
5960 if (params.p2p_opp_ps &&5960 if (params.p2p_opp_ps &&
5961 !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))5961 !(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
6134 return -ENOBUFS;6134 return -ENOBUFS;
6135}6135}
6136 6136
6137static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {6137static const struct nla_policy
6138 [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 },6138nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
6139 [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 },6139 [NL80211_MESHCONF_RETRY_TIMEOUT] =
6140 [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 },6140 NLA_POLICY_RANGE(NLA_U16, 1, 255),
6141 [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 },6141 [NL80211_MESHCONF_CONFIRM_TIMEOUT] =
6142 [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 },6142 NLA_POLICY_RANGE(NLA_U16, 1, 255),
6143 [NL80211_MESHCONF_TTL] = { .type = NLA_U8 },6143 [NL80211_MESHCONF_HOLDING_TIMEOUT] =
6144 [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 },6144 NLA_POLICY_RANGE(NLA_U16, 1, 255),
6145 [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },6145 [NL80211_MESHCONF_MAX_PEER_LINKS] =
6146 [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 },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),
6147 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },6153 [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
6148 [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },6154 [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),
6150 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },6156 [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
6151 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },6157 [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] =
6152 [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 },6158 NLA_POLICY_MIN(NLA_U16, 1),
6153 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },6159 [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] =
6154 [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 },6160 NLA_POLICY_MIN(NLA_U16, 1),
6155 [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },6161 [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] =
6156 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },6162 NLA_POLICY_MIN(NLA_U16, 1),
6157 [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },6163 [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4),
6158 [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32 },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),
6159 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },6170 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
6160 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },6171 [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
6161 [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 },6172 [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] =
6162 [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 },6173 NLA_POLICY_MIN(NLA_U16, 1),
6163 [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 },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),
6164 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },6180 [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
6165 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },6181 [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 },
6166};6182};
@@ -6173,68 +6189,12 @@ static const struct nla_policy · 6 unmodified lines
6173 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },6189 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
6174 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },6190 [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
6175 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },6191 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
6176 [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,6192 [NL80211_MESH_SETUP_IE] =
6177 .len = IEEE80211_MAX_DATA_LEN },6193 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
6194 IEEE80211_MAX_DATA_LEN),
6178 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },6195 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
6179};6196};
6180 6197
6181static 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
6190static 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
6199static 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
6208static 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
6217static 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
6226static 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
6238static int nl80211_parse_mesh_config(struct genl_info *info,6198static int nl80211_parse_mesh_config(struct genl_info *info,
6239 struct mesh_config *cfg,6199 struct mesh_config *cfg,
6240 u32 *mask_out)6200 u32 *mask_out)
@@ -6243,13 +6203,12 @@ static int nl80211_parse_mesh_config(struct genl_info *info, · 2 unmodified lines
6243 u32 mask = 0;6203 u32 mask = 0;
6244 u16 ht_opmode;6204 u16 ht_opmode;
6245 6205
6246#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \6206#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \
6247do { \6207do { \
6248 if (tb[attr]) { \6208 if (tb[attr]) { \
6249 if (fn(tb[attr], min, max, &cfg->param)) \6209 cfg->param = fn(tb[attr]); \
6250 return -EINVAL; \6210 mask |= BIT((attr) - 1); \
6251 mask |= (1 << (attr - 1)); \6211 } \
6252 } \
6253} while (0)6212} while (0)
6254 6213
6255 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])6214 if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
@@ -6264,75 +6223,73 @@ do { \ · 8 unmodified lines
6264 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);6223 BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32);
6265 6224
6266 /* Fill in the params struct */6225 /* Fill in the params struct */
6267 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255,6226 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask,
6268 mask, NL80211_MESHCONF_RETRY_TIMEOUT,6227 NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16);
6269 nl80211_check_u16);6228 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask,
6270 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255,6229 NL80211_MESHCONF_CONFIRM_TIMEOUT,
6271 mask, NL80211_MESHCONF_CONFIRM_TIMEOUT,6230 nla_get_u16);
6272 nl80211_check_u16);6231 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask,
6273 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255,6232 NL80211_MESHCONF_HOLDING_TIMEOUT,
6274 mask, NL80211_MESHCONF_HOLDING_TIMEOUT,6233 nla_get_u16);
6275 nl80211_check_u16);6234 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask,
6276 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255,6235 NL80211_MESHCONF_MAX_PEER_LINKS,
6277 mask, NL80211_MESHCONF_MAX_PEER_LINKS,6236 nla_get_u16);
6278 nl80211_check_u16);6237 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask,
6279 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16,6238 NL80211_MESHCONF_MAX_RETRIES, nla_get_u8);
6280 mask, NL80211_MESHCONF_MAX_RETRIES,6239 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask,
6281 nl80211_check_u8);6240 NL80211_MESHCONF_TTL, nla_get_u8);
6282 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255,6241 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask,
6283 mask, NL80211_MESHCONF_TTL, nl80211_check_u8);6242 NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8);
6284 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255,6243 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask,
6285 mask, NL80211_MESHCONF_ELEMENT_TTL,6244 NL80211_MESHCONF_AUTO_OPEN_PLINKS,
6286 nl80211_check_u8);6245 nla_get_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);
6290 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,6246 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
6291 1, 255, mask,6247 mask,
6292 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,6248 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
6293 nl80211_check_u32);6249 nla_get_u32);
6294 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255,6250 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask,
6295 mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,6251 NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
6296 nl80211_check_u8);6252 nla_get_u8);
6297 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535,6253 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask,
6298 mask, NL80211_MESHCONF_PATH_REFRESH_TIME,6254 NL80211_MESHCONF_PATH_REFRESH_TIME,
6299 nl80211_check_u32);6255 nla_get_u32);
6300 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535,6256 if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) &&
6301 mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,6257 (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535))
6302 nl80211_check_u16);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);
6303 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,6262 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
6304 1, 65535, mask,6263 mask,
6305 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,6264 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
6306 nl80211_check_u32);6265 nla_get_u32);
6307 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,6266 if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) &&
6308 1, 65535, mask,6267 (cfg->dot11MeshHWMPactivePathTimeout < 1 ||
6268 cfg->dot11MeshHWMPactivePathTimeout > 65535))
6269 return -EINVAL;
6270 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask,
6309 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,6271 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
6310 nl80211_check_u16);6272 nla_get_u16);
6311 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,6273 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask,
6312 1, 65535, mask,
6313 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,6274 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
6314 nl80211_check_u16);6275 nla_get_u16);
6315 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,6276 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
6316 dot11MeshHWMPnetDiameterTraversalTime,6277 dot11MeshHWMPnetDiameterTraversalTime, mask,
6317 1, 65535, mask,
6318 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,6278 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
6319 nl80211_check_u16);6279 nla_get_u16);
6320 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4,6280 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask,
6321 mask, NL80211_MESHCONF_HWMP_ROOTMODE,6281 NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8);
6322 nl80211_check_u8);6282 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask,
6323 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535,6283 NL80211_MESHCONF_HWMP_RANN_INTERVAL,
6324 mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL,6284 nla_get_u16);
6325 nl80211_check_u16);6285 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol,
6326 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
6327 dot11MeshGateAnnouncementProtocol, 0, 1,
6328 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,6286 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
6329 nl80211_check_bool);6287 nla_get_u8);
6330 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,6288 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask,
6331 mask, NL80211_MESHCONF_FORWARDING,6289 NL80211_MESHCONF_FORWARDING, nla_get_u8);
6332 nl80211_check_bool);6290 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask,
6333 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,6291 NL80211_MESHCONF_RSSI_THRESHOLD,
6334 mask, NL80211_MESHCONF_RSSI_THRESHOLD,6292 nla_get_s32);
6335 nl80211_check_s32);
6336 /*6293 /*
6337 * Check HT operation mode based on6294 * Check HT operation mode based on
6338 * IEEE 802.11-2016 9.4.2.57 HT Operation element.6295 * IEEE 802.11-2016 9.4.2.57 HT Operation element.
@@ -6351,29 +6308,27 @@ do { \ · 12 unmodified lines
6351 cfg->ht_opmode = ht_opmode;6308 cfg->ht_opmode = ht_opmode;
6352 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));6309 mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
6353 }6310 }
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);
6361 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,6311 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
6362 dot11MeshHWMPconfirmationInterval,6312 dot11MeshHWMPactivePathToRootTimeout, mask,
6363 1, 65535, 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,
6364 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,6324 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
6365 nl80211_check_u16);6325 nla_get_u16);
6366 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode,6326 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask,
6367 NL80211_MESH_POWER_ACTIVE,6327 NL80211_MESHCONF_POWER_MODE, nla_get_u32);
6368 NL80211_MESH_POWER_MAX,6328 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask,
6369 mask, NL80211_MESHCONF_POWER_MODE,6329 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
6370 nl80211_check_power_mode);6330 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask,
6371 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,6331 NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32);
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);
6377 if (mask_out)6332 if (mask_out)
6378 *mask_out = mask;6333 *mask_out = mask;
6379 6334
@@ -6416,8 +6371,6 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, · 36 unmodified lines
6416 if (tb[NL80211_MESH_SETUP_IE]) {6371 if (tb[NL80211_MESH_SETUP_IE]) {
6417 struct nlattr *ieattr =6372 struct nlattr *ieattr =
6418 tb[NL80211_MESH_SETUP_IE];6373 tb[NL80211_MESH_SETUP_IE];
6419 if (!is_valid_ie_attr(ieattr))
6420 return -EINVAL;
6421 setup->ie = nla_data(ieattr);6374 setup->ie = nla_data(ieattr);
6422 setup->ie_len = nla_len(ieattr);6375 setup->ie_len = nla_len(ieattr);
6423 }6376 }
@@ -7050,9 +7003,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) · 626 unmodified lines
7050 int err, tmp, n_ssids = 0, n_channels, i;7003 int err, tmp, n_ssids = 0, n_channels, i;
7051 size_t ie_len;7004 size_t ie_len;
7052 7005
7053 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
7054 return -EINVAL;
7055
7056 wiphy = &rdev->wiphy;7006 wiphy = &rdev->wiphy;
7057 7007
7058 if (wdev->iftype == NL80211_IFTYPE_NAN)7008 if (wdev->iftype == NL80211_IFTYPE_NAN)
@@ -7406,9 +7356,6 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, · 347 unmodified lines
7406 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];7356 struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
7407 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;7357 s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
7408 7358
7409 if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
7410 return ERR_PTR(-EINVAL);
7411
7412 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {7359 if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
7413 n_channels = validate_scan_freqs(7360 n_channels = validate_scan_freqs(
7414 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);7361 attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
@@ -7768,7 +7715,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, · 353 unmodified lines
7768 */7715 */
7769 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1) {7716 if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1) {
7770 while (!sched_scan_req->reqid)7717 while (!sched_scan_req->reqid)
7771 sched_scan_req->reqid = rdev->wiphy.cookie_counter++;7718 sched_scan_req->reqid = cfg80211_assign_cookie(rdev);
7772 }7719 }
7773 7720
7774 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);7721 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
7944 if (!need_new_beacon)7891 if (!need_new_beacon)
7945 goto skip_beacons;7892 goto skip_beacons;
7946 7893
7947 err = nl80211_parse_beacon(info->attrs, &params.beacon_after);7894 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
7948 if (err)7895 if (err)
7949 return err;7896 return err;
7950 7897
@@ -7954,7 +7901,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) · 3 unmodified lines
7954 if (err)7901 if (err)
7955 return err;7902 return err;
7956 7903
7957 err = nl80211_parse_beacon(csa_attrs, &params.beacon_csa);7904 err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa);
7958 if (err)7905 if (err)
7959 return err;7906 return err;
7960 7907
@@ -8191,7 +8138,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) · 230 unmodified lines
8191 int err;8138 int err;
8192 8139
8193 rtnl_lock();8140 rtnl_lock();
8194 err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);8141 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
8195 if (err) {8142 if (err) {
8196 rtnl_unlock();8143 rtnl_unlock();
8197 return err;8144 return err;
@@ -8312,7 +8259,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) · 114 unmodified lines
8312 bool radio_stats;8259 bool radio_stats;
8313 8260
8314 rtnl_lock();8261 rtnl_lock();
8315 res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);8262 res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
8316 if (res)8263 if (res)
8317 goto out_err;8264 goto out_err;
8318 8265
@@ -8376,9 +8323,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) · 57 unmodified lines
8376 struct key_parse key;8323 struct key_parse key;
8377 bool local_state_change;8324 bool local_state_change;
8378 8325
8379 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8380 return -EINVAL;
8381
8382 if (!info->attrs[NL80211_ATTR_MAC])8326 if (!info->attrs[NL80211_ATTR_MAC])
8383 return -EINVAL;8327 return -EINVAL;
8384 8328
@@ -8617,9 +8561,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) · 232 unmodified lines
8617 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)8561 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
8618 return -EPERM;8562 return -EPERM;
8619 8563
8620 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8621 return -EINVAL;
8622
8623 if (!info->attrs[NL80211_ATTR_MAC] ||8564 if (!info->attrs[NL80211_ATTR_MAC] ||
8624 !info->attrs[NL80211_ATTR_SSID] ||8565 !info->attrs[NL80211_ATTR_SSID] ||
8625 !info->attrs[NL80211_ATTR_WIPHY_FREQ])8566 !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
8743 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)8684 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
8744 return -EPERM;8685 return -EPERM;
8745 8686
8746 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8747 return -EINVAL;
8748
8749 if (!info->attrs[NL80211_ATTR_MAC])8687 if (!info->attrs[NL80211_ATTR_MAC])
8750 return -EINVAL;8688 return -EINVAL;
8751 8689
@@ -8794,9 +8732,6 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) · 42 unmodified lines
8794 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)8732 dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid)
8795 return -EPERM;8733 return -EPERM;
8796 8734
8797 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8798 return -EINVAL;
8799
8800 if (!info->attrs[NL80211_ATTR_MAC])8735 if (!info->attrs[NL80211_ATTR_MAC])
8801 return -EINVAL;8736 return -EINVAL;
8802 8737
@@ -8871,9 +8806,6 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) · 68 unmodified lines
8871 8806
8872 memset(&ibss, 0, sizeof(ibss));8807 memset(&ibss, 0, sizeof(ibss));
8873 8808
8874 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
8875 return -EINVAL;
8876
8877 if (!info->attrs[NL80211_ATTR_SSID] ||8809 if (!info->attrs[NL80211_ATTR_SSID] ||
8878 !nla_len(info->attrs[NL80211_ATTR_SSID]))8810 !nla_len(info->attrs[NL80211_ATTR_SSID]))
8879 return -EINVAL;8811 return -EINVAL;
@@ -9311,9 +9243,6 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) · 431 unmodified lines
9311 9243
9312 memset(&connect, 0, sizeof(connect));9244 memset(&connect, 0, sizeof(connect));
9313 9245
9314 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
9315 return -EINVAL;
9316
9317 if (!info->attrs[NL80211_ATTR_SSID] ||9246 if (!info->attrs[NL80211_ATTR_SSID] ||
9318 !nla_len(info->attrs[NL80211_ATTR_SSID]))9247 !nla_len(info->attrs[NL80211_ATTR_SSID]))
9319 return -EINVAL;9248 return -EINVAL;
@@ -9372,11 +9301,6 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) · 52 unmodified lines
9372 !wiphy_ext_feature_isset(&rdev->wiphy,9301 !wiphy_ext_feature_isset(&rdev->wiphy,
9373 NL80211_EXT_FEATURE_MFP_OPTIONAL))9302 NL80211_EXT_FEATURE_MFP_OPTIONAL))
9374 return -EOPNOTSUPP;9303 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;
9380 } else {9304 } else {
9381 connect.mfp = NL80211_MFP_NO;9305 connect.mfp = NL80211_MFP_NO;
9382 }9306 }
@@ -9549,8 +9473,6 @@ static int nl80211_update_connect_params(struct sk_buff *skb, · 166 unmodified lines
9549 return -EOPNOTSUPP;9473 return -EOPNOTSUPP;
9550 9474
9551 if (info->attrs[NL80211_ATTR_IE]) {9475 if (info->attrs[NL80211_ATTR_IE]) {
9552 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
9553 return -EINVAL;
9554 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);9476 connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
9555 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);9477 connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
9556 changed |= UPDATE_ASSOC_IES;9478 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
10135 10057
10136 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);10058 ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]);
10137 10059
10138 if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED)
10139 return -EINVAL;
10140
10141 wdev = dev->ieee80211_ptr;10060 wdev = dev->ieee80211_ptr;
10142 10061
10143 if (!rdev->ops->set_power_mgmt)10062 if (!rdev->ops->set_power_mgmt)
@@ -10700,8 +10619,7 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg, · 556 unmodified lines
10700 if (!scan_plan)10619 if (!scan_plan)
10701 return -ENOBUFS;10620 return -ENOBUFS;
10702 10621
10703 if (!scan_plan ||10622 if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
10704 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
10705 req->scan_plans[i].interval) ||10623 req->scan_plans[i].interval) ||
10706 (req->scan_plans[i].iterations &&10624 (req->scan_plans[i].iterations &&
10707 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,10625 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
11299 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])11217 if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION])
11300 new_rule->condition =11218 new_rule->condition =
11301 nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);11219 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;
11305 11220
11306 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])11221 if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN])
11307 return -EINVAL;11222 return -EINVAL;
@@ -11654,8 +11569,6 @@ static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info) · 346 unmodified lines
11654 11569
11655 conf.master_pref =11570 conf.master_pref =
11656 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);11571 nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
11657 if (!conf.master_pref)
11658 return -EINVAL;
11659 11572
11660 if (info->attrs[NL80211_ATTR_BANDS]) {11573 if (info->attrs[NL80211_ATTR_BANDS]) {
11661 u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]);11574 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
11773 if (!func)11686 if (!func)
11774 return -ENOMEM;11687 return -ENOMEM;
11775 11688
11776 func->cookie = wdev->wiphy->cookie_counter++;11689 func->cookie = cfg80211_assign_cookie(rdev);
11777 11690
11778 if (!tb[NL80211_NAN_FUNC_TYPE] ||11691 if (!tb[NL80211_NAN_FUNC_TYPE] ||
11779 nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]) > NL80211_NAN_FUNC_MAX_TYPE) {11692 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
12219 return -EOPNOTSUPP;12132 return -EOPNOTSUPP;
12220 12133
12221 if (!info->attrs[NL80211_ATTR_MDID] ||12134 if (!info->attrs[NL80211_ATTR_MDID] ||
12222 !info->attrs[NL80211_ATTR_IE] ||12135 !info->attrs[NL80211_ATTR_IE])
12223 !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
12224 return -EINVAL;12136 return -EINVAL;
12225 12137
12226 memset(&ft_params, 0, sizeof(ft_params));12138 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
12640 return -EINVAL;12552 return -EINVAL;
12641 12553
12642 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);12554 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
12643 if (tsid >= IEEE80211_NUM_TIDS)
12644 return -EINVAL;
12645
12646 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);12555 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
12647 if (up >= IEEE80211_NUM_UPS)
12648 return -EINVAL;
12649 12556
12650 /* WMM uses TIDs 0-7 even for TSPEC */12557 /* WMM uses TIDs 0-7 even for TSPEC */
12651 if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {12558 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
13003 return err;12910 return err;
13004}12911}
13005 12912
12913static 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
12978nla_put_failure:
12979 nlmsg_free(msg);
12980 return -ENOBUFS;
12981}
12982
13006#define NL80211_FLAG_NEED_WIPHY 0x0112983#define NL80211_FLAG_NEED_WIPHY 0x01
13007#define NL80211_FLAG_NEED_NETDEV 0x0212984#define NL80211_FLAG_NEED_NETDEV 0x02
13008#define NL80211_FLAG_NEED_RTNL 0x0412985#define NL80211_FLAG_NEED_RTNL 0x04
@@ -13914,6 +13891,13 @@ static const struct genl_ops nl80211_ops[] = { · 905 unmodified lines
13914 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |13891 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
13915 NL80211_FLAG_NEED_RTNL,13892 NL80211_FLAG_NEED_RTNL,
13916 },13893 },
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 },
13917};13901};
13918 13902
13919static struct genl_family nl80211_fam __ro_after_init = {13903static 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
1232 return ret;1232 return ret;
1233}1233}
1234 1234
1235static inline int
1236rdev_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
1235#endif /* __CFG80211_RDEV_OPS */1250#endif /* __CFG80211_RDEV_OPS */
net/wireless/reg.c+9−0
@@ -3831,6 +3831,15 @@ static int __init regulatory_init_db(void) · 3830 unmodified lines
3831{3831{
3832 int err;3832 int err;
3833 3833
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
3834 err = load_builtin_regdb_keys();3843 err = load_builtin_regdb_keys();
3835 if (err)3844 if (err)
3836 return err;3845 return err;
net/wireless/trace.h+134−99
@@ -2368,6 +2368,140 @@ TRACE_EVENT(rdev_external_auth, · 2367 unmodified lines
2368 __entry->bssid, __entry->ssid, __entry->status)2368 __entry->bssid, __entry->ssid, __entry->status)
2369);2369);
2370 2370
2371TRACE_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
2394TRACE_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
2417TRACE_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
2432DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan,
2433 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
2434 TP_ARGS(wiphy, wdev)
2435);
2436
2437TRACE_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
2456DEFINE_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
2461TRACE_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
2371/*************************************************************2505/*************************************************************
2372 * cfg80211 exported functions traces *2506 * cfg80211 exported functions traces *
2373 *************************************************************/2507 *************************************************************/
@@ -3160,105 +3294,6 @@ TRACE_EVENT(cfg80211_stop_iface, · 786 unmodified lines
3160 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,3294 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
3161 WIPHY_PR_ARG, WDEV_PR_ARG)3295 WIPHY_PR_ARG, WDEV_PR_ARG)
3162);3296);
3163
3164TRACE_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
3187TRACE_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
3210TRACE_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
3225DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan,
3226 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
3227 TP_ARGS(wiphy, wdev)
3228);
3229
3230TRACE_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
3249TRACE_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);
3262#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */3297#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
3263 3298
3264#undef TRACE_INCLUDE_PATH3299#undef TRACE_INCLUDE_PATH