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 ====================
Unified · Split
| @@ -495,7 +495,6 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = { · 494 unmodified lines | |||
| 495 | 495 | ||
| 496 | static spinlock_t hwsim_radio_lock; | 496 | static spinlock_t hwsim_radio_lock; |
| 497 | static LIST_HEAD(hwsim_radios); | 497 | static LIST_HEAD(hwsim_radios); |
| 498 | static struct workqueue_struct *hwsim_wq; | ||
| 499 | static struct rhashtable hwsim_radios_rht; | 498 | static struct rhashtable hwsim_radios_rht; |
| 500 | static int hwsim_radio_idx; | 499 | static int hwsim_radio_idx; |
| 501 | static int hwsim_radios_generation = 1; | 500 | static 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); |
| 3830 | out_free_rht: | 3825 | out_free_rht: |
| 3831 | rhashtable_destroy(&hwsim_radios_rht); | 3826 | rhashtable_destroy(&hwsim_radios_rht); |
| 3832 | out_free_wq: | ||
| 3833 | destroy_workqueue(hwsim_wq); | ||
| 3834 | return err; | 3827 | return err; |
| 3835 | } | 3828 | } |
| 3836 | module_init(init_mac80211_hwsim); | 3829 | module_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 | } |
| 3853 | module_exit(exit_mac80211_hwsim); | 3844 | module_exit(exit_mac80211_hwsim); |
| @@ -1670,6 +1670,7 @@ struct ieee80211_mu_edca_param_set { · 1669 unmodified lines | |||
| 1670 | #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 | 1670 | #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 |
| 1671 | #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 | 1671 | #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 |
| 1672 | #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 | 1672 | #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 |
| 1673 | #define IEEE80211_VHT_CAP_RXSTBC_SHIFT 8 | ||
| 1673 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 | 1674 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 |
| 1674 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 | 1675 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 |
| 1675 | #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13 | 1676 | #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13 |
| @@ -775,6 +775,12 @@ struct cfg80211_crypto_settings { · 774 unmodified lines | |||
| 775 | * @assocresp_ies_len: length of assocresp_ies in octets | 775 | * @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 | */ |
| 779 | struct cfg80211_beacon_data { | 785 | struct 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 | ||
| 793 | struct mac_address { | 804 | struct 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 has | 1304 | * @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 | */ |
| 1296 | struct station_info { | 1311 | struct 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 | */ | ||
| 2838 | struct cfg80211_ftm_responder_stats { | ||
| 2839 | u32 filled; | ||
| 2840 | u32 success_num; | ||
| 2841 | u32 partial_num; | ||
| 2842 | u32 failed_num; | ||
| 2843 | u32 asap_num; | ||
| 2844 | u32 non_asap_num; | ||
| 2845 | u64 total_duration_ms; | ||
| 2846 | u32 unknown_triggers_num; | ||
| 2847 | u32 reschedule_requests_num; | ||
| 2848 | u32 out_of_window_triggers_num; | ||
| 2849 | }; | ||
| 2850 | |||
| 2799 | /** | 2851 | /** |
| 2800 | * struct cfg80211_ops - backend description for wireless configuration | 2852 | * 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 parameter | 3181 | * @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 | */ |
| 3132 | struct cfg80211_ops { | 3187 | struct 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 the | 4019 | * 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, a | 4022 | * @nan_supported_bands: bands supported by the device in NAN mode, a |
| 3965 | * bitmap of &enum nl80211_band values. For instance, for | 4023 | * bitmap of &enum nl80211_band values. For instance, for |
| 3966 | * NL80211_BAND_2GHZ, bit 0 would be set | 4024 | * 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; |
| @@ -309,6 +309,8 @@ struct ieee80211_vif_chanctx_switch { · 308 unmodified lines | |||
| 309 | * @BSS_CHANGED_KEEP_ALIVE: keep alive options (idle period or protected | 309 | * @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 interface | 311 | * @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 | */ |
| 314 | enum ieee80211_bss_change { | 316 | enum 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 | */ | ||
| 477 | struct ieee80211_ftm_responder_params { | ||
| 478 | const u8 *lci; | ||
| 479 | const u8 *civicloc; | ||
| 480 | size_t lci_len; | ||
| 481 | size_t civicloc_len; | ||
| 482 | }; | ||
| 483 | |||
| 466 | /** | 484 | /** |
| 467 | * struct ieee80211_bss_conf - holds the BSS's changing parameters | 485 | * 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 RSN | 580 | * @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 the | 581 | * 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 | */ |
| 566 | struct ieee80211_bss_conf { | 587 | struct 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 relation | 3621 | * aggregating two specific frames in the same A-MSDU. The relation |
| 3599 | * between the skbs should be symmetric and transitive. Note that while | 3622 | * 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 | */ |
| 3602 | struct ieee80211_ops { | 3627 | struct 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 | |||
| 4351 | void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta, | 4379 | void 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 | */ | ||
| 4393 | void 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 callback | 4398 | * ieee80211_tx_status - transmit status callback |
| 4356 | * | 4399 | * |
| @@ -1033,6 +1033,9 @@ · 1032 unmodified lines | |||
| 1033 | * %NL80211_ATTR_CHANNEL_WIDTH,%NL80211_ATTR_NSS attributes with its | 1033 | * %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 number | 1039 | * @NL80211_CMD_MAX: highest used command number |
| 1037 | * @__NL80211_CMD_AFTER_LAST: internal use | 1040 | * @__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 set | 2246 | * 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 available | 2257 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
| 2245 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 2258 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| 2246 | * @__NL80211_ATTR_AFTER_LAST: internal use | 2259 | * @__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 alignment | 3068 | * @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: internal | 3077 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
| 3055 | * @NL80211_STA_INFO_MAX: highest possible station info attribute | 3078 | * @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 data | 5250 | * @NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT: Driver/device can omit all data |
| 5226 | * except for supported rates from the probe request content if requested | 5251 | * 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 are | 5256 | * @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 keys | 5257 | * 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 | */ | ||
| 5851 | enum nl80211_ftm_responder_attributes { | ||
| 5852 | __NL80211_FTM_RESP_ATTR_INVALID, | ||
| 5853 | |||
| 5854 | NL80211_FTM_RESP_ATTR_ENABLED, | ||
| 5855 | NL80211_FTM_RESP_ATTR_LCI, | ||
| 5856 | NL80211_FTM_RESP_ATTR_CIVICLOC, | ||
| 5857 | |||
| 5858 | /* keep last */ | ||
| 5859 | __NL80211_FTM_RESP_ATTR_LAST, | ||
| 5860 | NL80211_FTM_RESP_ATTR_MAX = __NL80211_FTM_RESP_ATTR_LAST - 1, | ||
| 5861 | }; | ||
| 5862 | |||
| 5863 | /* | ||
| 5864 | * enum nl80211_ftm_responder_stats - FTM responder statistics | ||
| 5865 | * | ||
| 5866 | * These attribute types are used with %NL80211_ATTR_FTM_RESPONDER_STATS | ||
| 5867 | * when getting FTM responder statistics. | ||
| 5868 | * | ||
| 5869 | * @__NL80211_FTM_STATS_INVALID: attribute number 0 is reserved | ||
| 5870 | * @NL80211_FTM_STATS_SUCCESS_NUM: number of FTM sessions in which all frames | ||
| 5871 | * were ssfully answered (u32) | ||
| 5872 | * @NL80211_FTM_STATS_PARTIAL_NUM: number of FTM sessions in which part of the | ||
| 5873 | * frames were successfully answered (u32) | ||
| 5874 | * @NL80211_FTM_STATS_FAILED_NUM: number of failed FTM sessions (u32) | ||
| 5875 | * @NL80211_FTM_STATS_ASAP_NUM: number of ASAP sessions (u32) | ||
| 5876 | * @NL80211_FTM_STATS_NON_ASAP_NUM: number of non-ASAP sessions (u32) | ||
| 5877 | * @NL80211_FTM_STATS_TOTAL_DURATION_MSEC: total sessions durations - gives an | ||
| 5878 | * indication of how much time the responder was busy (u64, msec) | ||
| 5879 | * @NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM: number of unknown FTM triggers - | ||
| 5880 | * triggers from initiators that didn't finish successfully the negotiation | ||
| 5881 | * phase with the responder (u32) | ||
| 5882 | * @NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM: number of FTM reschedule requests | ||
| 5883 | * - initiator asks for a new scheduling although it already has scheduled | ||
| 5884 | * FTM slot (u32) | ||
| 5885 | * @NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM: number of FTM triggers out of | ||
| 5886 | * scheduled window (u32) | ||
| 5887 | * @NL80211_FTM_STATS_PAD: used for padding, ignore | ||
| 5888 | * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal | ||
| 5889 | * @NL80211_FTM_STATS_MAX: highest possible FTM responder stats attribute | ||
| 5890 | */ | ||
| 5891 | enum nl80211_ftm_responder_stats { | ||
| 5892 | __NL80211_FTM_STATS_INVALID, | ||
| 5893 | NL80211_FTM_STATS_SUCCESS_NUM, | ||
| 5894 | NL80211_FTM_STATS_PARTIAL_NUM, | ||
| 5895 | NL80211_FTM_STATS_FAILED_NUM, | ||
| 5896 | NL80211_FTM_STATS_ASAP_NUM, | ||
| 5897 | NL80211_FTM_STATS_NON_ASAP_NUM, | ||
| 5898 | NL80211_FTM_STATS_TOTAL_DURATION_MSEC, | ||
| 5899 | NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM, | ||
| 5900 | NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM, | ||
| 5901 | NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM, | ||
| 5902 | NL80211_FTM_STATS_PAD, | ||
| 5903 | |||
| 5904 | /* keep last */ | ||
| 5905 | __NL80211_FTM_STATS_AFTER_LAST, | ||
| 5906 | NL80211_FTM_STATS_MAX = __NL80211_FTM_STATS_AFTER_LAST - 1 | ||
| 5907 | }; | ||
| 5908 | |||
| 5811 | #endif /* __LINUX_NL80211_H */ | 5909 | #endif /* __LINUX_NL80211_H */ |
| @@ -27,20 +27,6 @@ config MAC80211_RC_MINSTREL · 26 unmodified lines | |||
| 27 | ---help--- | 27 | ---help--- |
| 28 | This option enables the 'minstrel' TX rate control algorithm | 28 | This option enables the 'minstrel' TX rate control algorithm |
| 29 | 29 | ||
| 30 | config MAC80211_RC_MINSTREL_HT | ||
| 31 | bool "Minstrel 802.11n support" if EXPERT | ||
| 32 | depends on MAC80211_RC_MINSTREL | ||
| 33 | default y | ||
| 34 | ---help--- | ||
| 35 | This option enables the 'minstrel_ht' TX rate control algorithm | ||
| 36 | |||
| 37 | config MAC80211_RC_MINSTREL_VHT | ||
| 38 | bool "Minstrel 802.11ac support" if EXPERT | ||
| 39 | depends on MAC80211_RC_MINSTREL_HT | ||
| 40 | default n | ||
| 41 | ---help--- | ||
| 42 | This option enables VHT in the 'minstrel_ht' TX rate control algorithm | ||
| 43 | |||
| 44 | choice | 30 | choice |
| 45 | prompt "Default rate control algorithm" | 31 | prompt "Default rate control algorithm" |
| 46 | depends on MAC80211_HAS_RC | 32 | depends on MAC80211_HAS_RC |
| @@ -62,8 +48,7 @@ endchoice · 15 unmodified lines | |||
| 62 | 48 | ||
| 63 | config MAC80211_RC_DEFAULT | 49 | config MAC80211_RC_DEFAULT |
| 64 | string | 50 | string |
| 65 | default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT | 51 | default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL |
| 66 | default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL | ||
| 67 | default "" | 52 | default "" |
| 68 | 53 | ||
| 69 | endif | 54 | endif |
| @@ -53,13 +53,14 @@ mac80211-$(CONFIG_PM) += pm.o · 52 unmodified lines | |||
| 53 | 53 | ||
| 54 | CFLAGS_trace.o := -I$(src) | 54 | CFLAGS_trace.o := -I$(src) |
| 55 | 55 | ||
| 56 | rc80211_minstrel-y := rc80211_minstrel.o | 56 | rc80211_minstrel-y := \ |
| 57 | rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o | 57 | rc80211_minstrel.o \ |
| 58 | rc80211_minstrel_ht.o | ||
| 58 | 59 | ||
| 59 | rc80211_minstrel_ht-y := rc80211_minstrel_ht.o | 60 | rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += \ |
| 60 | rc80211_minstrel_ht-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o | 61 | rc80211_minstrel_debugfs.o \ |
| 62 | rc80211_minstrel_ht_debugfs.o | ||
| 61 | 63 | ||
| 62 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) | 64 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) |
| 63 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y) | ||
| 64 | 65 | ||
| 65 | ccflags-y += -DDEBUG | 66 | ccflags-y += -DDEBUG |
| @@ -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 | ||
| 793 | static int ieee80211_set_ftm_responder_params( | ||
| 794 | struct ieee80211_sub_if_data *sdata, | ||
| 795 | const u8 *lci, size_t lci_len, | ||
| 796 | const u8 *civicloc, size_t civicloc_len) | ||
| 797 | { | ||
| 798 | struct ieee80211_ftm_responder_params *new, *old; | ||
| 799 | struct ieee80211_bss_conf *bss_conf; | ||
| 800 | u8 *pos; | ||
| 801 | int len; | ||
| 802 | |||
| 803 | if ((!lci || !lci_len) && (!civicloc || !civicloc_len)) | ||
| 804 | return 1; | ||
| 805 | |||
| 806 | bss_conf = &sdata->vif.bss_conf; | ||
| 807 | old = bss_conf->ftmr_params; | ||
| 808 | len = lci_len + civicloc_len; | ||
| 809 | |||
| 810 | new = kzalloc(sizeof(*new) + len, GFP_KERNEL); | ||
| 811 | if (!new) | ||
| 812 | return -ENOMEM; | ||
| 813 | |||
| 814 | pos = (u8 *)(new + 1); | ||
| 815 | if (lci_len) { | ||
| 816 | new->lci_len = lci_len; | ||
| 817 | new->lci = pos; | ||
| 818 | memcpy(pos, lci, lci_len); | ||
| 819 | pos += lci_len; | ||
| 820 | } | ||
| 821 | |||
| 822 | if (civicloc_len) { | ||
| 823 | new->civicloc_len = civicloc_len; | ||
| 824 | new->civicloc = pos; | ||
| 825 | memcpy(pos, civicloc, civicloc_len); | ||
| 826 | pos += civicloc_len; | ||
| 827 | } | ||
| 828 | |||
| 829 | bss_conf->ftmr_params = new; | ||
| 830 | kfree(old); | ||
| 831 | |||
| 832 | return 0; | ||
| 833 | } | ||
| 834 | |||
| 793 | static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, | 835 | static 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 | ||
| 3841 | static int | ||
| 3842 | ieee80211_get_ftm_responder_stats(struct wiphy *wiphy, | ||
| 3843 | struct net_device *dev, | ||
| 3844 | struct cfg80211_ftm_responder_stats *ftm_stats) | ||
| 3845 | { | ||
| 3846 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
| 3847 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 3848 | |||
| 3849 | return drv_get_ftm_responder_stats(local, sdata, ftm_stats); | ||
| 3850 | } | ||
| 3851 | |||
| 3768 | const struct cfg80211_ops mac80211_config_ops = { | 3852 | const 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 | }; |
| @@ -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 | ||
| 1186 | static inline int | ||
| 1187 | drv_get_ftm_responder_stats(struct ieee80211_local *local, | ||
| 1188 | struct ieee80211_sub_if_data *sdata, | ||
| 1189 | struct cfg80211_ftm_responder_stats *ftm_stats) | ||
| 1190 | { | ||
| 1191 | u32 ret = -EOPNOTSUPP; | ||
| 1192 | |||
| 1193 | if (local->ops->get_ftm_responder_stats) | ||
| 1194 | ret = local->ops->get_ftm_responder_stats(&local->hw, | ||
| 1195 | &sdata->vif, | ||
| 1196 | ftm_stats); | ||
| 1197 | trace_drv_get_ftm_responder_stats(local, sdata, ftm_stats); | ||
| 1198 | |||
| 1199 | return ret; | ||
| 1200 | } | ||
| 1201 | |||
| 1186 | static inline int drv_start_nan(struct ieee80211_local *local, | 1202 | static 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) |
| @@ -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; |
| @@ -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 | ||
| 1393 | static void __exit ieee80211_exit(void) | 1389 | static 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(); |
| @@ -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 | ||
| 2764 | static bool ieee80211_mark_sta_auth(struct ieee80211_sub_if_data *sdata, | ||
| 2765 | const u8 *bssid) | ||
| 2766 | { | ||
| 2767 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
| 2768 | struct sta_info *sta; | ||
| 2769 | |||
| 2770 | sdata_info(sdata, "authenticated\n"); | ||
| 2771 | ifmgd->auth_data->done = true; | ||
| 2772 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; | ||
| 2773 | ifmgd->auth_data->timeout_started = true; | ||
| 2774 | run_again(sdata, ifmgd->auth_data->timeout); | ||
| 2775 | |||
| 2776 | /* move station state to auth */ | ||
| 2777 | mutex_lock(&sdata->local->sta_mtx); | ||
| 2778 | sta = sta_info_get(sdata, bssid); | ||
| 2779 | if (!sta) { | ||
| 2780 | WARN_ONCE(1, "%s: STA %pM not found", sdata->name, bssid); | ||
| 2781 | return false; | ||
| 2782 | } | ||
| 2783 | if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) { | ||
| 2784 | sdata_info(sdata, "failed moving %pM to auth\n", bssid); | ||
| 2785 | return false; | ||
| 2786 | } | ||
| 2787 | mutex_unlock(&sdata->local->sta_mtx); | ||
| 2788 | |||
| 2789 | return true; | ||
| 2790 | } | ||
| 2791 | |||
| 2764 | static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | 2792 | static 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 | } |
| @@ -95,18 +95,5 @@ static inline void rc80211_minstrel_exit(void) · 94 unmodified lines | |||
| 95 | } | 95 | } |
| 96 | #endif | 96 | #endif |
| 97 | 97 | ||
| 98 | #ifdef CONFIG_MAC80211_RC_MINSTREL_HT | ||
| 99 | int rc80211_minstrel_ht_init(void); | ||
| 100 | void rc80211_minstrel_ht_exit(void); | ||
| 101 | #else | ||
| 102 | static inline int rc80211_minstrel_ht_init(void) | ||
| 103 | { | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | static inline void rc80211_minstrel_ht_exit(void) | ||
| 107 | { | ||
| 108 | } | ||
| 109 | #endif | ||
| 110 | |||
| 111 | 98 | ||
| 112 | #endif /* IEEE80211_RATE_H */ | 99 | #endif /* IEEE80211_RATE_H */ |
| @@ -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 | ||
| 575 | static void * | ||
| 576 | minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) | ||
| 577 | { | ||
| 578 | struct ieee80211_supported_band *sband; | ||
| 579 | struct minstrel_sta_info *mi; | ||
| 580 | struct minstrel_priv *mp = priv; | ||
| 581 | struct ieee80211_hw *hw = mp->hw; | ||
| 582 | int max_rates = 0; | ||
| 583 | int i; | ||
| 584 | |||
| 585 | mi = kzalloc(sizeof(struct minstrel_sta_info), gfp); | ||
| 586 | if (!mi) | ||
| 587 | return NULL; | ||
| 588 | |||
| 589 | for (i = 0; i < NUM_NL80211_BANDS; i++) { | ||
| 590 | sband = hw->wiphy->bands[i]; | ||
| 591 | if (sband && sband->n_bitrates > max_rates) | ||
| 592 | max_rates = sband->n_bitrates; | ||
| 593 | } | ||
| 594 | |||
| 595 | mi->r = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp); | ||
| 596 | if (!mi->r) | ||
| 597 | goto error; | ||
| 598 | |||
| 599 | mi->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp); | ||
| 600 | if (!mi->sample_table) | ||
| 601 | goto error1; | ||
| 602 | |||
| 603 | mi->last_stats_update = jiffies; | ||
| 604 | return mi; | ||
| 605 | |||
| 606 | error1: | ||
| 607 | kfree(mi->r); | ||
| 608 | error: | ||
| 609 | kfree(mi); | ||
| 610 | return NULL; | ||
| 611 | } | ||
| 612 | |||
| 613 | static void | ||
| 614 | minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) | ||
| 615 | { | ||
| 616 | struct minstrel_sta_info *mi = priv_sta; | ||
| 617 | |||
| 618 | kfree(mi->sample_table); | ||
| 619 | kfree(mi->r); | ||
| 620 | kfree(mi); | ||
| 621 | } | ||
| 622 | |||
| 623 | static void | ||
| 624 | minstrel_init_cck_rates(struct minstrel_priv *mp) | ||
| 625 | { | ||
| 626 | static const int bitrates[4] = { 10, 20, 55, 110 }; | ||
| 627 | struct ieee80211_supported_band *sband; | ||
| 628 | u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); | ||
| 629 | int i, j; | ||
| 630 | |||
| 631 | sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; | ||
| 632 | if (!sband) | ||
| 633 | return; | ||
| 634 | |||
| 635 | for (i = 0, j = 0; i < sband->n_bitrates; i++) { | ||
| 636 | struct ieee80211_rate *rate = &sband->bitrates[i]; | ||
| 637 | |||
| 638 | if (rate->flags & IEEE80211_RATE_ERP_G) | ||
| 639 | continue; | ||
| 640 | |||
| 641 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
| 642 | continue; | ||
| 643 | |||
| 644 | for (j = 0; j < ARRAY_SIZE(bitrates); j++) { | ||
| 645 | if (rate->bitrate != bitrates[j]) | ||
| 646 | continue; | ||
| 647 | |||
| 648 | mp->cck_rates[j] = i; | ||
| 649 | break; | ||
| 650 | } | ||
| 651 | } | ||
| 652 | } | ||
| 653 | |||
| 654 | static void * | ||
| 655 | minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | ||
| 656 | { | ||
| 657 | struct minstrel_priv *mp; | ||
| 658 | |||
| 659 | mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); | ||
| 660 | if (!mp) | ||
| 661 | return NULL; | ||
| 662 | |||
| 663 | /* contention window settings | ||
| 664 | * Just an approximation. Using the per-queue values would complicate | ||
| 665 | * the calculations and is probably unnecessary */ | ||
| 666 | mp->cw_min = 15; | ||
| 667 | mp->cw_max = 1023; | ||
| 668 | |||
| 669 | /* number of packets (in %) to use for sampling other rates | ||
| 670 | * sample less often for non-mrr packets, because the overhead | ||
| 671 | * is much higher than with mrr */ | ||
| 672 | mp->lookaround_rate = 5; | ||
| 673 | mp->lookaround_rate_mrr = 10; | ||
| 674 | |||
| 675 | /* maximum time that the hw is allowed to stay in one MRR segment */ | ||
| 676 | mp->segment_size = 6000; | ||
| 677 | |||
| 678 | if (hw->max_rate_tries > 0) | ||
| 679 | mp->max_retry = hw->max_rate_tries; | ||
| 680 | else | ||
| 681 | /* safe default, does not necessarily have to match hw properties */ | ||
| 682 | mp->max_retry = 7; | ||
| 683 | |||
| 684 | if (hw->max_rates >= 4) | ||
| 685 | mp->has_mrr = true; | ||
| 686 | |||
| 687 | mp->hw = hw; | ||
| 688 | mp->update_interval = 100; | ||
| 689 | |||
| 690 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
| 691 | mp->fixed_rate_idx = (u32) -1; | ||
| 692 | mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx", | ||
| 693 | 0666, debugfsdir, &mp->fixed_rate_idx); | ||
| 694 | #endif | ||
| 695 | |||
| 696 | minstrel_init_cck_rates(mp); | ||
| 697 | |||
| 698 | return mp; | ||
| 699 | } | ||
| 700 | |||
| 701 | static void | ||
| 702 | minstrel_free(void *priv) | ||
| 703 | { | ||
| 704 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
| 705 | debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate); | ||
| 706 | #endif | ||
| 707 | kfree(priv); | ||
| 708 | } | ||
| 709 | |||
| 710 | static u32 minstrel_get_expected_throughput(void *priv_sta) | 569 | static 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 | ||
| 727 | const struct rate_control_ops mac80211_minstrel = { | 586 | const 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 | |||
| 743 | int __init | ||
| 744 | rc80211_minstrel_init(void) | ||
| 745 | { | ||
| 746 | return ieee80211_rate_control_register(&mac80211_minstrel); | ||
| 747 | } | ||
| 748 | |||
| 749 | void | ||
| 750 | rc80211_minstrel_exit(void) | ||
| 751 | { | ||
| 752 | ieee80211_rate_control_unregister(&mac80211_minstrel); | ||
| 753 | } | ||
| @@ -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 | */ | ||
| 41 | static inline int | ||
| 42 | minstrel_ewmv(int old_ewmv, int cur_prob, int prob_ewma, int weight) | ||
| 43 | { | ||
| 44 | int diff, incr; | ||
| 45 | |||
| 46 | diff = cur_prob - prob_ewma; | ||
| 47 | incr = (EWMA_DIV - weight) * diff / EWMA_DIV; | ||
| 48 | return weight * (old_ewmv + MINSTREL_TRUNC(diff * incr)) / EWMA_DIV; | ||
| 49 | } | ||
| 50 | |||
| 51 | struct minstrel_rate_stats { | 38 | struct 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 probability | 46 | /* 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 | ||
| 119 | struct minstrel_priv { | 98 | struct minstrel_priv { |
| @@ -137,7 +116,6 @@ struct minstrel_priv { · 17 unmodified lines | |||
| 137 | * - setting will be applied on next update | 116 | * - 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 | #endif | 119 | #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 */ | ||
| 150 | static inline int | ||
| 151 | minstrel_get_ewmsd10(struct minstrel_rate_stats *mrs) | ||
| 152 | { | ||
| 153 | unsigned int ewmv = mrs->prob_ewmv; | ||
| 154 | return int_sqrt(MINSTREL_TRUNC(ewmv * 1000 * 1000)); | ||
| 155 | } | ||
| 156 | |||
| 157 | extern const struct rate_control_ops mac80211_minstrel; | 127 | extern const struct rate_control_ops mac80211_minstrel; |
| 158 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | 128 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); |
| 159 | void 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 */ |
| 162 | void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs); | 131 | void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs); |
| @@ -165,7 +134,5 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma); · 2 unmodified lines | |||
| 165 | /* debugfs */ | 134 | /* debugfs */ |
| 166 | int minstrel_stats_open(struct inode *inode, struct file *file); | 135 | int minstrel_stats_open(struct inode *inode, struct file *file); |
| 167 | int minstrel_stats_csv_open(struct inode *inode, struct file *file); | 136 | int minstrel_stats_csv_open(struct inode *inode, struct file *file); |
| 168 | ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); | ||
| 169 | int minstrel_stats_release(struct inode *inode, struct file *file); | ||
| 170 | 137 | ||
| 171 | #endif | 138 | #endif |
| @@ -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 | ||
| 57 | ssize_t | ||
| 58 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) | ||
| 59 | { | ||
| 60 | struct minstrel_debugfs_info *ms; | ||
| 61 | |||
| 62 | ms = file->private_data; | ||
| 63 | return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); | ||
| 64 | } | ||
| 65 | |||
| 66 | int | ||
| 67 | minstrel_stats_release(struct inode *inode, struct file *file) | ||
| 68 | { | ||
| 69 | kfree(file->private_data); | ||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | int | 57 | int |
| 74 | minstrel_stats_open(struct inode *inode, struct file *file) | 58 | minstrel_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 | ||
| 138 | static const struct file_operations minstrel_stat_fops = { | ||
| 139 | .owner = THIS_MODULE, | ||
| 140 | .open = minstrel_stats_open, | ||
| 141 | .read = minstrel_stats_read, | ||
| 142 | .release = minstrel_stats_release, | ||
| 143 | .llseek = default_llseek, | ||
| 144 | }; | ||
| 145 | |||
| 146 | int | 119 | int |
| 147 | minstrel_stats_csv_open(struct inode *inode, struct file *file) | 120 | minstrel_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 | |||
| 204 | static const struct file_operations minstrel_stat_csv_fops = { | ||
| 205 | .owner = THIS_MODULE, | ||
| 206 | .open = minstrel_stats_csv_open, | ||
| 207 | .read = minstrel_stats_read, | ||
| 208 | .release = minstrel_stats_release, | ||
| 209 | .llseek = default_llseek, | ||
| 210 | }; | ||
| 211 | |||
| 212 | void | ||
| 213 | minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) | ||
| 214 | { | ||
| 215 | struct minstrel_sta_info *mi = priv_sta; | ||
| 216 | |||
| 217 | mi->dbg_stats = debugfs_create_file("rc_stats", 0444, dir, mi, | ||
| 218 | &minstrel_stat_fops); | ||
| 219 | |||
| 220 | mi->dbg_stats_csv = debugfs_create_file("rc_stats_csv", 0444, dir, mi, | ||
| 221 | &minstrel_stat_csv_fops); | ||
| 222 | } | ||
| 223 | |||
| 224 | void | ||
| 225 | minstrel_remove_sta_debugfs(void *priv, void *priv_sta) | ||
| 226 | { | ||
| 227 | struct minstrel_sta_info *mi = priv_sta; | ||
| 228 | |||
| 229 | debugfs_remove(mi->dbg_stats); | ||
| 230 | |||
| 231 | debugfs_remove(mi->dbg_stats_csv); | ||
| 232 | } | ||
| @@ -52,22 +52,23 @@ · 51 unmodified lines | |||
| 52 | _streams - 1 | 52 | _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 | ||
| 141 | static bool minstrel_vht_only = true; | 143 | static bool minstrel_vht_only = true; |
| 142 | module_param(minstrel_vht_only, bool, 0644); | 144 | module_param(minstrel_vht_only, bool, 0644); |
| 143 | MODULE_PARM_DESC(minstrel_vht_only, | 145 | MODULE_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 into | 149 | * 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 -> #streams | 154 | * BW -> SGI -> #streams |
| 154 | */ | 155 | */ |
| 155 | const struct mcs_group minstrel_mcs_groups[] = { | 156 | const 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_VHT | 175 | 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 | ||
| 201 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; | 200 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; |
| @@ -282,7 +281,8 @@ minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, · 80 unmodified lines | |||
| 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% to | 318 | * 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 | ||
| 763 | static inline int | ||
| 764 | minstrel_get_duration(int index) | ||
| 765 | { | ||
| 766 | const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; | ||
| 767 | unsigned int duration = group->duration[index % MCS_GROUP_RATES]; | ||
| 768 | return duration << group->shift; | ||
| 769 | } | ||
| 770 | |||
| 762 | static void | 771 | static void |
| 763 | minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | 772 | minstrel_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 usual | 902 | * If the rate is slower than single-stream MCS4, limit A-MSDU to usual |
| 892 | * data packet size | 903 | * 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 usual | 910 | * rate success probability is less than 75%, limit A-MSDU to twice the usual |
| 900 | * data packet size | 911 | * 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 | ||
| 949 | static inline int | ||
| 950 | minstrel_get_duration(int index) | ||
| 951 | { | ||
| 952 | const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; | ||
| 953 | return group->duration[index % MCS_GROUP_RATES]; | ||
| 954 | } | ||
| 955 | |||
| 956 | static int | 960 | static int |
| 957 | minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | 961 | minstrel_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 | else | 1161 | else |
| 1152 | #endif | 1162 | 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 | #endif | 1237 | |
| 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 | ||
| 1356 | static void | ||
| 1357 | minstrel_ht_init_cck_rates(struct minstrel_priv *mp) | ||
| 1358 | { | ||
| 1359 | static const int bitrates[4] = { 10, 20, 55, 110 }; | ||
| 1360 | struct ieee80211_supported_band *sband; | ||
| 1361 | u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); | ||
| 1362 | int i, j; | ||
| 1363 | |||
| 1364 | sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; | ||
| 1365 | if (!sband) | ||
| 1366 | return; | ||
| 1367 | |||
| 1368 | for (i = 0; i < sband->n_bitrates; i++) { | ||
| 1369 | struct ieee80211_rate *rate = &sband->bitrates[i]; | ||
| 1370 | |||
| 1371 | if (rate->flags & IEEE80211_RATE_ERP_G) | ||
| 1372 | continue; | ||
| 1373 | |||
| 1374 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
| 1375 | continue; | ||
| 1376 | |||
| 1377 | for (j = 0; j < ARRAY_SIZE(bitrates); j++) { | ||
| 1378 | if (rate->bitrate != bitrates[j]) | ||
| 1379 | continue; | ||
| 1380 | |||
| 1381 | mp->cck_rates[j] = i; | ||
| 1382 | break; | ||
| 1383 | } | ||
| 1384 | } | ||
| 1385 | } | ||
| 1386 | |||
| 1343 | static void * | 1387 | static void * |
| 1344 | minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 1388 | minstrel_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 | ||
| 1349 | static void | 1434 | static void |
| 1350 | minstrel_ht_free(void *priv) | 1435 | minstrel_ht_free(void *priv) |
| 1351 | { | 1436 | { |
| 1352 | mac80211_minstrel.free(priv); | 1437 | kfree(priv); |
| 1353 | } | 1438 | } |
| 1354 | 1439 | ||
| 1355 | static u32 minstrel_ht_get_expected_throughput(void *priv_sta) | 1440 | static u32 minstrel_ht_get_expected_throughput(void *priv_sta) |
| @@ -1384,7 +1469,6 @@ static const struct rate_control_ops mac80211_minstrel_ht = { · 28 unmodified lines | |||
| 1384 | .free = minstrel_ht_free, | 1469 | .free = minstrel_ht_free, |
| 1385 | #ifdef CONFIG_MAC80211_DEBUGFS | 1470 | #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 | #endif | 1472 | #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 | ||
| 1411 | int __init | 1495 | int __init |
| 1412 | rc80211_minstrel_ht_init(void) | 1496 | rc80211_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 | ||
| 1418 | void | 1502 | void |
| 1419 | rc80211_minstrel_ht_exit(void) | 1503 | rc80211_minstrel_exit(void) |
| 1420 | { | 1504 | { |
| 1421 | ieee80211_rate_control_unregister(&mac80211_minstrel_ht); | 1505 | ieee80211_rate_control_unregister(&mac80211_minstrel_ht); |
| 1422 | } | 1506 | } |
| @@ -15,11 +15,7 @@ · 14 unmodified lines | |||
| 15 | */ | 15 | */ |
| 16 | #define MINSTREL_MAX_STREAMS 3 | 16 | #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 10 | 33 | #define MCS_GROUP_RATES 10 |
| 39 | #else | ||
| 40 | #define MCS_GROUP_RATES 8 | ||
| 41 | #endif | ||
| 42 | 34 | ||
| 43 | struct mcs_group { | 35 | struct 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 | ||
| 49 | extern const struct mcs_group minstrel_mcs_groups[]; | 42 | extern 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 | ||
| 122 | void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | 111 | void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); |
| 123 | void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta); | ||
| 124 | int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, | 112 | int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, |
| 125 | int prob_ewma); | 113 | int prob_ewma); |
| 126 | 114 | ||
| @@ -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 | ||
| 18 | static ssize_t | ||
| 19 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) | ||
| 20 | { | ||
| 21 | struct minstrel_debugfs_info *ms; | ||
| 22 | |||
| 23 | ms = file->private_data; | ||
| 24 | return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); | ||
| 25 | } | ||
| 26 | |||
| 27 | static int | ||
| 28 | minstrel_stats_release(struct inode *inode, struct file *file) | ||
| 29 | { | ||
| 30 | kfree(file->private_data); | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | |||
| 18 | static char * | 34 | static char * |
| 19 | minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) | 35 | minstrel_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 | |||
| 312 | void | ||
| 313 | minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta) | ||
| 314 | { | ||
| 315 | struct minstrel_ht_sta_priv *msp = priv_sta; | ||
| 316 | |||
| 317 | debugfs_remove(msp->dbg_stats); | ||
| 318 | debugfs_remove(msp->dbg_stats_csv); | ||
| 319 | } | 327 | } |
| @@ -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 to | 2466 | * 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 | } |
| @@ -987,6 +987,25 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw, · 986 unmodified lines | |||
| 987 | } | 987 | } |
| 988 | EXPORT_SYMBOL(ieee80211_tx_status_ext); | 988 | EXPORT_SYMBOL(ieee80211_tx_status_ext); |
| 989 | 989 | ||
| 990 | void ieee80211_tx_rate_update(struct ieee80211_hw *hw, | ||
| 991 | struct ieee80211_sta *pubsta, | ||
| 992 | struct ieee80211_tx_info *info) | ||
| 993 | { | ||
| 994 | struct ieee80211_local *local = hw_to_local(hw); | ||
| 995 | struct ieee80211_supported_band *sband = hw->wiphy->bands[info->band]; | ||
| 996 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | ||
| 997 | struct ieee80211_tx_status status = { | ||
| 998 | .info = info, | ||
| 999 | .sta = pubsta, | ||
| 1000 | }; | ||
| 1001 | |||
| 1002 | rate_control_tx_status(local, sband, &status); | ||
| 1003 | |||
| 1004 | if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) | ||
| 1005 | sta->tx_stats.last_rate = info->status.rates[0]; | ||
| 1006 | } | ||
| 1007 | EXPORT_SYMBOL(ieee80211_tx_rate_update); | ||
| 1008 | |||
| 990 | void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets) | 1009 | void 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); |
| @@ -2600,6 +2600,29 @@ TRACE_EVENT(drv_wake_tx_queue, · 2599 unmodified lines | |||
| 2600 | ) | 2600 | ) |
| 2601 | ); | 2601 | ); |
| 2602 | 2602 | ||
| 2603 | TRACE_EVENT(drv_get_ftm_responder_stats, | ||
| 2604 | TP_PROTO(struct ieee80211_local *local, | ||
| 2605 | struct ieee80211_sub_if_data *sdata, | ||
| 2606 | struct cfg80211_ftm_responder_stats *ftm_stats), | ||
| 2607 | |||
| 2608 | TP_ARGS(local, sdata, ftm_stats), | ||
| 2609 | |||
| 2610 | TP_STRUCT__entry( | ||
| 2611 | LOCAL_ENTRY | ||
| 2612 | VIF_ENTRY | ||
| 2613 | ), | ||
| 2614 | |||
| 2615 | TP_fast_assign( | ||
| 2616 | LOCAL_ASSIGN; | ||
| 2617 | VIF_ASSIGN; | ||
| 2618 | ), | ||
| 2619 | |||
| 2620 | TP_printk( | ||
| 2621 | LOCAL_PR_FMT VIF_PR_FMT, | ||
| 2622 | LOCAL_PR_ARG, VIF_PR_ARG | ||
| 2623 | ) | ||
| 2624 | ); | ||
| 2625 | |||
| 2603 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ | 2626 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ |
| 2604 | 2627 | ||
| 2605 | #undef TRACE_INCLUDE_PATH | 2628 | #undef TRACE_INCLUDE_PATH |
| @@ -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 | ||
| @@ -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 | ||
| 1022 | void cfg80211_unregister_wdev(struct wireless_dev *wdev) | 1022 | static 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 | |||
| 1058 | void cfg80211_unregister_wdev(struct wireless_dev *wdev) | ||
| 1059 | { | ||
| 1060 | if (WARN_ON(wdev->netdev)) | ||
| 1061 | return; | ||
| 1062 | |||
| 1063 | __cfg80211_unregister_wdev(wdev, true); | ||
| 1064 | } | ||
| 1052 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | 1065 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
| 1053 | 1066 | ||
| 1054 | static const struct device_type wiphy_type = { | 1067 | static const struct device_type wiphy_type = { |
| @@ -1153,6 +1166,30 @@ void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, · 98 unmodified lines | |||
| 1153 | } | 1166 | } |
| 1154 | EXPORT_SYMBOL(cfg80211_stop_iface); | 1167 | EXPORT_SYMBOL(cfg80211_stop_iface); |
| 1155 | 1168 | ||
| 1169 | void cfg80211_init_wdev(struct cfg80211_registered_device *rdev, | ||
| 1170 | struct wireless_dev *wdev) | ||
| 1171 | { | ||
| 1172 | mutex_init(&wdev->mtx); | ||
| 1173 | INIT_LIST_HEAD(&wdev->event_list); | ||
| 1174 | spin_lock_init(&wdev->event_lock); | ||
| 1175 | INIT_LIST_HEAD(&wdev->mgmt_registrations); | ||
| 1176 | spin_lock_init(&wdev->mgmt_registrations_lock); | ||
| 1177 | |||
| 1178 | /* | ||
| 1179 | * We get here also when the interface changes network namespaces, | ||
| 1180 | * as it's registered into the new one, but we don't want it to | ||
| 1181 | * change ID in that case. Checking if the ID is already assigned | ||
| 1182 | * works, because 0 isn't considered a valid ID and the memory is | ||
| 1183 | * 0-initialized. | ||
| 1184 | */ | ||
| 1185 | if (!wdev->identifier) | ||
| 1186 | wdev->identifier = ++rdev->wdev_id; | ||
| 1187 | list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list); | ||
| 1188 | rdev->devlist_generation++; | ||
| 1189 | |||
| 1190 | nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); | ||
| 1191 | } | ||
| 1192 | |||
| 1156 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | 1193 | static 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 interfaces | 1215 | * 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 netdev | 1329 | * synchronise (so that we won't find this netdev |
| @@ -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 | #endif | 134 | #endif |
| 134 | } | 135 | } |
| 135 | 136 | ||
| 137 | static inline u64 cfg80211_assign_cookie(struct cfg80211_registered_device *rdev) | ||
| 138 | { | ||
| 139 | u64 r = ++rdev->cookie_counter; | ||
| 140 | |||
| 141 | if (WARN_ON(r == 0)) | ||
| 142 | r = ++rdev->cookie_counter; | ||
| 143 | |||
| 144 | return r; | ||
| 145 | } | ||
| 146 | |||
| 136 | extern struct workqueue_struct *cfg80211_wq; | 147 | extern struct workqueue_struct *cfg80211_wq; |
| 137 | extern struct list_head cfg80211_rdev_list; | 148 | extern struct list_head cfg80211_rdev_list; |
| 138 | extern int cfg80211_rdev_list_generation; | 149 | extern int cfg80211_rdev_list_generation; |
| @@ -187,6 +198,9 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); · 48 unmodified lines | |||
| 187 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, | 198 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, |
| 188 | struct net *net); | 199 | struct net *net); |
| 189 | 200 | ||
| 201 | void cfg80211_init_wdev(struct cfg80211_registered_device *rdev, | ||
| 202 | struct wireless_dev *wdev); | ||
| 203 | |||
| 190 | static inline void wdev_lock(struct wireless_dev *wdev) | 204 | static inline void wdev_lock(struct wireless_dev *wdev) |
| 191 | __acquires(wdev) | 205 | __acquires(wdev) |
| 192 | { | 206 | { |
| @@ -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 | |||
| 344 | static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | 342 | static 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 | |||
| 400 | static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | 392 | static 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)); |
| @@ -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 | ||
| 28 | MODULE_AUTHOR("Jouni Malinen"); | 28 | MODULE_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 | ||
| 42 | static void *lib80211_wep_init(int keyidx) | 42 | static 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 | |||
| 129 | static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | 129 | static 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 of | 171 | /* 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 | |||
| 182 | static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | 178 | static 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; |
| @@ -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 | ||
| 203 | static int validate_ie_attr(const struct nlattr *attr, | ||
| 204 | struct netlink_ext_ack *extack) | ||
| 205 | { | ||
| 206 | const u8 *pos; | ||
| 207 | int len; | ||
| 208 | |||
| 209 | pos = nla_data(attr); | ||
| 210 | len = nla_len(attr); | ||
| 211 | |||
| 212 | while (len) { | ||
| 213 | u8 elemlen; | ||
| 214 | |||
| 215 | if (len < 2) | ||
| 216 | goto error; | ||
| 217 | len -= 2; | ||
| 218 | |||
| 219 | elemlen = pos[1]; | ||
| 220 | if (elemlen > len) | ||
| 221 | goto error; | ||
| 222 | |||
| 223 | len -= elemlen; | ||
| 224 | pos += 2 + elemlen; | ||
| 225 | } | ||
| 226 | |||
| 227 | return 0; | ||
| 228 | error: | ||
| 229 | NL_SET_ERR_MSG_ATTR(extack, attr, "malformed information elements"); | ||
| 230 | return -EINVAL; | ||
| 231 | } | ||
| 232 | |||
| 203 | /* policy for the attributes */ | 233 | /* policy for the attributes */ |
| 234 | static const struct nla_policy | ||
| 235 | nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = { | ||
| 236 | [NL80211_FTM_RESP_ATTR_ENABLED] = { .type = NLA_FLAG, }, | ||
| 237 | [NL80211_FTM_RESP_ATTR_LCI] = { .type = NLA_BINARY, | ||
| 238 | .len = U8_MAX }, | ||
| 239 | [NL80211_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_BINARY, | ||
| 240 | .len = U8_MAX }, | ||
| 241 | }; | ||
| 242 | |||
| 204 | static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { | 243 | static 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_LEN | 462 | .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 | |||
| 491 | static const struct nla_policy | 558 | static const struct nla_policy |
| 492 | nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = { | 559 | nl80211_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 | ||
| 570 | static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | 640 | static 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 */ | ||
| 618 | static bool is_valid_ie_attr(const struct nlattr *attr) | ||
| 619 | { | ||
| 620 | const u8 *pos; | ||
| 621 | int len; | ||
| 622 | |||
| 623 | if (!attr) | ||
| 624 | return true; | ||
| 625 | |||
| 626 | pos = nla_data(attr); | ||
| 627 | len = nla_len(attr); | ||
| 628 | |||
| 629 | while (len) { | ||
| 630 | u8 elemlen; | ||
| 631 | |||
| 632 | if (len < 2) | ||
| 633 | return false; | ||
| 634 | len -= 2; | ||
| 635 | |||
| 636 | elemlen = pos[1]; | ||
| 637 | if (elemlen > len) | ||
| 638 | return false; | ||
| 639 | |||
| 640 | len -= elemlen; | ||
| 641 | pos += 2 + elemlen; | ||
| 642 | } | ||
| 643 | |||
| 644 | return true; | ||
| 645 | } | ||
| 646 | |||
| 647 | /* message building helper */ | 686 | /* message building helper */ |
| 648 | static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq, | 687 | static 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 go | 3291 | * P2P Device and NAN do not have a netdev, so don't go |
| 3253 | * through the netdev notifier and must be added here | 3292 | * 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 | ||
| 4001 | static int nl80211_parse_beacon(struct nlattr *attrs[], | 4018 | static 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, ¶ms.beacon); | 4243 | err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.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, ¶ms); | 4418 | err = nl80211_parse_beacon(rdev, info->attrs, ¶ms); |
| 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 | else | 5251 | 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, ¶ms)) | 5285 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) |
| 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 | else | 5394 | 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, ¶ms); | 5439 | err = nl80211_parse_sta_channel_info(info, ¶ms); |
| 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 | ||
| 6137 | static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = { | 6137 | static const struct nla_policy |
| 6138 | [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 }, | 6138 | nl80211_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 | ||
| 6181 | static int nl80211_check_bool(const struct nlattr *nla, u8 min, u8 max, bool *out) | ||
| 6182 | { | ||
| 6183 | u8 val = nla_get_u8(nla); | ||
| 6184 | if (val < min || val > max) | ||
| 6185 | return -EINVAL; | ||
| 6186 | *out = val; | ||
| 6187 | return 0; | ||
| 6188 | } | ||
| 6189 | |||
| 6190 | static int nl80211_check_u8(const struct nlattr *nla, u8 min, u8 max, u8 *out) | ||
| 6191 | { | ||
| 6192 | u8 val = nla_get_u8(nla); | ||
| 6193 | if (val < min || val > max) | ||
| 6194 | return -EINVAL; | ||
| 6195 | *out = val; | ||
| 6196 | return 0; | ||
| 6197 | } | ||
| 6198 | |||
| 6199 | static int nl80211_check_u16(const struct nlattr *nla, u16 min, u16 max, u16 *out) | ||
| 6200 | { | ||
| 6201 | u16 val = nla_get_u16(nla); | ||
| 6202 | if (val < min || val > max) | ||
| 6203 | return -EINVAL; | ||
| 6204 | *out = val; | ||
| 6205 | return 0; | ||
| 6206 | } | ||
| 6207 | |||
| 6208 | static int nl80211_check_u32(const struct nlattr *nla, u32 min, u32 max, u32 *out) | ||
| 6209 | { | ||
| 6210 | u32 val = nla_get_u32(nla); | ||
| 6211 | if (val < min || val > max) | ||
| 6212 | return -EINVAL; | ||
| 6213 | *out = val; | ||
| 6214 | return 0; | ||
| 6215 | } | ||
| 6216 | |||
| 6217 | static int nl80211_check_s32(const struct nlattr *nla, s32 min, s32 max, s32 *out) | ||
| 6218 | { | ||
| 6219 | s32 val = nla_get_s32(nla); | ||
| 6220 | if (val < min || val > max) | ||
| 6221 | return -EINVAL; | ||
| 6222 | *out = val; | ||
| 6223 | return 0; | ||
| 6224 | } | ||
| 6225 | |||
| 6226 | static int nl80211_check_power_mode(const struct nlattr *nla, | ||
| 6227 | enum nl80211_mesh_power_mode min, | ||
| 6228 | enum nl80211_mesh_power_mode max, | ||
| 6229 | enum nl80211_mesh_power_mode *out) | ||
| 6230 | { | ||
| 6231 | u32 val = nla_get_u32(nla); | ||
| 6232 | if (val < min || val > max) | ||
| 6233 | return -EINVAL; | ||
| 6234 | *out = val; | ||
| 6235 | return 0; | ||
| 6236 | } | ||
| 6237 | |||
| 6238 | static int nl80211_parse_mesh_config(struct genl_info *info, | 6198 | static 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) \ |
| 6247 | do { \ | 6207 | do { \ |
| 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 on | 6294 | * 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, ¶ms.beacon_after); | 7894 | err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.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, ¶ms.beacon_csa); | 7904 | err = nl80211_parse_beacon(rdev, csa_attrs, ¶ms.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 | ||
| 12913 | static int nl80211_get_ftm_responder_stats(struct sk_buff *skb, | ||
| 12914 | struct genl_info *info) | ||
| 12915 | { | ||
| 12916 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
| 12917 | struct net_device *dev = info->user_ptr[1]; | ||
| 12918 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
| 12919 | struct cfg80211_ftm_responder_stats ftm_stats = {}; | ||
| 12920 | struct sk_buff *msg; | ||
| 12921 | void *hdr; | ||
| 12922 | struct nlattr *ftm_stats_attr; | ||
| 12923 | int err; | ||
| 12924 | |||
| 12925 | if (wdev->iftype != NL80211_IFTYPE_AP || !wdev->beacon_interval) | ||
| 12926 | return -EOPNOTSUPP; | ||
| 12927 | |||
| 12928 | err = rdev_get_ftm_responder_stats(rdev, dev, &ftm_stats); | ||
| 12929 | if (err) | ||
| 12930 | return err; | ||
| 12931 | |||
| 12932 | if (!ftm_stats.filled) | ||
| 12933 | return -ENODATA; | ||
| 12934 | |||
| 12935 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 12936 | if (!msg) | ||
| 12937 | return -ENOMEM; | ||
| 12938 | |||
| 12939 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | ||
| 12940 | NL80211_CMD_GET_FTM_RESPONDER_STATS); | ||
| 12941 | if (!hdr) | ||
| 12942 | return -ENOBUFS; | ||
| 12943 | |||
| 12944 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) | ||
| 12945 | goto nla_put_failure; | ||
| 12946 | |||
| 12947 | ftm_stats_attr = nla_nest_start(msg, NL80211_ATTR_FTM_RESPONDER_STATS); | ||
| 12948 | if (!ftm_stats_attr) | ||
| 12949 | goto nla_put_failure; | ||
| 12950 | |||
| 12951 | #define SET_FTM(field, name, type) \ | ||
| 12952 | do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \ | ||
| 12953 | nla_put_ ## type(msg, NL80211_FTM_STATS_ ## name, \ | ||
| 12954 | ftm_stats.field)) \ | ||
| 12955 | goto nla_put_failure; } while (0) | ||
| 12956 | #define SET_FTM_U64(field, name) \ | ||
| 12957 | do { if ((ftm_stats.filled & BIT(NL80211_FTM_STATS_ ## name)) && \ | ||
| 12958 | nla_put_u64_64bit(msg, NL80211_FTM_STATS_ ## name, \ | ||
| 12959 | ftm_stats.field, NL80211_FTM_STATS_PAD)) \ | ||
| 12960 | goto nla_put_failure; } while (0) | ||
| 12961 | |||
| 12962 | SET_FTM(success_num, SUCCESS_NUM, u32); | ||
| 12963 | SET_FTM(partial_num, PARTIAL_NUM, u32); | ||
| 12964 | SET_FTM(failed_num, FAILED_NUM, u32); | ||
| 12965 | SET_FTM(asap_num, ASAP_NUM, u32); | ||
| 12966 | SET_FTM(non_asap_num, NON_ASAP_NUM, u32); | ||
| 12967 | SET_FTM_U64(total_duration_ms, TOTAL_DURATION_MSEC); | ||
| 12968 | SET_FTM(unknown_triggers_num, UNKNOWN_TRIGGERS_NUM, u32); | ||
| 12969 | SET_FTM(reschedule_requests_num, RESCHEDULE_REQUESTS_NUM, u32); | ||
| 12970 | SET_FTM(out_of_window_triggers_num, OUT_OF_WINDOW_TRIGGERS_NUM, u32); | ||
| 12971 | #undef SET_FTM | ||
| 12972 | |||
| 12973 | nla_nest_end(msg, ftm_stats_attr); | ||
| 12974 | |||
| 12975 | genlmsg_end(msg, hdr); | ||
| 12976 | return genlmsg_reply(msg, info); | ||
| 12977 | |||
| 12978 | nla_put_failure: | ||
| 12979 | nlmsg_free(msg); | ||
| 12980 | return -ENOBUFS; | ||
| 12981 | } | ||
| 12982 | |||
| 13006 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 12983 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
| 13007 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 12984 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
| 13008 | #define NL80211_FLAG_NEED_RTNL 0x04 | 12985 | #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 | ||
| 13919 | static struct genl_family nl80211_fam __ro_after_init = { | 13903 | static struct genl_family nl80211_fam __ro_after_init = { |
| @@ -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 | ||
| 1235 | static inline int | ||
| 1236 | rdev_get_ftm_responder_stats(struct cfg80211_registered_device *rdev, | ||
| 1237 | struct net_device *dev, | ||
| 1238 | struct cfg80211_ftm_responder_stats *ftm_stats) | ||
| 1239 | { | ||
| 1240 | int ret = -EOPNOTSUPP; | ||
| 1241 | |||
| 1242 | trace_rdev_get_ftm_responder_stats(&rdev->wiphy, dev, ftm_stats); | ||
| 1243 | if (rdev->ops->get_ftm_responder_stats) | ||
| 1244 | ret = rdev->ops->get_ftm_responder_stats(&rdev->wiphy, dev, | ||
| 1245 | ftm_stats); | ||
| 1246 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
| 1247 | return ret; | ||
| 1248 | } | ||
| 1249 | |||
| 1235 | #endif /* __CFG80211_RDEV_OPS */ | 1250 | #endif /* __CFG80211_RDEV_OPS */ |
| @@ -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; |
| @@ -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 | ||
| 2371 | TRACE_EVENT(rdev_start_radar_detection, | ||
| 2372 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
| 2373 | struct cfg80211_chan_def *chandef, | ||
| 2374 | u32 cac_time_ms), | ||
| 2375 | TP_ARGS(wiphy, netdev, chandef, cac_time_ms), | ||
| 2376 | TP_STRUCT__entry( | ||
| 2377 | WIPHY_ENTRY | ||
| 2378 | NETDEV_ENTRY | ||
| 2379 | CHAN_DEF_ENTRY | ||
| 2380 | __field(u32, cac_time_ms) | ||
| 2381 | ), | ||
| 2382 | TP_fast_assign( | ||
| 2383 | WIPHY_ASSIGN; | ||
| 2384 | NETDEV_ASSIGN; | ||
| 2385 | CHAN_DEF_ASSIGN(chandef); | ||
| 2386 | __entry->cac_time_ms = cac_time_ms; | ||
| 2387 | ), | ||
| 2388 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT | ||
| 2389 | ", cac_time_ms=%u", | ||
| 2390 | WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, | ||
| 2391 | __entry->cac_time_ms) | ||
| 2392 | ); | ||
| 2393 | |||
| 2394 | TRACE_EVENT(rdev_set_mcast_rate, | ||
| 2395 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
| 2396 | int *mcast_rate), | ||
| 2397 | TP_ARGS(wiphy, netdev, mcast_rate), | ||
| 2398 | TP_STRUCT__entry( | ||
| 2399 | WIPHY_ENTRY | ||
| 2400 | NETDEV_ENTRY | ||
| 2401 | __array(int, mcast_rate, NUM_NL80211_BANDS) | ||
| 2402 | ), | ||
| 2403 | TP_fast_assign( | ||
| 2404 | WIPHY_ASSIGN; | ||
| 2405 | NETDEV_ASSIGN; | ||
| 2406 | memcpy(__entry->mcast_rate, mcast_rate, | ||
| 2407 | sizeof(int) * NUM_NL80211_BANDS); | ||
| 2408 | ), | ||
| 2409 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " | ||
| 2410 | "mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 60GHz=0x%x]", | ||
| 2411 | WIPHY_PR_ARG, NETDEV_PR_ARG, | ||
| 2412 | __entry->mcast_rate[NL80211_BAND_2GHZ], | ||
| 2413 | __entry->mcast_rate[NL80211_BAND_5GHZ], | ||
| 2414 | __entry->mcast_rate[NL80211_BAND_60GHZ]) | ||
| 2415 | ); | ||
| 2416 | |||
| 2417 | TRACE_EVENT(rdev_set_coalesce, | ||
| 2418 | TP_PROTO(struct wiphy *wiphy, struct cfg80211_coalesce *coalesce), | ||
| 2419 | TP_ARGS(wiphy, coalesce), | ||
| 2420 | TP_STRUCT__entry( | ||
| 2421 | WIPHY_ENTRY | ||
| 2422 | __field(int, n_rules) | ||
| 2423 | ), | ||
| 2424 | TP_fast_assign( | ||
| 2425 | WIPHY_ASSIGN; | ||
| 2426 | __entry->n_rules = coalesce ? coalesce->n_rules : 0; | ||
| 2427 | ), | ||
| 2428 | TP_printk(WIPHY_PR_FMT ", n_rules=%d", | ||
| 2429 | WIPHY_PR_ARG, __entry->n_rules) | ||
| 2430 | ); | ||
| 2431 | |||
| 2432 | DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan, | ||
| 2433 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), | ||
| 2434 | TP_ARGS(wiphy, wdev) | ||
| 2435 | ); | ||
| 2436 | |||
| 2437 | TRACE_EVENT(rdev_set_multicast_to_unicast, | ||
| 2438 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
| 2439 | const bool enabled), | ||
| 2440 | TP_ARGS(wiphy, netdev, enabled), | ||
| 2441 | TP_STRUCT__entry( | ||
| 2442 | WIPHY_ENTRY | ||
| 2443 | NETDEV_ENTRY | ||
| 2444 | __field(bool, enabled) | ||
| 2445 | ), | ||
| 2446 | TP_fast_assign( | ||
| 2447 | WIPHY_ASSIGN; | ||
| 2448 | NETDEV_ASSIGN; | ||
| 2449 | __entry->enabled = enabled; | ||
| 2450 | ), | ||
| 2451 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", unicast: %s", | ||
| 2452 | WIPHY_PR_ARG, NETDEV_PR_ARG, | ||
| 2453 | BOOL_TO_STR(__entry->enabled)) | ||
| 2454 | ); | ||
| 2455 | |||
| 2456 | DEFINE_EVENT(wiphy_wdev_evt, rdev_get_txq_stats, | ||
| 2457 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), | ||
| 2458 | TP_ARGS(wiphy, wdev) | ||
| 2459 | ); | ||
| 2460 | |||
| 2461 | TRACE_EVENT(rdev_get_ftm_responder_stats, | ||
| 2462 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
| 2463 | struct cfg80211_ftm_responder_stats *ftm_stats), | ||
| 2464 | |||
| 2465 | TP_ARGS(wiphy, netdev, ftm_stats), | ||
| 2466 | |||
| 2467 | TP_STRUCT__entry( | ||
| 2468 | WIPHY_ENTRY | ||
| 2469 | NETDEV_ENTRY | ||
| 2470 | __field(u64, timestamp) | ||
| 2471 | __field(u32, success_num) | ||
| 2472 | __field(u32, partial_num) | ||
| 2473 | __field(u32, failed_num) | ||
| 2474 | __field(u32, asap_num) | ||
| 2475 | __field(u32, non_asap_num) | ||
| 2476 | __field(u64, duration) | ||
| 2477 | __field(u32, unknown_triggers) | ||
| 2478 | __field(u32, reschedule) | ||
| 2479 | __field(u32, out_of_window) | ||
| 2480 | ), | ||
| 2481 | |||
| 2482 | TP_fast_assign( | ||
| 2483 | WIPHY_ASSIGN; | ||
| 2484 | NETDEV_ASSIGN; | ||
| 2485 | __entry->success_num = ftm_stats->success_num; | ||
| 2486 | __entry->partial_num = ftm_stats->partial_num; | ||
| 2487 | __entry->failed_num = ftm_stats->failed_num; | ||
| 2488 | __entry->asap_num = ftm_stats->asap_num; | ||
| 2489 | __entry->non_asap_num = ftm_stats->non_asap_num; | ||
| 2490 | __entry->duration = ftm_stats->total_duration_ms; | ||
| 2491 | __entry->unknown_triggers = ftm_stats->unknown_triggers_num; | ||
| 2492 | __entry->reschedule = ftm_stats->reschedule_requests_num; | ||
| 2493 | __entry->out_of_window = ftm_stats->out_of_window_triggers_num; | ||
| 2494 | ), | ||
| 2495 | |||
| 2496 | TP_printk(WIPHY_PR_FMT "Ftm responder stats: success %u, partial %u, " | ||
| 2497 | "failed %u, asap %u, non asap %u, total duration %llu, unknown " | ||
| 2498 | "triggers %u, rescheduled %u, out of window %u", WIPHY_PR_ARG, | ||
| 2499 | __entry->success_num, __entry->partial_num, __entry->failed_num, | ||
| 2500 | __entry->asap_num, __entry->non_asap_num, __entry->duration, | ||
| 2501 | __entry->unknown_triggers, __entry->reschedule, | ||
| 2502 | __entry->out_of_window) | ||
| 2503 | ); | ||
| 2504 | |||
| 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 | |||
| 3164 | TRACE_EVENT(rdev_start_radar_detection, | ||
| 3165 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
| 3166 | struct cfg80211_chan_def *chandef, | ||
| 3167 | u32 cac_time_ms), | ||
| 3168 | TP_ARGS(wiphy, netdev, chandef, cac_time_ms), | ||
| 3169 | TP_STRUCT__entry( | ||
| 3170 | WIPHY_ENTRY | ||
| 3171 | NETDEV_ENTRY | ||
| 3172 | CHAN_DEF_ENTRY | ||
| 3173 | __field(u32, cac_time_ms) | ||
| 3174 | ), | ||
| 3175 | TP_fast_assign( | ||
| 3176 | WIPHY_ASSIGN; | ||
| 3177 | NETDEV_ASSIGN; | ||
| 3178 | CHAN_DEF_ASSIGN(chandef); | ||
| 3179 | __entry->cac_time_ms = cac_time_ms; | ||
| 3180 | ), | ||
| 3181 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT | ||
| 3182 | ", cac_time_ms=%u", | ||
| 3183 | WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, | ||
| 3184 | __entry->cac_time_ms) | ||
| 3185 | ); | ||
| 3186 | |||
| 3187 | TRACE_EVENT(rdev_set_mcast_rate, | ||
| 3188 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
| 3189 | int *mcast_rate), | ||
| 3190 | TP_ARGS(wiphy, netdev, mcast_rate), | ||
| 3191 | TP_STRUCT__entry( | ||
| 3192 | WIPHY_ENTRY | ||
| 3193 | NETDEV_ENTRY | ||
| 3194 | __array(int, mcast_rate, NUM_NL80211_BANDS) | ||
| 3195 | ), | ||
| 3196 | TP_fast_assign( | ||
| 3197 | WIPHY_ASSIGN; | ||
| 3198 | NETDEV_ASSIGN; | ||
| 3199 | memcpy(__entry->mcast_rate, mcast_rate, | ||
| 3200 | sizeof(int) * NUM_NL80211_BANDS); | ||
| 3201 | ), | ||
| 3202 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " | ||
| 3203 | "mcast_rates [2.4GHz=0x%x, 5.2GHz=0x%x, 60GHz=0x%x]", | ||
| 3204 | WIPHY_PR_ARG, NETDEV_PR_ARG, | ||
| 3205 | __entry->mcast_rate[NL80211_BAND_2GHZ], | ||
| 3206 | __entry->mcast_rate[NL80211_BAND_5GHZ], | ||
| 3207 | __entry->mcast_rate[NL80211_BAND_60GHZ]) | ||
| 3208 | ); | ||
| 3209 | |||
| 3210 | TRACE_EVENT(rdev_set_coalesce, | ||
| 3211 | TP_PROTO(struct wiphy *wiphy, struct cfg80211_coalesce *coalesce), | ||
| 3212 | TP_ARGS(wiphy, coalesce), | ||
| 3213 | TP_STRUCT__entry( | ||
| 3214 | WIPHY_ENTRY | ||
| 3215 | __field(int, n_rules) | ||
| 3216 | ), | ||
| 3217 | TP_fast_assign( | ||
| 3218 | WIPHY_ASSIGN; | ||
| 3219 | __entry->n_rules = coalesce ? coalesce->n_rules : 0; | ||
| 3220 | ), | ||
| 3221 | TP_printk(WIPHY_PR_FMT ", n_rules=%d", | ||
| 3222 | WIPHY_PR_ARG, __entry->n_rules) | ||
| 3223 | ); | ||
| 3224 | |||
| 3225 | DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan, | ||
| 3226 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), | ||
| 3227 | TP_ARGS(wiphy, wdev) | ||
| 3228 | ); | ||
| 3229 | |||
| 3230 | TRACE_EVENT(rdev_set_multicast_to_unicast, | ||
| 3231 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | ||
| 3232 | const bool enabled), | ||
| 3233 | TP_ARGS(wiphy, netdev, enabled), | ||
| 3234 | TP_STRUCT__entry( | ||
| 3235 | WIPHY_ENTRY | ||
| 3236 | NETDEV_ENTRY | ||
| 3237 | __field(bool, enabled) | ||
| 3238 | ), | ||
| 3239 | TP_fast_assign( | ||
| 3240 | WIPHY_ASSIGN; | ||
| 3241 | NETDEV_ASSIGN; | ||
| 3242 | __entry->enabled = enabled; | ||
| 3243 | ), | ||
| 3244 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", unicast: %s", | ||
| 3245 | WIPHY_PR_ARG, NETDEV_PR_ARG, | ||
| 3246 | BOOL_TO_STR(__entry->enabled)) | ||
| 3247 | ); | ||
| 3248 | |||
| 3249 | TRACE_EVENT(rdev_get_txq_stats, | ||
| 3250 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), | ||
| 3251 | TP_ARGS(wiphy, wdev), | ||
| 3252 | TP_STRUCT__entry( | ||
| 3253 | WIPHY_ENTRY | ||
| 3254 | WDEV_ENTRY | ||
| 3255 | ), | ||
| 3256 | TP_fast_assign( | ||
| 3257 | WIPHY_ASSIGN; | ||
| 3258 | WDEV_ASSIGN; | ||
| 3259 | ), | ||
| 3260 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) | ||
| 3261 | ); | ||
| 3262 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ | 3297 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ |
| 3263 | 3298 | ||
| 3264 | #undef TRACE_INCLUDE_PATH | 3299 | #undef TRACE_INCLUDE_PATH |