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 | 496 | static spinlock_t hwsim_radio_lock; |
| 497 | 497 | static LIST_HEAD(hwsim_radios); |
| 498 | −static struct workqueue_struct *hwsim_wq; | |
| 499 | 498 | static struct rhashtable hwsim_radios_rht; |
| 500 | 499 | static int hwsim_radio_idx; |
| 501 | 500 | static int hwsim_radios_generation = 1; |
| @@ -3692,13 +3691,9 @@ static int __init init_mac80211_hwsim(void) · 3190 unmodified lines | ||
| 3692 | 3691 | |
| 3693 | 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 | 3694 | err = rhashtable_init(&hwsim_radios_rht, &hwsim_rht_params); |
| 3700 | 3695 | if (err) |
| 3701 | − goto out_free_wq; | |
| 3696 | + return err; | |
| 3702 | 3697 | |
| 3703 | 3698 | err = register_pernet_device(&hwsim_net_ops); |
| 3704 | 3699 | if (err) |
| @@ -3829,8 +3824,6 @@ out_unregister_pernet: · 124 unmodified lines | ||
| 3829 | 3824 | unregister_pernet_device(&hwsim_net_ops); |
| 3830 | 3825 | out_free_rht: |
| 3831 | 3826 | rhashtable_destroy(&hwsim_radios_rht); |
| 3832 | −out_free_wq: | |
| 3833 | − destroy_workqueue(hwsim_wq); | |
| 3834 | 3827 | return err; |
| 3835 | 3828 | } |
| 3836 | 3829 | module_init(init_mac80211_hwsim); |
| @@ -3842,12 +3835,10 @@ static void __exit exit_mac80211_hwsim(void) · 5 unmodified lines | ||
| 3842 | 3835 | hwsim_exit_netlink(); |
| 3843 | 3836 | |
| 3844 | 3837 | mac80211_hwsim_free(); |
| 3845 | − flush_workqueue(hwsim_wq); | |
| 3846 | 3838 | |
| 3847 | 3839 | rhashtable_destroy(&hwsim_radios_rht); |
| 3848 | 3840 | unregister_netdev(hwsim_mon); |
| 3849 | 3841 | platform_driver_unregister(&mac80211_hwsim_driver); |
| 3850 | 3842 | unregister_pernet_device(&hwsim_net_ops); |
| 3851 | − destroy_workqueue(hwsim_wq); | |
| 3852 | 3843 | } |
| 3853 | 3844 | module_exit(exit_mac80211_hwsim); |
| @@ -1670,6 +1670,7 @@ struct ieee80211_mu_edca_param_set { · 1669 unmodified lines | ||
| 1670 | 1670 | #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 |
| 1671 | 1671 | #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 |
| 1672 | 1672 | #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 |
| 1673 | +#define IEEE80211_VHT_CAP_RXSTBC_SHIFT 8 | |
| 1673 | 1674 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 |
| 1674 | 1675 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 |
| 1675 | 1676 | #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13 |
| @@ -775,6 +775,12 @@ struct cfg80211_crypto_settings { · 774 unmodified lines | ||
| 775 | 775 | * @assocresp_ies_len: length of assocresp_ies in octets |
| 776 | 776 | * @probe_resp_len: length of probe response template (@probe_resp) |
| 777 | 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 | 785 | struct cfg80211_beacon_data { |
| 780 | 786 | const u8 *head, *tail; |
| @@ -782,12 +788,17 @@ struct cfg80211_beacon_data { · 1 unmodified line | ||
| 782 | 788 | const u8 *proberesp_ies; |
| 783 | 789 | const u8 *assocresp_ies; |
| 784 | 790 | const u8 *probe_resp; |
| 791 | + const u8 *lci; | |
| 792 | + const u8 *civicloc; | |
| 793 | + s8 ftm_responder; | |
| 785 | 794 | |
| 786 | 795 | size_t head_len, tail_len; |
| 787 | 796 | size_t beacon_ies_len; |
| 788 | 797 | size_t proberesp_ies_len; |
| 789 | 798 | size_t assocresp_ies_len; |
| 790 | 799 | size_t probe_resp_len; |
| 800 | + size_t lci_len; | |
| 801 | + size_t civicloc_len; | |
| 791 | 802 | }; |
| 792 | 803 | |
| 793 | 804 | struct mac_address { |
| @@ -1292,6 +1303,10 @@ struct cfg80211_tid_stats { · 498 unmodified lines | ||
| 1292 | 1303 | * @ack_signal: signal strength (in dBm) of the last ACK frame. |
| 1293 | 1304 | * @avg_ack_signal: average rssi value of ack packet for the no of msdu's has |
| 1294 | 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 | 1311 | struct station_info { |
| 1297 | 1312 | u64 filled; |
| @@ -1338,6 +1353,9 @@ struct station_info { · 40 unmodified lines | ||
| 1338 | 1353 | struct cfg80211_tid_stats *pertid; |
| 1339 | 1354 | s8 ack_signal; |
| 1340 | 1355 | s8 avg_ack_signal; |
| 1356 | + | |
| 1357 | + u32 rx_mpdu_count; | |
| 1358 | + u32 fcs_err_count; | |
| 1341 | 1359 | }; |
| 1342 | 1360 | |
| 1343 | 1361 | #if IS_ENABLED(CONFIG_CFG80211) |
| @@ -2796,6 +2814,40 @@ struct cfg80211_external_auth_params { · 1452 unmodified lines | ||
| 2796 | 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 | 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 | 3181 | * @tx_control_port: TX a control port frame (EAPoL). The noencrypt parameter |
| 3130 | 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 | 3187 | struct cfg80211_ops { |
| 3133 | 3188 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); |
| @@ -3433,6 +3488,10 @@ struct cfg80211_ops { · 299 unmodified lines | ||
| 3433 | 3488 | const u8 *buf, size_t len, |
| 3434 | 3489 | const u8 *dest, const __be16 proto, |
| 3435 | 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 | 4019 | * by the driver in the .connect() callback. The bit position maps to the |
| 3961 | 4020 | * attribute indices defined in &enum nl80211_bss_select_attr. |
| 3962 | 4021 | * |
| 3963 | − * @cookie_counter: unique generic cookie counter, used to identify objects. | |
| 3964 | 4022 | * @nan_supported_bands: bands supported by the device in NAN mode, a |
| 3965 | 4023 | * bitmap of &enum nl80211_band values. For instance, for |
| 3966 | 4024 | * NL80211_BAND_2GHZ, bit 0 would be set |
| @@ -4099,8 +4157,6 @@ struct wiphy { · 132 unmodified lines | ||
| 4099 | 4157 | |
| 4100 | 4158 | u32 bss_select_support; |
| 4101 | 4159 | |
| 4102 | − u64 cookie_counter; | |
| 4103 | − | |
| 4104 | 4160 | u8 nan_supported_bands; |
| 4105 | 4161 | |
| 4106 | 4162 | u32 txq_limit; |
| @@ -309,6 +309,8 @@ struct ieee80211_vif_chanctx_switch { · 308 unmodified lines | ||
| 309 | 309 | * @BSS_CHANGED_KEEP_ALIVE: keep alive options (idle period or protected |
| 310 | 310 | * keep alive) changed. |
| 311 | 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 | 316 | enum ieee80211_bss_change { |
| @@ -338,6 +340,7 @@ enum ieee80211_bss_change { · 23 unmodified lines | ||
| 338 | 340 | BSS_CHANGED_MU_GROUPS = 1<<23, |
| 339 | 341 | BSS_CHANGED_KEEP_ALIVE = 1<<24, |
| 340 | 342 | BSS_CHANGED_MCAST_RATE = 1<<25, |
| 343 | + BSS_CHANGED_FTM_RESPONDER = 1<<26, | |
| 341 | 344 | |
| 342 | 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 | 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 | 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 | 580 | * @protected_keep_alive: if set, indicates that the station should send an RSN |
| 563 | 581 | * protected frame to the AP to reset the idle timer at the AP for the |
| 564 | 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 | 587 | struct ieee80211_bss_conf { |
| 567 | 588 | const u8 *bssid; |
| @@ -612,6 +633,8 @@ struct ieee80211_bss_conf { · 44 unmodified lines | ||
| 612 | 633 | bool allow_p2p_go_ps; |
| 613 | 634 | u16 max_idle_period; |
| 614 | 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 | 3621 | * aggregating two specific frames in the same A-MSDU. The relation |
| 3599 | 3622 | * between the skbs should be symmetric and transitive. Note that while |
| 3600 | 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 | 3627 | struct ieee80211_ops { |
| 3603 | 3628 | void (*tx)(struct ieee80211_hw *hw, |
| @@ -3883,6 +3908,9 @@ struct ieee80211_ops { · 279 unmodified lines | ||
| 3883 | 3908 | bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *hw, |
| 3884 | 3909 | struct sk_buff *head, |
| 3885 | 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 | 4379 | void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta, |
| 4352 | 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 | 4398 | * ieee80211_tx_status - transmit status callback |
| 4356 | 4399 | * |
| @@ -1033,6 +1033,9 @@ · 1032 unmodified lines | ||
| 1033 | 1033 | * %NL80211_ATTR_CHANNEL_WIDTH,%NL80211_ATTR_NSS attributes with its |
| 1034 | 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 | 1039 | * @NL80211_CMD_MAX: highest used command number |
| 1037 | 1040 | * @__NL80211_CMD_AFTER_LAST: internal use |
| 1038 | 1041 | */ |
| @@ -1245,6 +1248,8 @@ enum nl80211_commands { · 206 unmodified lines | ||
| 1245 | 1248 | |
| 1246 | 1249 | NL80211_CMD_CONTROL_PORT_FRAME, |
| 1247 | 1250 | |
| 1251 | + NL80211_CMD_GET_FTM_RESPONDER_STATS, | |
| 1252 | + | |
| 1248 | 1253 | /* add new commands above here */ |
| 1249 | 1254 | |
| 1250 | 1255 | /* used to define NL80211_CMD_MAX below */ |
| @@ -2241,6 +2246,14 @@ enum nl80211_commands { · 990 unmodified lines | ||
| 2241 | 2246 | * association request when used with NL80211_CMD_NEW_STATION). Can be set |
| 2242 | 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 | 2257 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
| 2245 | 2258 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| 2246 | 2259 | * @__NL80211_ATTR_AFTER_LAST: internal use |
| @@ -2682,6 +2695,10 @@ enum nl80211_attrs { · 435 unmodified lines | ||
| 2682 | 2695 | |
| 2683 | 2696 | NL80211_ATTR_HE_CAPABILITY, |
| 2684 | 2697 | |
| 2698 | + NL80211_ATTR_FTM_RESPONDER, | |
| 2699 | + | |
| 2700 | + NL80211_ATTR_FTM_RESPONDER_STATS, | |
| 2701 | + | |
| 2685 | 2702 | /* add attributes here, update the policy in nl80211.c */ |
| 2686 | 2703 | |
| 2687 | 2704 | __NL80211_ATTR_AFTER_LAST, |
| @@ -3051,6 +3068,12 @@ enum nl80211_sta_bss_param { · 363 unmodified lines | ||
| 3051 | 3068 | * @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment |
| 3052 | 3069 | * @NL80211_STA_INFO_ACK_SIGNAL: signal strength of the last ACK frame(u8, dBm) |
| 3053 | 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 | 3077 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
| 3055 | 3078 | * @NL80211_STA_INFO_MAX: highest possible station info attribute |
| 3056 | 3079 | */ |
| @@ -3091,6 +3114,8 @@ enum nl80211_sta_info { · 34 unmodified lines | ||
| 3091 | 3114 | NL80211_STA_INFO_PAD, |
| 3092 | 3115 | NL80211_STA_INFO_ACK_SIGNAL, |
| 3093 | 3116 | NL80211_STA_INFO_ACK_SIGNAL_AVG, |
| 3117 | + NL80211_STA_INFO_RX_MPDUS, | |
| 3118 | + NL80211_STA_INFO_FCS_ERROR_COUNT, | |
| 3094 | 3119 | |
| 3095 | 3120 | /* keep last */ |
| 3096 | 3121 | __NL80211_STA_INFO_AFTER_LAST, |
| @@ -5225,6 +5250,8 @@ enum nl80211_feature_flags { · 2128 unmodified lines | ||
| 5225 | 5250 | * @NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT: Driver/device can omit all data |
| 5226 | 5251 | * except for supported rates from the probe request content if requested |
| 5227 | 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 | 5256 | * @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0: Driver/device confirm that they are |
| 5230 | 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 | 5296 | NL80211_EXT_FEATURE_SCAN_RANDOM_SN, |
| 5270 | 5297 | NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT, |
| 5271 | 5298 | NL80211_EXT_FEATURE_CAN_REPLACE_PTK0, |
| 5299 | + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER, | |
| 5272 | 5300 | |
| 5273 | 5301 | /* add new features before the definition below */ |
| 5274 | 5302 | NUM_NL80211_EXT_FEATURES, |
| @@ -5808,4 +5836,74 @@ enum nl80211_external_auth_action { · 533 unmodified lines | ||
| 5808 | 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 | 5909 | #endif /* __LINUX_NL80211_H */ |
| @@ -27,20 +27,6 @@ config MAC80211_RC_MINSTREL · 26 unmodified lines | ||
| 27 | 27 | ---help--- |
| 28 | 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 | 30 | choice |
| 45 | 31 | prompt "Default rate control algorithm" |
| 46 | 32 | depends on MAC80211_HAS_RC |
| @@ -62,8 +48,7 @@ endchoice · 15 unmodified lines | ||
| 62 | 48 | |
| 63 | 49 | config MAC80211_RC_DEFAULT |
| 64 | 50 | string |
| 65 | − default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT | |
| 66 | − default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL | |
| 51 | + default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL | |
| 67 | 52 | default "" |
| 68 | 53 | |
| 69 | 54 | endif |
| @@ -53,13 +53,14 @@ mac80211-$(CONFIG_PM) += pm.o · 52 unmodified lines | ||
| 53 | 53 | |
| 54 | 54 | CFLAGS_trace.o := -I$(src) |
| 55 | 55 | |
| 56 | −rc80211_minstrel-y := rc80211_minstrel.o | |
| 57 | −rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o | |
| 56 | +rc80211_minstrel-y := \ | |
| 57 | + rc80211_minstrel.o \ | |
| 58 | + rc80211_minstrel_ht.o | |
| 58 | 59 | |
| 59 | −rc80211_minstrel_ht-y := rc80211_minstrel_ht.o | |
| 60 | −rc80211_minstrel_ht-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o | |
| 60 | +rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += \ | |
| 61 | + rc80211_minstrel_debugfs.o \ | |
| 62 | + rc80211_minstrel_ht_debugfs.o | |
| 61 | 63 | |
| 62 | 64 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) |
| 63 | −mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y) | |
| 64 | 65 | |
| 65 | 66 | ccflags-y += -DDEBUG |
| @@ -790,6 +790,48 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, · 789 unmodified lines | ||
| 790 | 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 | 835 | static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, |
| 794 | 836 | struct cfg80211_beacon_data *params, |
| 795 | 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 | 905 | if (err == 0) |
| 864 | 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 | 922 | rcu_assign_pointer(sdata->u.ap.beacon, new); |
| 867 | 923 | |
| 868 | 924 | if (old) |
| @@ -1063,6 +1119,9 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) · 194 unmodified lines | ||
| 1063 | 1119 | kfree_rcu(old_probe_resp, rcu_head); |
| 1064 | 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 | 1125 | __sta_info_flush(sdata, true); |
| 1067 | 1126 | ieee80211_free_keys(sdata, true); |
| 1068 | 1127 | |
| @@ -2875,6 +2934,20 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) · 1806 unmodified lines | ||
| 2875 | 2934 | memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); |
| 2876 | 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 | 2952 | return new_beacon; |
| 2880 | 2953 | } |
| @@ -3765,6 +3838,17 @@ out: · 884 unmodified lines | ||
| 3765 | 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 | 3852 | const struct cfg80211_ops mac80211_config_ops = { |
| 3769 | 3853 | .add_virtual_intf = ieee80211_add_iface, |
| 3770 | 3854 | .del_virtual_intf = ieee80211_del_iface, |
| @@ -3859,4 +3943,5 @@ const struct cfg80211_ops mac80211_config_ops = { · 88 unmodified lines | ||
| 3859 | 3943 | .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast, |
| 3860 | 3944 | .tx_control_port = ieee80211_tx_control_port, |
| 3861 | 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 | 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 | 1202 | static inline int drv_start_nan(struct ieee80211_local *local, |
| 1187 | 1203 | struct ieee80211_sub_if_data *sdata, |
| 1188 | 1204 | struct cfg80211_nan_conf *conf) |
| @@ -377,6 +377,7 @@ struct ieee80211_mgd_auth_data { · 376 unmodified lines | ||
| 377 | 377 | u8 key[WLAN_KEY_LEN_WEP104]; |
| 378 | 378 | u8 key_len, key_idx; |
| 379 | 379 | bool done; |
| 380 | + bool peer_confirmed; | |
| 380 | 381 | bool timeout_started; |
| 381 | 382 | |
| 382 | 383 | u16 sae_trans, sae_status; |
| @@ -1203,8 +1203,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) · 1202 unmodified lines | ||
| 1203 | 1203 | continue; |
| 1204 | 1204 | |
| 1205 | 1205 | sband = kmemdup(sband, sizeof(*sband), GFP_KERNEL); |
| 1206 | − if (!sband) | |
| 1206 | + if (!sband) { | |
| 1207 | + result = -ENOMEM; | |
| 1207 | 1208 | goto fail_rate; |
| 1209 | + } | |
| 1208 | 1210 | |
| 1209 | 1211 | wiphy_dbg(hw->wiphy, "copying sband (band %d) due to VHT EXT NSS BW flag\n", |
| 1210 | 1212 | band); |
| @@ -1373,18 +1375,12 @@ static int __init ieee80211_init(void) · 162 unmodified lines | ||
| 1373 | 1375 | if (ret) |
| 1374 | 1376 | return ret; |
| 1375 | 1377 | |
| 1376 | − ret = rc80211_minstrel_ht_init(); | |
| 1377 | − if (ret) | |
| 1378 | − goto err_minstrel; | |
| 1379 | − | |
| 1380 | 1378 | ret = ieee80211_iface_init(); |
| 1381 | 1379 | if (ret) |
| 1382 | 1380 | goto err_netdev; |
| 1383 | 1381 | |
| 1384 | 1382 | return 0; |
| 1385 | 1383 | err_netdev: |
| 1386 | − rc80211_minstrel_ht_exit(); | |
| 1387 | − err_minstrel: | |
| 1388 | 1384 | rc80211_minstrel_exit(); |
| 1389 | 1385 | |
| 1390 | 1386 | return ret; |
| @@ -1392,7 +1388,6 @@ static int __init ieee80211_init(void) · 1 unmodified line | ||
| 1392 | 1388 | |
| 1393 | 1389 | static void __exit ieee80211_exit(void) |
| 1394 | 1390 | { |
| 1395 | − rc80211_minstrel_ht_exit(); | |
| 1396 | 1391 | rc80211_minstrel_exit(); |
| 1397 | 1392 | |
| 1398 | 1393 | ieee80211s_stop(); |
| @@ -2761,13 +2761,40 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, · 2760 unmodified lines | ||
| 2761 | 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 | 2792 | static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, |
| 2765 | 2793 | struct ieee80211_mgmt *mgmt, size_t len) |
| 2766 | 2794 | { |
| 2767 | 2795 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 2768 | 2796 | u8 bssid[ETH_ALEN]; |
| 2769 | 2797 | u16 auth_alg, auth_transaction, status_code; |
| 2770 | − struct sta_info *sta; | |
| 2771 | 2798 | struct ieee80211_event event = { |
| 2772 | 2799 | .type = MLME_EVENT, |
| 2773 | 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 | 2818 | status_code = le16_to_cpu(mgmt->u.auth.status_code); |
| 2792 | 2819 | |
| 2793 | 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 | 2826 | sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n", |
| 2796 | 2827 | mgmt->sa, auth_alg, ifmgd->auth_data->algorithm, |
| 2797 | 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 | 2866 | event.u.mlme.status = MLME_SUCCESS; |
| 2836 | 2867 | drv_event_callback(sdata->local, sdata, &event); |
| 2837 | − sdata_info(sdata, "authenticated\n"); | |
| 2838 | − ifmgd->auth_data->done = true; | |
| 2839 | − ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; | |
| 2840 | − ifmgd->auth_data->timeout_started = true; | |
| 2841 | − run_again(sdata, ifmgd->auth_data->timeout); | |
| 2842 | − | |
| 2843 | − if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && | |
| 2844 | − ifmgd->auth_data->expected_transaction != 2) { | |
| 2845 | − /* | |
| 2846 | − * Report auth frame to user space for processing since another | |
| 2847 | − * round of Authentication frames is still needed. | |
| 2848 | − */ | |
| 2849 | − cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); | |
| 2850 | − return; | |
| 2868 | + if (ifmgd->auth_data->algorithm != WLAN_AUTH_SAE || | |
| 2869 | + (auth_transaction == 2 && | |
| 2870 | + ifmgd->auth_data->expected_transaction == 2)) { | |
| 2871 | + if (!ieee80211_mark_sta_auth(sdata, bssid)) | |
| 2872 | + goto out_err; | |
| 2873 | + } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && | |
| 2874 | + auth_transaction == 2) { | |
| 2875 | + sdata_info(sdata, "SAE peer confirmed\n"); | |
| 2876 | + ifmgd->auth_data->peer_confirmed = true; | |
| 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 | 2879 | cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); |
| 2867 | 2880 | return; |
| 2868 | 2881 | out_err: |
| @@ -4878,6 +4891,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 2009 unmodified lines | ||
| 4878 | 4891 | struct ieee80211_mgd_auth_data *auth_data; |
| 4879 | 4892 | u16 auth_alg; |
| 4880 | 4893 | int err; |
| 4894 | + bool cont_auth; | |
| 4881 | 4895 | |
| 4882 | 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 | 4926 | return -EOPNOTSUPP; |
| 4913 | 4927 | } |
| 4914 | 4928 | |
| 4929 | + if (ifmgd->assoc_data) | |
| 4930 | + return -EBUSY; | |
| 4931 | + | |
| 4915 | 4932 | auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len + |
| 4916 | 4933 | req->ie_len, GFP_KERNEL); |
| 4917 | 4934 | if (!auth_data) |
| @@ -4931,6 +4948,13 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 13 unmodified lines | ||
| 4931 | 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 | 4958 | if (req->ie && req->ie_len) { |
| 4935 | 4959 | memcpy(&auth_data->data[auth_data->data_len], |
| 4936 | 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 | 4972 | /* try to authenticate/probe */ |
| 4949 | 4973 | |
| 4950 | − if ((ifmgd->auth_data && !ifmgd->auth_data->done) || | |
| 4951 | − ifmgd->assoc_data) { | |
| 4952 | − err = -EBUSY; | |
| 4953 | − goto err_free; | |
| 4974 | + if (ifmgd->auth_data) { | |
| 4975 | + if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE) { | |
| 4976 | + auth_data->peer_confirmed = | |
| 4977 | + ifmgd->auth_data->peer_confirmed; | |
| 4978 | + } | |
| 4979 | + ieee80211_destroy_auth_data(sdata, cont_auth); | |
| 4954 | 4980 | } |
| 4955 | 4981 | |
| 4956 | − if (ifmgd->auth_data) | |
| 4957 | − ieee80211_destroy_auth_data(sdata, false); | |
| 4958 | − | |
| 4959 | 4982 | /* prep auth_data so we don't go into idle on disassoc */ |
| 4960 | 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 | 4994 | if (ifmgd->associated) { |
| 4963 | 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 | 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 | 5012 | if (err) |
| 4981 | 5013 | goto err_clear; |
| 4982 | 5014 | |
| @@ -4997,7 +5029,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, · 14 unmodified lines | ||
| 4997 | 5029 | mutex_lock(&sdata->local->mtx); |
| 4998 | 5030 | ieee80211_vif_release_channel(sdata); |
| 4999 | 5031 | mutex_unlock(&sdata->local->mtx); |
| 5000 | − err_free: | |
| 5001 | 5032 | kfree(auth_data); |
| 5002 | 5033 | return err; |
| 5003 | 5034 | } |
| @@ -95,18 +95,5 @@ static inline void rc80211_minstrel_exit(void) · 94 unmodified lines | ||
| 95 | 95 | } |
| 96 | 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 | 99 | #endif /* IEEE80211_RATE_H */ |
| @@ -167,12 +167,6 @@ minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) · 166 unmodified lines | ||
| 167 | 167 | if (unlikely(!mrs->att_hist)) { |
| 168 | 168 | mrs->prob_ewma = cur_prob; |
| 169 | 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 | 170 | /*update exponential weighted moving avarage */ |
| 177 | 171 | mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma, |
| 178 | 172 | cur_prob, |
| @@ -572,141 +566,6 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, · 393 unmodified lines | ||
| 572 | 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 | 569 | static u32 minstrel_get_expected_throughput(void *priv_sta) |
| 711 | 570 | { |
| 712 | 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 | 586 | const struct rate_control_ops mac80211_minstrel = { |
| 728 | − .name = "minstrel", | |
| 729 | 587 | .tx_status_ext = minstrel_tx_status, |
| 730 | 588 | .get_rate = minstrel_get_rate, |
| 731 | 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 | 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 | 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 | 38 | struct minstrel_rate_stats { |
| 52 | 39 | /* current / last sampling period attempts/success counters */ |
| 53 | 40 | u16 attempts, last_attempts; |
| @@ -56,11 +43,8 @@ struct minstrel_rate_stats { · 2 unmodified lines | ||
| 56 | 43 | /* total attempts/success counters */ |
| 57 | 44 | u32 att_hist, succ_hist; |
| 58 | 45 | |
| 59 | − /* statistis of packet delivery probability | |
| 60 | − * prob_ewma - exponential weighted moving average of prob | |
| 61 | − * prob_ewmsd - exp. weighted moving standard deviation of prob */ | |
| 46 | + /* prob_ewma - exponential weighted moving average of prob */ | |
| 62 | 47 | u16 prob_ewma; |
| 63 | − u16 prob_ewmv; | |
| 64 | 48 | |
| 65 | 49 | /* maximum retry counts */ |
| 66 | 50 | u8 retry_count; |
| @@ -109,11 +93,6 @@ struct minstrel_sta_info { · 42 unmodified lines | ||
| 109 | 93 | |
| 110 | 94 | /* sampling table */ |
| 111 | 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 | 98 | struct minstrel_priv { |
| @@ -137,7 +116,6 @@ struct minstrel_priv { · 17 unmodified lines | ||
| 137 | 116 | * - setting will be applied on next update |
| 138 | 117 | */ |
| 139 | 118 | u32 fixed_rate_idx; |
| 140 | − struct dentry *dbg_fixed_rate; | |
| 141 | 119 | #endif |
| 142 | 120 | }; |
| 143 | 121 | |
| @@ -146,17 +124,8 @@ struct minstrel_debugfs_info { · 2 unmodified lines | ||
| 146 | 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 | 127 | extern const struct rate_control_ops mac80211_minstrel; |
| 158 | 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 | 130 | /* Recalculate success probabilities and counters for a given rate using EWMA */ |
| 162 | 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 | 134 | /* debugfs */ |
| 166 | 135 | int minstrel_stats_open(struct inode *inode, struct file *file); |
| 167 | 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 | 138 | #endif |
| @@ -54,22 +54,6 @@ · 53 unmodified lines | ||
| 54 | 54 | #include <net/mac80211.h> |
| 55 | 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 | 57 | int |
| 74 | 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 | 70 | p = ms->buf; |
| 87 | 71 | p += sprintf(p, "\n"); |
| 88 | 72 | p += sprintf(p, |
| 89 | − "best __________rate_________ ________statistics________ ____last_____ ______sum-of________\n"); | |
| 73 | + "best __________rate_________ ____statistics___ ____last_____ ______sum-of________\n"); | |
| 90 | 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 | 77 | for (i = 0; i < mi->n_rates; i++) { |
| 94 | 78 | struct minstrel_rate *mr = &mi->r[i]; |
| 95 | 79 | struct minstrel_rate_stats *mrs = &mi->r[i].stats; |
| 96 | − unsigned int prob_ewmsd; | |
| 97 | 80 | |
| 98 | 81 | *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; |
| 99 | 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 | 92 | tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); |
| 110 | 93 | tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); |
| 111 | 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 | 97 | " %3u %3u %-3u " |
| 116 | 98 | "%9llu %-9llu\n", |
| 117 | 99 | tp_max / 10, tp_max % 10, |
| 118 | 100 | tp_avg / 10, tp_avg % 10, |
| 119 | 101 | eprob / 10, eprob % 10, |
| 120 | − prob_ewmsd / 10, prob_ewmsd % 10, | |
| 121 | 102 | mrs->retry_count, |
| 122 | 103 | mrs->last_success, |
| 123 | 104 | mrs->last_attempts, |
| @@ -135,14 +116,6 @@ minstrel_stats_open(struct inode *inode, struct file *file) · 11 unmodified lines | ||
| 135 | 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 | 119 | int |
| 147 | 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 | 134 | for (i = 0; i < mi->n_rates; i++) { |
| 162 | 135 | struct minstrel_rate *mr = &mi->r[i]; |
| 163 | 136 | struct minstrel_rate_stats *mrs = &mi->r[i].stats; |
| 164 | − unsigned int prob_ewmsd; | |
| 165 | 137 | |
| 166 | 138 | p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : "")); |
| 167 | 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 | 149 | tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); |
| 178 | 150 | tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); |
| 179 | 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 | 154 | "%llu,%llu,%d,%d\n", |
| 184 | 155 | tp_max / 10, tp_max % 10, |
| 185 | 156 | tp_avg / 10, tp_avg % 10, |
| 186 | 157 | eprob / 10, eprob % 10, |
| 187 | − prob_ewmsd / 10, prob_ewmsd % 10, | |
| 188 | 158 | mrs->retry_count, |
| 189 | 159 | mrs->last_success, |
| 190 | 160 | mrs->last_attempts, |
| @@ -200,33 +170,3 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) · 9 unmodified lines | ||
| 200 | 170 | |
| 201 | 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 | 52 | _streams - 1 |
| 53 | 53 | |
| 54 | 54 | /* MCS rate information for an MCS group */ |
| 55 | −#define MCS_GROUP(_streams, _sgi, _ht40) \ | |
| 55 | +#define MCS_GROUP(_streams, _sgi, _ht40, _s) \ | |
| 56 | 56 | [GROUP_IDX(_streams, _sgi, _ht40)] = { \ |
| 57 | 57 | .streams = _streams, \ |
| 58 | + .shift = _s, \ | |
| 58 | 59 | .flags = \ |
| 59 | 60 | IEEE80211_TX_RC_MCS | \ |
| 60 | 61 | (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \ |
| 61 | 62 | (_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \ |
| 62 | 63 | .duration = { \ |
| 63 | − MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26), \ | |
| 64 | − MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52), \ | |
| 65 | − MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78), \ | |
| 66 | − MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104), \ | |
| 67 | − MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156), \ | |
| 68 | − MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208), \ | |
| 69 | − MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234), \ | |
| 70 | − MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) \ | |
| 64 | + MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s, \ | |
| 65 | + MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s, \ | |
| 66 | + MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s, \ | |
| 67 | + MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s, \ | |
| 68 | + MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s, \ | |
| 69 | + MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s, \ | |
| 70 | + MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s, \ | |
| 71 | + MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s \ | |
| 71 | 72 | } \ |
| 72 | 73 | } |
| 73 | 74 | |
| @@ -80,9 +81,10 @@ · 6 unmodified lines | ||
| 80 | 81 | #define BW2VBPS(_bw, r3, r2, r1) \ |
| 81 | 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 | 85 | [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \ |
| 85 | 86 | .streams = _streams, \ |
| 87 | + .shift = _s, \ | |
| 86 | 88 | .flags = \ |
| 87 | 89 | IEEE80211_TX_RC_VHT_MCS | \ |
| 88 | 90 | (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \ |
| @@ -90,25 +92,25 @@ · 1 unmodified line | ||
| 90 | 92 | _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \ |
| 91 | 93 | .duration = { \ |
| 92 | 94 | MCS_DURATION(_streams, _sgi, \ |
| 93 | − BW2VBPS(_bw, 117, 54, 26)), \ | |
| 95 | + BW2VBPS(_bw, 117, 54, 26)) >> _s, \ | |
| 94 | 96 | MCS_DURATION(_streams, _sgi, \ |
| 95 | − BW2VBPS(_bw, 234, 108, 52)), \ | |
| 97 | + BW2VBPS(_bw, 234, 108, 52)) >> _s, \ | |
| 96 | 98 | MCS_DURATION(_streams, _sgi, \ |
| 97 | − BW2VBPS(_bw, 351, 162, 78)), \ | |
| 99 | + BW2VBPS(_bw, 351, 162, 78)) >> _s, \ | |
| 98 | 100 | MCS_DURATION(_streams, _sgi, \ |
| 99 | − BW2VBPS(_bw, 468, 216, 104)), \ | |
| 101 | + BW2VBPS(_bw, 468, 216, 104)) >> _s, \ | |
| 100 | 102 | MCS_DURATION(_streams, _sgi, \ |
| 101 | − BW2VBPS(_bw, 702, 324, 156)), \ | |
| 103 | + BW2VBPS(_bw, 702, 324, 156)) >> _s, \ | |
| 102 | 104 | MCS_DURATION(_streams, _sgi, \ |
| 103 | − BW2VBPS(_bw, 936, 432, 208)), \ | |
| 105 | + BW2VBPS(_bw, 936, 432, 208)) >> _s, \ | |
| 104 | 106 | MCS_DURATION(_streams, _sgi, \ |
| 105 | − BW2VBPS(_bw, 1053, 486, 234)), \ | |
| 107 | + BW2VBPS(_bw, 1053, 486, 234)) >> _s, \ | |
| 106 | 108 | MCS_DURATION(_streams, _sgi, \ |
| 107 | − BW2VBPS(_bw, 1170, 540, 260)), \ | |
| 109 | + BW2VBPS(_bw, 1170, 540, 260)) >> _s, \ | |
| 108 | 110 | MCS_DURATION(_streams, _sgi, \ |
| 109 | − BW2VBPS(_bw, 1404, 648, 312)), \ | |
| 111 | + BW2VBPS(_bw, 1404, 648, 312)) >> _s, \ | |
| 110 | 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 | 123 | (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ |
| 122 | 124 | CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE)) |
| 123 | 125 | |
| 124 | −#define CCK_DURATION_LIST(_short) \ | |
| 125 | − CCK_ACK_DURATION(10, _short), \ | |
| 126 | − CCK_ACK_DURATION(20, _short), \ | |
| 127 | − CCK_ACK_DURATION(55, _short), \ | |
| 128 | − CCK_ACK_DURATION(110, _short) | |
| 126 | +#define CCK_DURATION_LIST(_short, _s) \ | |
| 127 | + CCK_ACK_DURATION(10, _short) >> _s, \ | |
| 128 | + CCK_ACK_DURATION(20, _short) >> _s, \ | |
| 129 | + CCK_ACK_DURATION(55, _short) >> _s, \ | |
| 130 | + CCK_ACK_DURATION(110, _short) >> _s | |
| 129 | 131 | |
| 130 | −#define CCK_GROUP \ | |
| 132 | +#define CCK_GROUP(_s) \ | |
| 131 | 133 | [MINSTREL_CCK_GROUP] = { \ |
| 132 | − .streams = 0, \ | |
| 134 | + .streams = 1, \ | |
| 133 | 135 | .flags = 0, \ |
| 136 | + .shift = _s, \ | |
| 134 | 137 | .duration = { \ |
| 135 | − CCK_DURATION_LIST(false), \ | |
| 136 | − CCK_DURATION_LIST(true) \ | |
| 138 | + CCK_DURATION_LIST(false, _s), \ | |
| 139 | + CCK_DURATION_LIST(true, _s) \ | |
| 137 | 140 | } \ |
| 138 | 141 | } |
| 139 | 142 | |
| 140 | −#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT | |
| 141 | 143 | static bool minstrel_vht_only = true; |
| 142 | 144 | module_param(minstrel_vht_only, bool, 0644); |
| 143 | 145 | MODULE_PARM_DESC(minstrel_vht_only, |
| 144 | 146 | "Use only VHT rates when VHT is supported by sta."); |
| 145 | −#endif | |
| 146 | 147 | |
| 147 | 148 | /* |
| 148 | 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 | 154 | * BW -> SGI -> #streams |
| 154 | 155 | */ |
| 155 | 156 | const struct mcs_group minstrel_mcs_groups[] = { |
| 156 | − MCS_GROUP(1, 0, BW_20), | |
| 157 | − MCS_GROUP(2, 0, BW_20), | |
| 158 | − MCS_GROUP(3, 0, BW_20), | |
| 157 | + MCS_GROUP(1, 0, BW_20, 5), | |
| 158 | + MCS_GROUP(2, 0, BW_20, 4), | |
| 159 | + MCS_GROUP(3, 0, BW_20, 4), | |
| 159 | 160 | |
| 160 | − MCS_GROUP(1, 1, BW_20), | |
| 161 | − MCS_GROUP(2, 1, BW_20), | |
| 162 | − MCS_GROUP(3, 1, BW_20), | |
| 161 | + MCS_GROUP(1, 1, BW_20, 5), | |
| 162 | + MCS_GROUP(2, 1, BW_20, 4), | |
| 163 | + MCS_GROUP(3, 1, BW_20, 4), | |
| 163 | 164 | |
| 164 | − MCS_GROUP(1, 0, BW_40), | |
| 165 | − MCS_GROUP(2, 0, BW_40), | |
| 166 | − MCS_GROUP(3, 0, BW_40), | |
| 165 | + MCS_GROUP(1, 0, BW_40, 4), | |
| 166 | + MCS_GROUP(2, 0, BW_40, 4), | |
| 167 | + MCS_GROUP(3, 0, BW_40, 4), | |
| 167 | 168 | |
| 168 | − MCS_GROUP(1, 1, BW_40), | |
| 169 | − MCS_GROUP(2, 1, BW_40), | |
| 170 | − MCS_GROUP(3, 1, BW_40), | |
| 169 | + MCS_GROUP(1, 1, BW_40, 4), | |
| 170 | + MCS_GROUP(2, 1, BW_40, 4), | |
| 171 | + MCS_GROUP(3, 1, BW_40, 4), | |
| 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), | |
| 176 | − VHT_GROUP(2, 0, BW_20), | |
| 177 | − VHT_GROUP(3, 0, BW_20), | |
| 175 | + VHT_GROUP(1, 0, BW_20, 5), | |
| 176 | + VHT_GROUP(2, 0, BW_20, 4), | |
| 177 | + VHT_GROUP(3, 0, BW_20, 4), | |
| 178 | 178 | |
| 179 | − VHT_GROUP(1, 1, BW_20), | |
| 180 | − VHT_GROUP(2, 1, BW_20), | |
| 181 | − VHT_GROUP(3, 1, BW_20), | |
| 179 | + VHT_GROUP(1, 1, BW_20, 5), | |
| 180 | + VHT_GROUP(2, 1, BW_20, 4), | |
| 181 | + VHT_GROUP(3, 1, BW_20, 4), | |
| 182 | 182 | |
| 183 | − VHT_GROUP(1, 0, BW_40), | |
| 184 | − VHT_GROUP(2, 0, BW_40), | |
| 185 | − VHT_GROUP(3, 0, BW_40), | |
| 183 | + VHT_GROUP(1, 0, BW_40, 4), | |
| 184 | + VHT_GROUP(2, 0, BW_40, 4), | |
| 185 | + VHT_GROUP(3, 0, BW_40, 4), | |
| 186 | 186 | |
| 187 | − VHT_GROUP(1, 1, BW_40), | |
| 188 | − VHT_GROUP(2, 1, BW_40), | |
| 189 | − VHT_GROUP(3, 1, BW_40), | |
| 187 | + VHT_GROUP(1, 1, BW_40, 4), | |
| 188 | + VHT_GROUP(2, 1, BW_40, 4), | |
| 189 | + VHT_GROUP(3, 1, BW_40, 4), | |
| 190 | 190 | |
| 191 | − VHT_GROUP(1, 0, BW_80), | |
| 192 | − VHT_GROUP(2, 0, BW_80), | |
| 193 | − VHT_GROUP(3, 0, BW_80), | |
| 191 | + VHT_GROUP(1, 0, BW_80, 4), | |
| 192 | + VHT_GROUP(2, 0, BW_80, 4), | |
| 193 | + VHT_GROUP(3, 0, BW_80, 4), | |
| 194 | 194 | |
| 195 | − VHT_GROUP(1, 1, BW_80), | |
| 196 | − VHT_GROUP(2, 1, BW_80), | |
| 197 | − VHT_GROUP(3, 1, BW_80), | |
| 198 | −#endif | |
| 195 | + VHT_GROUP(1, 1, BW_80, 4), | |
| 196 | + VHT_GROUP(2, 1, BW_80, 4), | |
| 197 | + VHT_GROUP(3, 1, BW_80, 4), | |
| 199 | 198 | }; |
| 200 | 199 | |
| 201 | 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 | 281 | break; |
| 283 | 282 | |
| 284 | 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 | 286 | idx += 4; |
| 287 | 287 | } |
| 288 | 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 | 311 | if (group != MINSTREL_CCK_GROUP) |
| 312 | 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 | 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 | 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 | 771 | static void |
| 763 | 772 | minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, |
| 764 | 773 | int index) |
| 765 | 774 | { |
| 766 | 775 | struct minstrel_rate_stats *mrs; |
| 767 | − const struct mcs_group *group; | |
| 768 | 776 | unsigned int tx_time, tx_time_rtscts, tx_time_data; |
| 769 | 777 | unsigned int cw = mp->cw_min; |
| 770 | 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 | 791 | mrs->retry_count_rtscts = 2; |
| 784 | 792 | mrs->retry_updated = true; |
| 785 | 793 | |
| 786 | − group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; | |
| 787 | − tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000; | |
| 794 | + tx_time_data = minstrel_get_duration(index) * ampdu_len / 1000; | |
| 788 | 795 | |
| 789 | 796 | /* Contention time for first 2 tries */ |
| 790 | 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 | 885 | int group = mi->max_prob_rate / MCS_GROUP_RATES; |
| 879 | 886 | const struct mcs_group *g = &minstrel_mcs_groups[group]; |
| 880 | 887 | int rate = mi->max_prob_rate % MCS_GROUP_RATES; |
| 888 | + unsigned int duration; | |
| 881 | 889 | |
| 882 | 890 | /* Disable A-MSDU if max_prob_rate is bad */ |
| 883 | 891 | if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100)) |
| 884 | 892 | return 1; |
| 885 | 893 | |
| 894 | + duration = g->duration[rate]; | |
| 895 | + duration <<= g->shift; | |
| 896 | + | |
| 886 | 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 | 899 | return 500; |
| 889 | 900 | |
| 890 | 901 | /* |
| 891 | 902 | * If the rate is slower than single-stream MCS4, limit A-MSDU to usual |
| 892 | 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 | 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 | 910 | * rate success probability is less than 75%, limit A-MSDU to twice the usual |
| 900 | 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 | 914 | (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) < |
| 904 | 915 | MINSTREL_FRAC(75, 100))) |
| 905 | 916 | return 3200; |
| @@ -946,13 +957,6 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) · 40 unmodified lines | ||
| 946 | 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 | 960 | static int |
| 957 | 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 | 1004 | return -1; |
| 1001 | 1005 | |
| 1002 | 1006 | /* |
| 1003 | − * Do not sample if the probability is already higher than 95% | |
| 1004 | − * to avoid wasting airtime. | |
| 1007 | + * Do not sample if the probability is already higher than 95%, | |
| 1008 | + * or if the rate is 3 times slower than the current max probability | |
| 1009 | + * rate, to avoid wasting airtime. | |
| 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 | 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 | 1021 | cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 / |
| 1015 | 1022 | MCS_GROUP_RATES].streams; |
| 1016 | − sample_dur = minstrel_get_duration(sample_idx); | |
| 1017 | 1023 | if (sample_dur >= minstrel_get_duration(tp_rate2) && |
| 1018 | 1024 | (cur_max_tp_streams - 1 < |
| 1019 | 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 | 1083 | return; |
| 1078 | 1084 | |
| 1079 | 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 | 1092 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
| 1081 | 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 | 1096 | int idx = sample_idx % ARRAY_SIZE(mp->cck_rates); |
| 1085 | 1097 | rate->idx = mp->cck_rates[idx]; |
| 1086 | 1098 | } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) { |
| 1087 | 1099 | ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES, |
| 1088 | 1100 | sample_group->streams); |
| 1089 | 1101 | } else { |
| 1090 | − rate->idx = sample_idx % MCS_GROUP_RATES + | |
| 1091 | − (sample_group->streams - 1) * 8; | |
| 1102 | + rate->idx = sample_idx + (sample_group->streams - 1) * 8; | |
| 1092 | 1103 | } |
| 1093 | 1104 | |
| 1094 | 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 | 1141 | struct minstrel_ht_sta_priv *msp = priv_sta; |
| 1131 | 1142 | struct minstrel_ht_sta *mi = &msp->ht; |
| 1132 | 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 | 1145 | struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; |
| 1135 | − struct sta_info *sinfo = container_of(sta, struct sta_info, sta); | |
| 1136 | 1146 | int use_vht; |
| 1137 | 1147 | int n_supported = 0; |
| 1138 | 1148 | int ack_dur; |
| 1139 | 1149 | int stbc; |
| 1140 | 1150 | int i; |
| 1151 | + bool ldpc; | |
| 1141 | 1152 | |
| 1142 | 1153 | /* fall back to the old minstrel for legacy stations */ |
| 1143 | 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 | 1157 | BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB); |
| 1147 | 1158 | |
| 1148 | −#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT | |
| 1149 | 1159 | if (vht_cap->vht_supported) |
| 1150 | 1160 | use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0); |
| 1151 | 1161 | else |
| 1152 | −#endif | |
| 1153 | − use_vht = 0; | |
| 1162 | + use_vht = 0; | |
| 1154 | 1163 | |
| 1155 | 1164 | msp->is_ht = true; |
| 1156 | 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 | 1185 | mi->sample_tries = 4; |
| 1177 | 1186 | |
| 1178 | − /* TODO tx_flags for vht - ATM the RC API is not fine-grained enough */ | |
| 1179 | 1187 | if (!use_vht) { |
| 1180 | − stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >> | |
| 1188 | + stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >> | |
| 1181 | 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) | |
| 1185 | − mi->tx_flags |= IEEE80211_TX_CTL_LDPC; | |
| 1191 | + ldpc = ht_cap & IEEE80211_HT_CAP_LDPC_CODING; | |
| 1192 | + } else { | |
| 1193 | + stbc = (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) >> | |
| 1194 | + IEEE80211_VHT_CAP_RXSTBC_SHIFT; | |
| 1195 | + | |
| 1196 | + ldpc = vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC; | |
| 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 | 1203 | for (i = 0; i < ARRAY_SIZE(mi->groups); i++) { |
| 1189 | 1204 | u32 gflags = minstrel_mcs_groups[i].flags; |
| 1190 | 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 | 1213 | if (gflags & IEEE80211_TX_RC_SHORT_GI) { |
| 1199 | 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 | 1216 | continue; |
| 1202 | 1217 | } else { |
| 1203 | − if (!(sta_cap & IEEE80211_HT_CAP_SGI_20)) | |
| 1218 | + if (!(ht_cap & IEEE80211_HT_CAP_SGI_20)) | |
| 1204 | 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 | 1233 | /* HT rate */ |
| 1219 | 1234 | if (gflags & IEEE80211_TX_RC_MCS) { |
| 1220 | −#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT | |
| 1221 | 1235 | if (use_vht && minstrel_vht_only) |
| 1222 | 1236 | continue; |
| 1223 | −#endif | |
| 1237 | + | |
| 1224 | 1238 | mi->supported[i] = mcs->rx_mask[nss - 1]; |
| 1225 | 1239 | if (mi->supported[i]) |
| 1226 | 1240 | n_supported++; |
| @@ -1258,8 +1272,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, · 31 unmodified lines | ||
| 1258 | 1272 | if (!n_supported) |
| 1259 | 1273 | goto use_legacy; |
| 1260 | 1274 | |
| 1261 | − if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE)) | |
| 1262 | − mi->cck_supported_short |= mi->cck_supported_short << 4; | |
| 1275 | + mi->supported[MINSTREL_CCK_GROUP] |= mi->cck_supported_short << 4; | |
| 1263 | 1276 | |
| 1264 | 1277 | /* create an initial rate table with the lowest supported rates */ |
| 1265 | 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 | 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 | 1387 | static void * |
| 1344 | 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 | 1434 | static void |
| 1350 | 1435 | minstrel_ht_free(void *priv) |
| 1351 | 1436 | { |
| 1352 | − mac80211_minstrel.free(priv); | |
| 1437 | + kfree(priv); | |
| 1353 | 1438 | } |
| 1354 | 1439 | |
| 1355 | 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 | 1469 | .free = minstrel_ht_free, |
| 1385 | 1470 | #ifdef CONFIG_MAC80211_DEBUGFS |
| 1386 | 1471 | .add_sta_debugfs = minstrel_ht_add_sta_debugfs, |
| 1387 | − .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs, | |
| 1388 | 1472 | #endif |
| 1389 | 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 | 1495 | int __init |
| 1412 | −rc80211_minstrel_ht_init(void) | |
| 1496 | +rc80211_minstrel_init(void) | |
| 1413 | 1497 | { |
| 1414 | 1498 | init_sample_table(); |
| 1415 | 1499 | return ieee80211_rate_control_register(&mac80211_minstrel_ht); |
| 1416 | 1500 | } |
| 1417 | 1501 | |
| 1418 | 1502 | void |
| 1419 | −rc80211_minstrel_ht_exit(void) | |
| 1503 | +rc80211_minstrel_exit(void) | |
| 1420 | 1504 | { |
| 1421 | 1505 | ieee80211_rate_control_unregister(&mac80211_minstrel_ht); |
| 1422 | 1506 | } |
| @@ -15,11 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | */ |
| 16 | 16 | #define MINSTREL_MAX_STREAMS 3 |
| 17 | 17 | #define MINSTREL_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */ |
| 18 | −#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT | |
| 19 | 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 | 20 | #define MINSTREL_HT_GROUPS_NB (MINSTREL_MAX_STREAMS * \ |
| 25 | 21 | MINSTREL_HT_STREAM_GROUPS) |
| @@ -34,16 +30,13 @@ · 8 unmodified lines | ||
| 34 | 30 | #define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB) |
| 35 | 31 | #define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1) |
| 36 | 32 | |
| 37 | −#ifdef CONFIG_MAC80211_RC_MINSTREL_VHT | |
| 38 | 33 | #define MCS_GROUP_RATES 10 |
| 39 | −#else | |
| 40 | −#define MCS_GROUP_RATES 8 | |
| 41 | −#endif | |
| 42 | 34 | |
| 43 | 35 | struct mcs_group { |
| 44 | − u32 flags; | |
| 45 | − unsigned int streams; | |
| 46 | − unsigned int duration[MCS_GROUP_RATES]; | |
| 36 | + u16 flags; | |
| 37 | + u8 streams; | |
| 38 | + u8 shift; | |
| 39 | + u16 duration[MCS_GROUP_RATES]; | |
| 47 | 40 | }; |
| 48 | 41 | |
| 49 | 42 | extern const struct mcs_group minstrel_mcs_groups[]; |
| @@ -110,17 +103,12 @@ struct minstrel_ht_sta_priv { · 60 unmodified lines | ||
| 110 | 103 | struct minstrel_ht_sta ht; |
| 111 | 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 | 106 | void *ratelist; |
| 118 | 107 | void *sample_table; |
| 119 | 108 | bool is_ht; |
| 120 | 109 | }; |
| 121 | 110 | |
| 122 | 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 | 112 | int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, |
| 125 | 113 | int prob_ewma); |
| 126 | 114 | |
| @@ -15,6 +15,22 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "rc80211_minstrel.h" |
| 16 | 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 | 34 | static char * |
| 19 | 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 | 57 | struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; |
| 42 | 58 | static const int bitrates[4] = { 10, 20, 55, 110 }; |
| 43 | 59 | int idx = i * MCS_GROUP_RATES + j; |
| 44 | − unsigned int prob_ewmsd; | |
| 60 | + unsigned int duration; | |
| 45 | 61 | |
| 46 | 62 | if (!(mi->supported[i] & BIT(j))) |
| 47 | 63 | continue; |
| @@ -79,21 +95,21 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) · 31 unmodified lines | ||
| 79 | 95 | p += sprintf(p, " %3u ", idx); |
| 80 | 96 | |
| 81 | 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 | 101 | p += sprintf(p, "%6u ", tx_time); |
| 84 | 102 | |
| 85 | 103 | tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); |
| 86 | 104 | tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); |
| 87 | 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 | 108 | " %3u %3u %-3u " |
| 92 | 109 | "%9llu %-9llu\n", |
| 93 | 110 | tp_max / 10, tp_max % 10, |
| 94 | 111 | tp_avg / 10, tp_avg % 10, |
| 95 | 112 | eprob / 10, eprob % 10, |
| 96 | − prob_ewmsd / 10, prob_ewmsd % 10, | |
| 97 | 113 | mrs->retry_count, |
| 98 | 114 | mrs->last_success, |
| 99 | 115 | mrs->last_attempts, |
| @@ -130,9 +146,9 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) · 30 unmodified lines | ||
| 130 | 146 | |
| 131 | 147 | p += sprintf(p, "\n"); |
| 132 | 148 | p += sprintf(p, |
| 133 | − " best ____________rate__________ ________statistics________ _____last____ ______sum-of________\n"); | |
| 149 | + " best ____________rate__________ ____statistics___ _____last____ ______sum-of________\n"); | |
| 134 | 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 | 153 | p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p); |
| 138 | 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 | 203 | struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; |
| 188 | 204 | static const int bitrates[4] = { 10, 20, 55, 110 }; |
| 189 | 205 | int idx = i * MCS_GROUP_RATES + j; |
| 190 | − unsigned int prob_ewmsd; | |
| 206 | + unsigned int duration; | |
| 191 | 207 | |
| 192 | 208 | if (!(mi->supported[i] & BIT(j))) |
| 193 | 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 | 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 | 245 | p += sprintf(p, "%u,", tx_time); |
| 227 | 246 | |
| 228 | 247 | tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); |
| 229 | 248 | tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); |
| 230 | 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 | 252 | "%u,%llu,%llu,", |
| 235 | 253 | tp_max / 10, tp_max % 10, |
| 236 | 254 | tp_avg / 10, tp_avg % 10, |
| 237 | 255 | eprob / 10, eprob % 10, |
| 238 | − prob_ewmsd / 10, prob_ewmsd % 10, | |
| 239 | 256 | mrs->retry_count, |
| 240 | 257 | mrs->last_success, |
| 241 | 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 | 321 | struct minstrel_ht_sta_priv *msp = priv_sta; |
| 305 | 322 | |
| 306 | − msp->dbg_stats = debugfs_create_file("rc_stats", 0444, dir, msp, | |
| 307 | − &minstrel_ht_stat_fops); | |
| 308 | − msp->dbg_stats_csv = debugfs_create_file("rc_stats_csv", 0444, dir, msp, | |
| 309 | − &minstrel_ht_stat_csv_fops); | |
| 310 | −} | |
| 311 | − | |
| 312 | −void | |
| 313 | −minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta) | |
| 314 | −{ | |
| 315 | − struct minstrel_ht_sta_priv *msp = priv_sta; | |
| 316 | − | |
| 317 | − debugfs_remove(msp->dbg_stats); | |
| 318 | − debugfs_remove(msp->dbg_stats_csv); | |
| 323 | + debugfs_create_file("rc_stats", 0444, dir, msp, | |
| 324 | + &minstrel_ht_stat_fops); | |
| 325 | + debugfs_create_file("rc_stats_csv", 0444, dir, msp, | |
| 326 | + &minstrel_ht_stat_csv_fops); | |
| 319 | 327 | } |
| @@ -2458,8 +2458,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) · 2457 unmodified lines | ||
| 2458 | 2458 | if (!xmit_skb) |
| 2459 | 2459 | net_info_ratelimited("%s: failed to clone multicast frame\n", |
| 2460 | 2460 | dev->name); |
| 2461 | − } else if (!is_multicast_ether_addr(ehdr->h_dest)) { | |
| 2462 | − dsta = sta_info_get(sdata, skb->data); | |
| 2461 | + } else if (!is_multicast_ether_addr(ehdr->h_dest) && | |
| 2462 | + !ether_addr_equal(ehdr->h_dest, ehdr->h_source)) { | |
| 2463 | + dsta = sta_info_get(sdata, ehdr->h_dest); | |
| 2463 | 2464 | if (dsta) { |
| 2464 | 2465 | /* |
| 2465 | 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 | 4242 | if (fast_rx->internal_forward) { |
| 4242 | 4243 | struct sk_buff *xmit_skb = NULL; |
| 4243 | − bool multicast = is_multicast_ether_addr(skb->data); | |
| 4244 | − | |
| 4245 | − if (multicast) { | |
| 4244 | + if (is_multicast_ether_addr(addrs.da)) { | |
| 4246 | 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 | 4248 | xmit_skb = skb; |
| 4249 | 4249 | skb = NULL; |
| 4250 | 4250 | } |
| @@ -987,6 +987,25 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw, · 986 unmodified lines | ||
| 987 | 987 | } |
| 988 | 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 | 1009 | void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets) |
| 991 | 1010 | { |
| 992 | 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 | 2626 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ |
| 2604 | 2627 | |
| 2605 | 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 | 264 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { |
| 265 | 265 | struct ieee80211_txq *txq = sta->sta.txq[i]; |
| 266 | 266 | |
| 267 | + if (!txq) | |
| 268 | + continue; | |
| 269 | + | |
| 267 | 270 | txqi = to_txq_info(txq); |
| 268 | 271 | |
| 269 | 272 | if (ac != txq->ac) |
| @@ -2175,6 +2178,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) · 1905 unmodified lines | ||
| 2175 | 2178 | case NL80211_IFTYPE_AP: |
| 2176 | 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 | 2186 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
| 2179 | 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 | 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 | 1024 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
| 1025 | 1025 | |
| 1026 | 1026 | ASSERT_RTNL(); |
| 1027 | 1027 | |
| 1028 | − if (WARN_ON(wdev->netdev)) | |
| 1029 | − return; | |
| 1030 | − | |
| 1031 | 1028 | nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE); |
| 1032 | 1029 | |
| 1033 | 1030 | list_del_rcu(&wdev->list); |
| 1034 | − synchronize_rcu(); | |
| 1031 | + if (sync) | |
| 1032 | + synchronize_rcu(); | |
| 1035 | 1033 | rdev->devlist_generation++; |
| 1036 | 1034 | |
| 1035 | + cfg80211_mlme_purge_registrations(wdev); | |
| 1036 | + | |
| 1037 | 1037 | switch (wdev->iftype) { |
| 1038 | 1038 | case NL80211_IFTYPE_P2P_DEVICE: |
| 1039 | − cfg80211_mlme_purge_registrations(wdev); | |
| 1040 | 1039 | cfg80211_stop_p2p_device(rdev, wdev); |
| 1041 | 1040 | break; |
| 1042 | 1041 | case NL80211_IFTYPE_NAN: |
| 1043 | 1042 | cfg80211_stop_nan(rdev, wdev); |
| 1044 | 1043 | break; |
| 1045 | 1044 | default: |
| 1046 | − WARN_ON_ONCE(1); | |
| 1047 | 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 | 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 | 1065 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
| 1053 | 1066 | |
| 1054 | 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 | 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 | 1193 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, |
| 1157 | 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 | 1215 | * called within code protected by it when interfaces |
| 1179 | 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 | 1218 | /* can only change netns with wiphy */ |
| 1199 | 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 | 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 | 1247 | break; |
| 1228 | 1248 | case NETDEV_GOING_DOWN: |
| 1229 | 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 | 1259 | list_for_each_entry_safe(pos, tmp, |
| 1240 | 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 | 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 | 1322 | * remove and clean it up. |
| 1303 | 1323 | */ |
| 1304 | 1324 | if (!list_empty(&wdev->list)) { |
| 1305 | − nl80211_notify_iface(rdev, wdev, | |
| 1306 | − NL80211_CMD_DEL_INTERFACE); | |
| 1325 | + __cfg80211_unregister_wdev(wdev, false); | |
| 1307 | 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 | 1329 | * synchronise (so that we won't find this netdev |
| @@ -66,6 +66,7 @@ struct cfg80211_registered_device { · 65 unmodified lines | ||
| 66 | 66 | /* protected by RTNL only */ |
| 67 | 67 | int num_running_ifaces; |
| 68 | 68 | int num_running_monitor_ifaces; |
| 69 | + u64 cookie_counter; | |
| 69 | 70 | |
| 70 | 71 | /* BSSes/scanning */ |
| 71 | 72 | spinlock_t bss_lock; |
| @@ -133,6 +134,16 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) · 61 unmodified lines | ||
| 133 | 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 | 147 | extern struct workqueue_struct *cfg80211_wq; |
| 137 | 148 | extern struct list_head cfg80211_rdev_list; |
| 138 | 149 | extern int cfg80211_rdev_list_generation; |
| @@ -187,6 +198,9 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); · 48 unmodified lines | ||
| 187 | 198 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, |
| 188 | 199 | struct net *net); |
| 189 | 200 | |
| 201 | +void cfg80211_init_wdev(struct cfg80211_registered_device *rdev, | |
| 202 | + struct wireless_dev *wdev); | |
| 203 | + | |
| 190 | 204 | static inline void wdev_lock(struct wireless_dev *wdev) |
| 191 | 205 | __acquires(wdev) |
| 192 | 206 | { |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <net/iw_handler.h> |
| 31 | 31 | |
| 32 | 32 | #include <crypto/hash.h> |
| 33 | −#include <crypto/skcipher.h> | |
| 33 | +#include <linux/crypto.h> | |
| 34 | 34 | #include <linux/crc32.h> |
| 35 | 35 | |
| 36 | 36 | #include <net/lib80211.h> |
| @@ -64,9 +64,9 @@ struct lib80211_tkip_data { · 27 unmodified lines | ||
| 64 | 64 | |
| 65 | 65 | int key_idx; |
| 66 | 66 | |
| 67 | − struct crypto_skcipher *rx_tfm_arc4; | |
| 67 | + struct crypto_cipher *rx_tfm_arc4; | |
| 68 | 68 | struct crypto_shash *rx_tfm_michael; |
| 69 | − struct crypto_skcipher *tx_tfm_arc4; | |
| 69 | + struct crypto_cipher *tx_tfm_arc4; | |
| 70 | 70 | struct crypto_shash *tx_tfm_michael; |
| 71 | 71 | |
| 72 | 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 | 100 | priv->key_idx = key_idx; |
| 101 | 101 | |
| 102 | − priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, | |
| 103 | − CRYPTO_ALG_ASYNC); | |
| 102 | + priv->tx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); | |
| 104 | 103 | if (IS_ERR(priv->tx_tfm_arc4)) { |
| 105 | 104 | priv->tx_tfm_arc4 = NULL; |
| 106 | 105 | goto fail; |
| @@ -112,8 +111,7 @@ static void *lib80211_tkip_init(int key_idx) · 5 unmodified lines | ||
| 112 | 111 | goto fail; |
| 113 | 112 | } |
| 114 | 113 | |
| 115 | − priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, | |
| 116 | − CRYPTO_ALG_ASYNC); | |
| 114 | + priv->rx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); | |
| 117 | 115 | if (IS_ERR(priv->rx_tfm_arc4)) { |
| 118 | 116 | priv->rx_tfm_arc4 = NULL; |
| 119 | 117 | goto fail; |
| @@ -130,9 +128,9 @@ static void *lib80211_tkip_init(int key_idx) · 10 unmodified lines | ||
| 130 | 128 | fail: |
| 131 | 129 | if (priv) { |
| 132 | 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 | 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 | 134 | kfree(priv); |
| 137 | 135 | } |
| 138 | 136 | |
| @@ -144,9 +142,9 @@ static void lib80211_tkip_deinit(void *priv) · 5 unmodified lines | ||
| 144 | 142 | struct lib80211_tkip_data *_priv = priv; |
| 145 | 143 | if (_priv) { |
| 146 | 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 | 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 | 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 | 342 | static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) |
| 345 | 343 | { |
| 346 | 344 | struct lib80211_tkip_data *tkey = priv; |
| 347 | − SKCIPHER_REQUEST_ON_STACK(req, tkey->tx_tfm_arc4); | |
| 348 | 345 | int len; |
| 349 | 346 | u8 rc4key[16], *pos, *icv; |
| 350 | 347 | u32 crc; |
| 351 | − struct scatterlist sg; | |
| 352 | − int err; | |
| 348 | + int i; | |
| 353 | 349 | |
| 354 | 350 | if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { |
| 355 | 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 | 370 | icv[2] = crc >> 16; |
| 375 | 371 | icv[3] = crc >> 24; |
| 376 | 372 | |
| 377 | − crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); | |
| 378 | − sg_init_one(&sg, pos, len + 4); | |
| 379 | − skcipher_request_set_tfm(req, tkey->tx_tfm_arc4); | |
| 380 | − skcipher_request_set_callback(req, 0, NULL, NULL); | |
| 381 | − skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); | |
| 382 | − err = crypto_skcipher_encrypt(req); | |
| 383 | − skcipher_request_zero(req); | |
| 384 | − return err; | |
| 373 | + crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); | |
| 374 | + for (i = 0; i < len + 4; i++) | |
| 375 | + crypto_cipher_encrypt_one(tkey->tx_tfm_arc4, pos + i, pos + i); | |
| 376 | + return 0; | |
| 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 | 392 | static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
| 401 | 393 | { |
| 402 | 394 | struct lib80211_tkip_data *tkey = priv; |
| 403 | − SKCIPHER_REQUEST_ON_STACK(req, tkey->rx_tfm_arc4); | |
| 404 | 395 | u8 rc4key[16]; |
| 405 | 396 | u8 keyidx, *pos; |
| 406 | 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 | 399 | struct ieee80211_hdr *hdr; |
| 409 | 400 | u8 icv[4]; |
| 410 | 401 | u32 crc; |
| 411 | − struct scatterlist sg; | |
| 412 | 402 | int plen; |
| 413 | − int err; | |
| 403 | + int i; | |
| 414 | 404 | |
| 415 | 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 | 454 | plen = skb->len - hdr_len - 12; |
| 465 | 455 | |
| 466 | − crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); | |
| 467 | − sg_init_one(&sg, pos, plen + 4); | |
| 468 | − skcipher_request_set_tfm(req, tkey->rx_tfm_arc4); | |
| 469 | − skcipher_request_set_callback(req, 0, NULL, NULL); | |
| 470 | − skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); | |
| 471 | − err = crypto_skcipher_decrypt(req); | |
| 472 | − skcipher_request_zero(req); | |
| 473 | − if (err) { | |
| 474 | − net_dbg_ratelimited("TKIP: failed to decrypt received packet from %pM\n", | |
| 475 | − hdr->addr2); | |
| 476 | − return -7; | |
| 477 | − } | |
| 456 | + crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); | |
| 457 | + for (i = 0; i < plen + 4; i++) | |
| 458 | + crypto_cipher_decrypt_one(tkey->rx_tfm_arc4, pos + i, pos + i); | |
| 478 | 459 | |
| 479 | 460 | crc = ~crc32_le(~0, pos, plen); |
| 480 | 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 | 641 | struct lib80211_tkip_data *tkey = priv; |
| 661 | 642 | int keyidx; |
| 662 | 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 | 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 | 648 | keyidx = tkey->key_idx; |
| 668 | 649 | memset(tkey, 0, sizeof(*tkey)); |
| @@ -22,7 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | #include <net/lib80211.h> |
| 24 | 24 | |
| 25 | −#include <crypto/skcipher.h> | |
| 25 | +#include <linux/crypto.h> | |
| 26 | 26 | #include <linux/crc32.h> |
| 27 | 27 | |
| 28 | 28 | MODULE_AUTHOR("Jouni Malinen"); |
| @@ -35,8 +35,8 @@ struct lib80211_wep_data { · 6 unmodified lines | ||
| 35 | 35 | u8 key[WEP_KEY_LEN + 1]; |
| 36 | 36 | u8 key_len; |
| 37 | 37 | u8 key_idx; |
| 38 | − struct crypto_skcipher *tx_tfm; | |
| 39 | − struct crypto_skcipher *rx_tfm; | |
| 38 | + struct crypto_cipher *tx_tfm; | |
| 39 | + struct crypto_cipher *rx_tfm; | |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | 42 | static void *lib80211_wep_init(int keyidx) |
| @@ -48,13 +48,13 @@ static void *lib80211_wep_init(int keyidx) · 5 unmodified lines | ||
| 48 | 48 | goto fail; |
| 49 | 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 | 52 | if (IS_ERR(priv->tx_tfm)) { |
| 53 | 53 | priv->tx_tfm = NULL; |
| 54 | 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 | 58 | if (IS_ERR(priv->rx_tfm)) { |
| 59 | 59 | priv->rx_tfm = NULL; |
| 60 | 60 | goto fail; |
| @@ -66,8 +66,8 @@ static void *lib80211_wep_init(int keyidx) · 5 unmodified lines | ||
| 66 | 66 | |
| 67 | 67 | fail: |
| 68 | 68 | if (priv) { |
| 69 | − crypto_free_skcipher(priv->tx_tfm); | |
| 70 | − crypto_free_skcipher(priv->rx_tfm); | |
| 69 | + crypto_free_cipher(priv->tx_tfm); | |
| 70 | + crypto_free_cipher(priv->rx_tfm); | |
| 71 | 71 | kfree(priv); |
| 72 | 72 | } |
| 73 | 73 | return NULL; |
| @@ -77,8 +77,8 @@ static void lib80211_wep_deinit(void *priv) · 3 unmodified lines | ||
| 77 | 77 | { |
| 78 | 78 | struct lib80211_wep_data *_priv = priv; |
| 79 | 79 | if (_priv) { |
| 80 | − crypto_free_skcipher(_priv->tx_tfm); | |
| 81 | − crypto_free_skcipher(_priv->rx_tfm); | |
| 80 | + crypto_free_cipher(_priv->tx_tfm); | |
| 81 | + crypto_free_cipher(_priv->rx_tfm); | |
| 82 | 82 | } |
| 83 | 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 | 129 | static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) |
| 130 | 130 | { |
| 131 | 131 | struct lib80211_wep_data *wep = priv; |
| 132 | − SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm); | |
| 133 | 132 | u32 crc, klen, len; |
| 134 | 133 | u8 *pos, *icv; |
| 135 | − struct scatterlist sg; | |
| 136 | 134 | u8 key[WEP_KEY_LEN + 3]; |
| 137 | − int err; | |
| 135 | + int i; | |
| 138 | 136 | |
| 139 | 137 | /* other checks are in lib80211_wep_build_iv */ |
| 140 | 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 | 160 | icv[2] = crc >> 16; |
| 163 | 161 | icv[3] = crc >> 24; |
| 164 | 162 | |
| 165 | − crypto_skcipher_setkey(wep->tx_tfm, key, klen); | |
| 166 | − sg_init_one(&sg, pos, len + 4); | |
| 167 | − skcipher_request_set_tfm(req, wep->tx_tfm); | |
| 168 | − skcipher_request_set_callback(req, 0, NULL, NULL); | |
| 169 | − skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); | |
| 170 | − err = crypto_skcipher_encrypt(req); | |
| 171 | − skcipher_request_zero(req); | |
| 172 | − return err; | |
| 163 | + crypto_cipher_setkey(wep->tx_tfm, key, klen); | |
| 164 | + | |
| 165 | + for (i = 0; i < len + 4; i++) | |
| 166 | + crypto_cipher_encrypt_one(wep->tx_tfm, pos + i, pos + i); | |
| 167 | + | |
| 168 | + return 0; | |
| 173 | 169 | } |
| 174 | 170 | |
| 175 | 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 | 178 | static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
| 183 | 179 | { |
| 184 | 180 | struct lib80211_wep_data *wep = priv; |
| 185 | − SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); | |
| 186 | 181 | u32 crc, klen, plen; |
| 187 | 182 | u8 key[WEP_KEY_LEN + 3]; |
| 188 | 183 | u8 keyidx, *pos, icv[4]; |
| 189 | − struct scatterlist sg; | |
| 190 | − int err; | |
| 184 | + int i; | |
| 191 | 185 | |
| 192 | 186 | if (skb->len < hdr_len + 8) |
| 193 | 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 | 202 | /* Apply RC4 to data and compute CRC32 over decrypted data */ |
| 209 | 203 | plen = skb->len - hdr_len - 8; |
| 210 | 204 | |
| 211 | − crypto_skcipher_setkey(wep->rx_tfm, key, klen); | |
| 212 | − sg_init_one(&sg, pos, plen + 4); | |
| 213 | − skcipher_request_set_tfm(req, wep->rx_tfm); | |
| 214 | − skcipher_request_set_callback(req, 0, NULL, NULL); | |
| 215 | − skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); | |
| 216 | − err = crypto_skcipher_decrypt(req); | |
| 217 | − skcipher_request_zero(req); | |
| 218 | − if (err) | |
| 219 | − return -7; | |
| 205 | + crypto_cipher_setkey(wep->rx_tfm, key, klen); | |
| 206 | + for (i = 0; i < plen + 4; i++) | |
| 207 | + crypto_cipher_decrypt_one(wep->rx_tfm, pos + i, pos + i); | |
| 220 | 208 | |
| 221 | 209 | crc = ~crc32_le(~0, pos, plen); |
| 222 | 210 | icv[0] = crc; |
| @@ -200,7 +200,46 @@ cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) · 199 unmodified lines | ||
| 200 | 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 | 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 | 243 | static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { |
| 205 | 244 | [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, |
| 206 | 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 | 252 | [NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 }, |
| 214 | 253 | [NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 }, |
| 215 | 254 | |
| 216 | − [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, | |
| 217 | − [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, | |
| 255 | + [NL80211_ATTR_WIPHY_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1), | |
| 256 | + [NL80211_ATTR_WIPHY_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1), | |
| 218 | 257 | [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, |
| 219 | 258 | [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 }, |
| 220 | 259 | [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 }, |
| 221 | 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 | 263 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, |
| 225 | 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 | 269 | [NL80211_ATTR_KEY] = { .type = NLA_NESTED, }, |
| 231 | 270 | [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, |
| 232 | 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 | 273 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, |
| 235 | 274 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, |
| 236 | 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 | 279 | [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, |
| 240 | 280 | [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, |
| 241 | 281 | [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY, |
| 242 | 282 | .len = IEEE80211_MAX_DATA_LEN }, |
| 243 | − [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY, | |
| 244 | − .len = IEEE80211_MAX_DATA_LEN }, | |
| 245 | − [NL80211_ATTR_STA_AID] = { .type = NLA_U16 }, | |
| 283 | + [NL80211_ATTR_BEACON_TAIL] = | |
| 284 | + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, | |
| 285 | + IEEE80211_MAX_DATA_LEN), | |
| 286 | + [NL80211_ATTR_STA_AID] = | |
| 287 | + NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID), | |
| 246 | 288 | [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED }, |
| 247 | 289 | [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 }, |
| 248 | 290 | [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY, |
| 249 | 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 | 294 | [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, |
| 252 | 295 | [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ }, |
| 253 | 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 | 313 | [NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN }, |
| 271 | 314 | |
| 272 | 315 | [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 }, |
| 273 | − [NL80211_ATTR_IE] = { .type = NLA_BINARY, | |
| 274 | − .len = IEEE80211_MAX_DATA_LEN }, | |
| 316 | + [NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY, | |
| 317 | + validate_ie_attr, | |
| 318 | + IEEE80211_MAX_DATA_LEN), | |
| 275 | 319 | [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED }, |
| 276 | 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 | 325 | [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 }, |
| 282 | 326 | [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG }, |
| 283 | 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 | 331 | [NL80211_ATTR_STA_FLAGS2] = { |
| 286 | 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 | 347 | [NL80211_ATTR_FRAME] = { .type = NLA_BINARY, |
| 302 | 348 | .len = IEEE80211_MAX_DATA_LEN }, |
| 303 | 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 | 353 | [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, |
| 306 | 354 | [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, |
| 307 | 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 | 362 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, |
| 315 | 363 | [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, |
| 316 | 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 | 369 | [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, |
| 319 | 370 | [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, |
| 320 | 371 | [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED }, |
| 321 | − [NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 }, | |
| 322 | − [NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY, | |
| 323 | − .len = IEEE80211_MAX_DATA_LEN }, | |
| 324 | − [NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY, | |
| 325 | − .len = IEEE80211_MAX_DATA_LEN }, | |
| 372 | + [NL80211_ATTR_HIDDEN_SSID] = | |
| 373 | + NLA_POLICY_RANGE(NLA_U32, | |
| 374 | + NL80211_HIDDEN_SSID_NOT_IN_USE, | |
| 375 | + NL80211_HIDDEN_SSID_ZERO_CONTENTS), | |
| 376 | + [NL80211_ATTR_IE_PROBE_RESP] = | |
| 377 | + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, | |
| 378 | + IEEE80211_MAX_DATA_LEN), | |
| 379 | + [NL80211_ATTR_IE_ASSOC_RESP] = | |
| 380 | + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, | |
| 381 | + IEEE80211_MAX_DATA_LEN), | |
| 326 | 382 | [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG }, |
| 327 | 383 | [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED }, |
| 328 | 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 | 404 | [NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, }, |
| 349 | 405 | [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN }, |
| 350 | 406 | [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, |
| 351 | − [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, | |
| 352 | − [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, | |
| 353 | − [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 }, | |
| 407 | + [NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127), | |
| 408 | + [NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1), | |
| 409 | + [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = | |
| 410 | + NLA_POLICY_RANGE(NLA_U32, | |
| 411 | + NL80211_MESH_POWER_UNKNOWN + 1, | |
| 412 | + NL80211_MESH_POWER_MAX), | |
| 354 | 413 | [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, |
| 355 | 414 | [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, |
| 356 | 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 | 422 | [NL80211_ATTR_MDID] = { .type = NLA_U16 }, |
| 364 | 423 | [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, |
| 365 | 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 | 427 | [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 }, |
| 368 | 428 | [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG }, |
| 369 | 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 | 444 | [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG }, |
| 385 | 445 | [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY }, |
| 386 | 446 | [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG }, |
| 387 | − [NL80211_ATTR_TSID] = { .type = NLA_U8 }, | |
| 388 | − [NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 }, | |
| 447 | + [NL80211_ATTR_TSID] = NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_TIDS - 1), | |
| 448 | + [NL80211_ATTR_USER_PRIO] = | |
| 449 | + NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1), | |
| 389 | 450 | [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 }, |
| 390 | 451 | [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 }, |
| 391 | 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 | 456 | [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG }, |
| 396 | 457 | [NL80211_ATTR_PBSS] = { .type = NLA_FLAG }, |
| 397 | 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 | 461 | [NL80211_ATTR_MU_MIMO_GROUP_DATA] = { |
| 400 | 462 | .len = VHT_MUMIMO_GROUPS_DATA_LEN |
| 401 | 463 | }, |
| 402 | 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 | 466 | [NL80211_ATTR_BANDS] = { .type = NLA_U32 }, |
| 405 | 467 | [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED }, |
| 406 | 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 | 492 | [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 }, |
| 431 | 493 | [NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY, |
| 432 | 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 | 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 | 507 | [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 }, |
| 441 | 508 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, |
| 442 | 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 | 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 | 558 | static const struct nla_policy |
| 492 | 559 | nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = { |
| 493 | 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 | 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 | 637 | [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 }, |
| 568 | 638 | }; |
| 569 | 639 | |
| 570 | −static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |
| 571 | − struct netlink_callback *cb, | |
| 640 | +static int nl80211_prepare_wdev_dump(struct netlink_callback *cb, | |
| 572 | 641 | struct cfg80211_registered_device **rdev, |
| 573 | 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 | 651 | return err; |
| 583 | 652 | |
| 584 | 653 | *wdev = __cfg80211_wdev_from_attrs( |
| 585 | − sock_net(skb->sk), | |
| 654 | + sock_net(cb->skb->sk), | |
| 586 | 655 | genl_family_attrbuf(&nl80211_fam)); |
| 587 | 656 | if (IS_ERR(*wdev)) |
| 588 | 657 | return PTR_ERR(*wdev); |
| @@ -614,36 +683,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, · 25 unmodified lines | ||
| 614 | 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 | 686 | /* message building helper */ |
| 648 | 687 | static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq, |
| 649 | 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 | 897 | if (tb[NL80211_KEY_CIPHER]) |
| 859 | 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 | 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 | 903 | if (tb[NL80211_KEY_DEFAULT_TYPES]) { |
| 869 | 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 | 945 | if (k->defmgmt) |
| 911 | 946 | k->def_multi = true; |
| 912 | 947 | |
| 913 | − if (info->attrs[NL80211_ATTR_KEY_TYPE]) { | |
| 948 | + if (info->attrs[NL80211_ATTR_KEY_TYPE]) | |
| 914 | 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 | 951 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) { |
| 922 | 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 | 2322 | struct genl_info *info, |
| 2293 | 2323 | struct cfg80211_chan_def *chandef) |
| 2294 | 2324 | { |
| 2325 | + struct netlink_ext_ack *extack = info->extack; | |
| 2326 | + struct nlattr **attrs = info->attrs; | |
| 2295 | 2327 | u32 control_freq; |
| 2296 | 2328 | |
| 2297 | − if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | |
| 2329 | + if (!attrs[NL80211_ATTR_WIPHY_FREQ]) | |
| 2298 | 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 | 2334 | chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq); |
| 2303 | 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 | 2337 | chandef->center_freq2 = 0; |
| 2306 | 2338 | |
| 2307 | 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 | 2343 | return -EINVAL; |
| 2344 | + } | |
| 2310 | 2345 | |
| 2311 | − if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | |
| 2346 | + if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | |
| 2312 | 2347 | enum nl80211_channel_type chantype; |
| 2313 | 2348 | |
| 2314 | − chantype = nla_get_u32( | |
| 2315 | − info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | |
| 2349 | + chantype = nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | |
| 2316 | 2350 | |
| 2317 | 2351 | switch (chantype) { |
| 2318 | 2352 | case NL80211_CHAN_NO_HT: |
| @@ -2322,42 +2356,56 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, · 3 unmodified lines | ||
| 2322 | 2356 | cfg80211_chandef_create(chandef, chandef->chan, |
| 2323 | 2357 | chantype); |
| 2324 | 2358 | /* user input for center_freq is incorrect */ |
| 2325 | − if (info->attrs[NL80211_ATTR_CENTER_FREQ1] && | |
| 2326 | − chandef->center_freq1 != nla_get_u32( | |
| 2327 | − info->attrs[NL80211_ATTR_CENTER_FREQ1])) | |
| 2359 | + if (attrs[NL80211_ATTR_CENTER_FREQ1] && | |
| 2360 | + chandef->center_freq1 != nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1])) { | |
| 2361 | + NL_SET_ERR_MSG_ATTR(extack, | |
| 2362 | + attrs[NL80211_ATTR_CENTER_FREQ1], | |
| 2363 | + "bad center frequency 1"); | |
| 2328 | 2364 | return -EINVAL; |
| 2365 | + } | |
| 2329 | 2366 | /* center_freq2 must be zero */ |
| 2330 | − if (info->attrs[NL80211_ATTR_CENTER_FREQ2] && | |
| 2331 | − nla_get_u32(info->attrs[NL80211_ATTR_CENTER_FREQ2])) | |
| 2367 | + if (attrs[NL80211_ATTR_CENTER_FREQ2] && | |
| 2368 | + nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2])) { | |
| 2369 | + NL_SET_ERR_MSG_ATTR(extack, | |
| 2370 | + attrs[NL80211_ATTR_CENTER_FREQ2], | |
| 2371 | + "center frequency 2 can't be used"); | |
| 2332 | 2372 | return -EINVAL; |
| 2373 | + } | |
| 2333 | 2374 | break; |
| 2334 | 2375 | default: |
| 2376 | + NL_SET_ERR_MSG_ATTR(extack, | |
| 2377 | + attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE], | |
| 2378 | + "invalid channel type"); | |
| 2335 | 2379 | return -EINVAL; |
| 2336 | 2380 | } |
| 2337 | − } else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) { | |
| 2381 | + } else if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) { | |
| 2338 | 2382 | chandef->width = |
| 2339 | − nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]); | |
| 2340 | − if (info->attrs[NL80211_ATTR_CENTER_FREQ1]) | |
| 2383 | + nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH]); | |
| 2384 | + if (attrs[NL80211_ATTR_CENTER_FREQ1]) | |
| 2341 | 2385 | chandef->center_freq1 = |
| 2342 | − nla_get_u32( | |
| 2343 | − info->attrs[NL80211_ATTR_CENTER_FREQ1]); | |
| 2344 | − if (info->attrs[NL80211_ATTR_CENTER_FREQ2]) | |
| 2386 | + nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]); | |
| 2387 | + if (attrs[NL80211_ATTR_CENTER_FREQ2]) | |
| 2345 | 2388 | chandef->center_freq2 = |
| 2346 | − nla_get_u32( | |
| 2347 | − info->attrs[NL80211_ATTR_CENTER_FREQ2]); | |
| 2389 | + nla_get_u32(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 | 2394 | return -EINVAL; |
| 2395 | + } | |
| 2352 | 2396 | |
| 2353 | 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 | 2400 | return -EINVAL; |
| 2401 | + } | |
| 2356 | 2402 | |
| 2357 | 2403 | if ((chandef->width == NL80211_CHAN_WIDTH_5 || |
| 2358 | 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 | 2407 | return -EINVAL; |
| 2408 | + } | |
| 2361 | 2409 | |
| 2362 | 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 | 2665 | if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) { |
| 2618 | 2666 | retry_short = nla_get_u8( |
| 2619 | 2667 | info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]); |
| 2620 | − if (retry_short == 0) | |
| 2621 | − return -EINVAL; | |
| 2622 | 2668 | |
| 2623 | 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 | 2672 | if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) { |
| 2627 | 2673 | retry_long = nla_get_u8( |
| 2628 | 2674 | info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]); |
| 2629 | − if (retry_long == 0) | |
| 2630 | − return -EINVAL; | |
| 2631 | 2675 | |
| 2632 | 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 | 3163 | ntype = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); |
| 3120 | 3164 | if (otype != ntype) |
| 3121 | 3165 | change = true; |
| 3122 | − if (ntype > NL80211_IFTYPE_MAX) | |
| 3123 | − return -EINVAL; | |
| 3124 | 3166 | } |
| 3125 | 3167 | |
| 3126 | 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 | 3227 | if (!info->attrs[NL80211_ATTR_IFNAME]) |
| 3186 | 3228 | return -EINVAL; |
| 3187 | 3229 | |
| 3188 | − if (info->attrs[NL80211_ATTR_IFTYPE]) { | |
| 3230 | + if (info->attrs[NL80211_ATTR_IFTYPE]) | |
| 3189 | 3231 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); |
| 3190 | − if (type > NL80211_IFTYPE_MAX) | |
| 3191 | − return -EINVAL; | |
| 3192 | − } | |
| 3193 | 3232 | |
| 3194 | 3233 | if (!rdev->ops->add_virtual_intf || |
| 3195 | 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 | 3291 | * P2P Device and NAN do not have a netdev, so don't go |
| 3253 | 3292 | * through the netdev notifier and must be added here |
| 3254 | 3293 | */ |
| 3255 | − mutex_init(&wdev->mtx); | |
| 3256 | − INIT_LIST_HEAD(&wdev->event_list); | |
| 3257 | − spin_lock_init(&wdev->event_lock); | |
| 3258 | − INIT_LIST_HEAD(&wdev->mgmt_registrations); | |
| 3259 | − spin_lock_init(&wdev->mgmt_registrations_lock); | |
| 3260 | − | |
| 3261 | − wdev->identifier = ++rdev->wdev_id; | |
| 3262 | − list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list); | |
| 3263 | − rdev->devlist_generation++; | |
| 3294 | + cfg80211_init_wdev(rdev, wdev); | |
| 3264 | 3295 | break; |
| 3265 | 3296 | default: |
| 3266 | 3297 | break; |
| @@ -3272,15 +3303,6 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) · 5 unmodified lines | ||
| 3272 | 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 | 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 | 3381 | params->cipher))) |
| 3360 | 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 | 3385 | goto nla_put_failure; |
| 3364 | 3386 | |
| 3365 | 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 | 3408 | if (info->attrs[NL80211_ATTR_KEY_IDX]) |
| 3387 | 3409 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); |
| 3388 | 3410 | |
| 3389 | − if (key_idx > 5) | |
| 3390 | − return -EINVAL; | |
| 3391 | − | |
| 3392 | 3411 | if (info->attrs[NL80211_ATTR_MAC]) |
| 3393 | 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 | 3415 | if (info->attrs[NL80211_ATTR_KEY_TYPE]) { |
| 3397 | 3416 | u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); |
| 3398 | 3417 | |
| 3399 | − if (kt >= NUM_NL80211_KEYTYPES) | |
| 3400 | − return -EINVAL; | |
| 3401 | 3418 | if (kt != NL80211_KEYTYPE_GROUP && |
| 3402 | 3419 | kt != NL80211_KEYTYPE_PAIRWISE) |
| 3403 | 3420 | return -EINVAL; |
| @@ -3998,16 +4015,12 @@ static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev, · 594 unmodified lines | ||
| 3998 | 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 | 4020 | struct cfg80211_beacon_data *bcn) |
| 4003 | 4021 | { |
| 4004 | 4022 | bool haveinfo = false; |
| 4005 | − | |
| 4006 | − if (!is_valid_ie_attr(attrs[NL80211_ATTR_BEACON_TAIL]) || | |
| 4007 | − !is_valid_ie_attr(attrs[NL80211_ATTR_IE]) || | |
| 4008 | − !is_valid_ie_attr(attrs[NL80211_ATTR_IE_PROBE_RESP]) || | |
| 4009 | − !is_valid_ie_attr(attrs[NL80211_ATTR_IE_ASSOC_RESP])) | |
| 4010 | − return -EINVAL; | |
| 4023 | + int err; | |
| 4011 | 4024 | |
| 4012 | 4025 | memset(bcn, 0, sizeof(*bcn)); |
| 4013 | 4026 | |
| @@ -4052,6 +4065,35 @@ static int nl80211_parse_beacon(struct nlattr *attrs[], · 38 unmodified lines | ||
| 4052 | 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 | 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 | 4240 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) |
| 4199 | 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 | 4244 | if (err) |
| 4203 | 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 | 4270 | return -EINVAL; |
| 4229 | 4271 | } |
| 4230 | 4272 | |
| 4231 | − if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) { | |
| 4273 | + if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) | |
| 4232 | 4274 | params.hidden_ssid = nla_get_u32( |
| 4233 | 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 | 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 | 4302 | return -EINVAL; |
| 4266 | 4303 | params.p2p_ctwindow = |
| 4267 | 4304 | nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]); |
| 4268 | − if (params.p2p_ctwindow > 127) | |
| 4269 | − return -EINVAL; | |
| 4270 | 4305 | if (params.p2p_ctwindow != 0 && |
| 4271 | 4306 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) |
| 4272 | 4307 | return -EINVAL; |
| @@ -4278,8 +4313,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 5 unmodified lines | ||
| 4278 | 4313 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
| 4279 | 4314 | return -EINVAL; |
| 4280 | 4315 | tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]); |
| 4281 | − if (tmp > 1) | |
| 4282 | − return -EINVAL; | |
| 4283 | 4316 | params.p2p_opp_ps = tmp; |
| 4284 | 4317 | if (params.p2p_opp_ps != 0 && |
| 4285 | 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 | 4415 | if (!wdev->beacon_interval) |
| 4383 | 4416 | return -EINVAL; |
| 4384 | 4417 | |
| 4385 | − err = nl80211_parse_beacon(info->attrs, ¶ms); | |
| 4418 | + err = nl80211_parse_beacon(rdev, info->attrs, ¶ms); | |
| 4386 | 4419 | if (err) |
| 4387 | 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 | 4761 | PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc); |
| 4729 | 4762 | PUT_SINFO_U64(BEACON_RX, rx_beacon); |
| 4730 | 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 | 4766 | if (wiphy_ext_feature_isset(&rdev->wiphy, |
| 4732 | 4767 | NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) { |
| 4733 | 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 | 4846 | int err; |
| 4812 | 4847 | |
| 4813 | 4848 | rtnl_lock(); |
| 4814 | − err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | |
| 4849 | + err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); | |
| 4815 | 4850 | if (err) |
| 4816 | 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 | 5251 | else |
| 5217 | 5252 | params.listen_interval = -1; |
| 5218 | 5253 | |
| 5219 | − if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) { | |
| 5220 | − u8 tmp; | |
| 5221 | − | |
| 5222 | − tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]); | |
| 5223 | − if (tmp >= NUM_NL80211_P2P_PS_STATUS) | |
| 5224 | − return -EINVAL; | |
| 5225 | − | |
| 5226 | − params.support_p2p_ps = tmp; | |
| 5227 | − } else { | |
| 5254 | + if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) | |
| 5255 | + params.support_p2p_ps = | |
| 5256 | + nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]); | |
| 5257 | + else | |
| 5228 | 5258 | params.support_p2p_ps = -1; |
| 5229 | − } | |
| 5230 | 5259 | |
| 5231 | 5260 | if (!info->attrs[NL80211_ATTR_MAC]) |
| 5232 | 5261 | return -EINVAL; |
| @@ -5256,38 +5285,23 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 23 unmodified lines | ||
| 5256 | 5285 | if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) |
| 5257 | 5286 | return -EINVAL; |
| 5258 | 5287 | |
| 5259 | − if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) { | |
| 5288 | + if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) | |
| 5260 | 5289 | params.plink_action = |
| 5261 | 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 | 5292 | if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) { |
| 5267 | 5293 | params.plink_state = |
| 5268 | 5294 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); |
| 5269 | − if (params.plink_state >= NUM_NL80211_PLINK_STATES) | |
| 5270 | − return -EINVAL; | |
| 5271 | − if (info->attrs[NL80211_ATTR_MESH_PEER_AID]) { | |
| 5295 | + if (info->attrs[NL80211_ATTR_MESH_PEER_AID]) | |
| 5272 | 5296 | params.peer_aid = nla_get_u16( |
| 5273 | 5297 | info->attrs[NL80211_ATTR_MESH_PEER_AID]); |
| 5274 | − if (params.peer_aid > IEEE80211_MAX_AID) | |
| 5275 | − return -EINVAL; | |
| 5276 | − } | |
| 5277 | 5298 | params.sta_modify_mask |= STATION_PARAM_APPLY_PLINK_STATE; |
| 5278 | 5299 | } |
| 5279 | 5300 | |
| 5280 | − if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) { | |
| 5281 | − enum nl80211_mesh_power_mode pm = nla_get_u32( | |
| 5301 | + if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) | |
| 5302 | + params.local_pm = nla_get_u32( | |
| 5282 | 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 | 5305 | if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) { |
| 5292 | 5306 | params.opmode_notif_used = true; |
| 5293 | 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 | 5378 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
| 5365 | 5379 | |
| 5366 | 5380 | if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) { |
| 5367 | − u8 tmp; | |
| 5368 | − | |
| 5369 | − tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]); | |
| 5370 | − if (tmp >= NUM_NL80211_P2P_PS_STATUS) | |
| 5371 | − return -EINVAL; | |
| 5372 | − | |
| 5373 | − params.support_p2p_ps = tmp; | |
| 5381 | + params.support_p2p_ps = | |
| 5382 | + nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]); | |
| 5374 | 5383 | } else { |
| 5375 | 5384 | /* |
| 5376 | 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 | 5393 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); |
| 5385 | 5394 | else |
| 5386 | 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 | 5397 | if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) { |
| 5391 | 5398 | params.capability = |
| @@ -5425,12 +5432,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) · 33 unmodified lines | ||
| 5425 | 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 | 5436 | params.plink_action = |
| 5430 | 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 | 5439 | err = nl80211_parse_sta_channel_info(info, ¶ms); |
| 5436 | 5440 | if (err) |
| @@ -5662,7 +5666,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, · 225 unmodified lines | ||
| 5662 | 5666 | int err; |
| 5663 | 5667 | |
| 5664 | 5668 | rtnl_lock(); |
| 5665 | − err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | |
| 5669 | + err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); | |
| 5666 | 5670 | if (err) |
| 5667 | 5671 | goto out_err; |
| 5668 | 5672 | |
| @@ -5858,7 +5862,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb, · 189 unmodified lines | ||
| 5858 | 5862 | int err; |
| 5859 | 5863 | |
| 5860 | 5864 | rtnl_lock(); |
| 5861 | − err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | |
| 5865 | + err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); | |
| 5862 | 5866 | if (err) |
| 5863 | 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 | 5944 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
| 5941 | 5945 | return -EINVAL; |
| 5942 | 5946 | params.p2p_ctwindow = |
| 5943 | − nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]); | |
| 5944 | − if (params.p2p_ctwindow < 0) | |
| 5945 | − return -EINVAL; | |
| 5947 | + nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]); | |
| 5946 | 5948 | if (params.p2p_ctwindow != 0 && |
| 5947 | 5949 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) |
| 5948 | 5950 | return -EINVAL; |
| @@ -5954,8 +5956,6 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) · 5 unmodified lines | ||
| 5954 | 5956 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
| 5955 | 5957 | return -EINVAL; |
| 5956 | 5958 | tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]); |
| 5957 | − if (tmp > 1) | |
| 5958 | − return -EINVAL; | |
| 5959 | 5959 | params.p2p_opp_ps = tmp; |
| 5960 | 5960 | if (params.p2p_opp_ps && |
| 5961 | 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 | 6134 | return -ENOBUFS; |
| 6135 | 6135 | } |
| 6136 | 6136 | |
| 6137 | −static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = { | |
| 6138 | − [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 }, | |
| 6139 | − [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 }, | |
| 6140 | − [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 }, | |
| 6141 | − [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 }, | |
| 6142 | − [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 }, | |
| 6143 | − [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, | |
| 6144 | − [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 }, | |
| 6145 | − [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, | |
| 6146 | − [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 }, | |
| 6137 | +static const struct nla_policy | |
| 6138 | +nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = { | |
| 6139 | + [NL80211_MESHCONF_RETRY_TIMEOUT] = | |
| 6140 | + NLA_POLICY_RANGE(NLA_U16, 1, 255), | |
| 6141 | + [NL80211_MESHCONF_CONFIRM_TIMEOUT] = | |
| 6142 | + NLA_POLICY_RANGE(NLA_U16, 1, 255), | |
| 6143 | + [NL80211_MESHCONF_HOLDING_TIMEOUT] = | |
| 6144 | + NLA_POLICY_RANGE(NLA_U16, 1, 255), | |
| 6145 | + [NL80211_MESHCONF_MAX_PEER_LINKS] = | |
| 6146 | + NLA_POLICY_RANGE(NLA_U16, 0, 255), | |
| 6147 | + [NL80211_MESHCONF_MAX_RETRIES] = NLA_POLICY_MAX(NLA_U8, 16), | |
| 6148 | + [NL80211_MESHCONF_TTL] = NLA_POLICY_MIN(NLA_U8, 1), | |
| 6149 | + [NL80211_MESHCONF_ELEMENT_TTL] = NLA_POLICY_MIN(NLA_U8, 1), | |
| 6150 | + [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = NLA_POLICY_MAX(NLA_U8, 1), | |
| 6151 | + [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = | |
| 6152 | + NLA_POLICY_RANGE(NLA_U32, 1, 255), | |
| 6147 | 6153 | [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, |
| 6148 | 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 | 6156 | [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, |
| 6151 | − [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, | |
| 6152 | − [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 }, | |
| 6153 | − [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, | |
| 6154 | − [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, | |
| 6155 | − [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, | |
| 6156 | − [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, | |
| 6157 | − [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 }, | |
| 6158 | − [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32 }, | |
| 6157 | + [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = | |
| 6158 | + NLA_POLICY_MIN(NLA_U16, 1), | |
| 6159 | + [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = | |
| 6160 | + NLA_POLICY_MIN(NLA_U16, 1), | |
| 6161 | + [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = | |
| 6162 | + NLA_POLICY_MIN(NLA_U16, 1), | |
| 6163 | + [NL80211_MESHCONF_HWMP_ROOTMODE] = NLA_POLICY_MAX(NLA_U8, 4), | |
| 6164 | + [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = | |
| 6165 | + NLA_POLICY_MIN(NLA_U16, 1), | |
| 6166 | + [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = NLA_POLICY_MAX(NLA_U8, 1), | |
| 6167 | + [NL80211_MESHCONF_FORWARDING] = NLA_POLICY_MAX(NLA_U8, 1), | |
| 6168 | + [NL80211_MESHCONF_RSSI_THRESHOLD] = | |
| 6169 | + NLA_POLICY_RANGE(NLA_S32, -255, 0), | |
| 6159 | 6170 | [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 }, |
| 6160 | 6171 | [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 }, |
| 6161 | − [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 }, | |
| 6162 | − [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, | |
| 6163 | − [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 }, | |
| 6172 | + [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = | |
| 6173 | + NLA_POLICY_MIN(NLA_U16, 1), | |
| 6174 | + [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = | |
| 6175 | + NLA_POLICY_MIN(NLA_U16, 1), | |
| 6176 | + [NL80211_MESHCONF_POWER_MODE] = | |
| 6177 | + NLA_POLICY_RANGE(NLA_U32, | |
| 6178 | + NL80211_MESH_POWER_ACTIVE, | |
| 6179 | + NL80211_MESH_POWER_MAX), | |
| 6164 | 6180 | [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 }, |
| 6165 | 6181 | [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 }, |
| 6166 | 6182 | }; |
| @@ -6173,68 +6189,12 @@ static const struct nla_policy · 6 unmodified lines | ||
| 6173 | 6189 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, |
| 6174 | 6190 | [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 }, |
| 6175 | 6191 | [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG }, |
| 6176 | − [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, | |
| 6177 | − .len = IEEE80211_MAX_DATA_LEN }, | |
| 6192 | + [NL80211_MESH_SETUP_IE] = | |
| 6193 | + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, | |
| 6194 | + IEEE80211_MAX_DATA_LEN), | |
| 6178 | 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 | 6198 | static int nl80211_parse_mesh_config(struct genl_info *info, |
| 6239 | 6199 | struct mesh_config *cfg, |
| 6240 | 6200 | u32 *mask_out) |
| @@ -6243,13 +6203,12 @@ static int nl80211_parse_mesh_config(struct genl_info *info, · 2 unmodified lines | ||
| 6243 | 6203 | u32 mask = 0; |
| 6244 | 6204 | u16 ht_opmode; |
| 6245 | 6205 | |
| 6246 | −#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \ | |
| 6247 | −do { \ | |
| 6248 | − if (tb[attr]) { \ | |
| 6249 | − if (fn(tb[attr], min, max, &cfg->param)) \ | |
| 6250 | − return -EINVAL; \ | |
| 6251 | − mask |= (1 << (attr - 1)); \ | |
| 6252 | − } \ | |
| 6206 | +#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, mask, attr, fn) \ | |
| 6207 | +do { \ | |
| 6208 | + if (tb[attr]) { \ | |
| 6209 | + cfg->param = fn(tb[attr]); \ | |
| 6210 | + mask |= BIT((attr) - 1); \ | |
| 6211 | + } \ | |
| 6253 | 6212 | } while (0) |
| 6254 | 6213 | |
| 6255 | 6214 | if (!info->attrs[NL80211_ATTR_MESH_CONFIG]) |
| @@ -6264,75 +6223,73 @@ do { \ · 8 unmodified lines | ||
| 6264 | 6223 | BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32); |
| 6265 | 6224 | |
| 6266 | 6225 | /* Fill in the params struct */ |
| 6267 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255, | |
| 6268 | − mask, NL80211_MESHCONF_RETRY_TIMEOUT, | |
| 6269 | − nl80211_check_u16); | |
| 6270 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255, | |
| 6271 | − mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, | |
| 6272 | − nl80211_check_u16); | |
| 6273 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255, | |
| 6274 | − mask, NL80211_MESHCONF_HOLDING_TIMEOUT, | |
| 6275 | − nl80211_check_u16); | |
| 6276 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255, | |
| 6277 | − mask, NL80211_MESHCONF_MAX_PEER_LINKS, | |
| 6278 | − nl80211_check_u16); | |
| 6279 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16, | |
| 6280 | − mask, NL80211_MESHCONF_MAX_RETRIES, | |
| 6281 | − nl80211_check_u8); | |
| 6282 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255, | |
| 6283 | − mask, NL80211_MESHCONF_TTL, nl80211_check_u8); | |
| 6284 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255, | |
| 6285 | − mask, NL80211_MESHCONF_ELEMENT_TTL, | |
| 6286 | − nl80211_check_u8); | |
| 6287 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1, | |
| 6288 | − mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, | |
| 6289 | − nl80211_check_bool); | |
| 6226 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, mask, | |
| 6227 | + NL80211_MESHCONF_RETRY_TIMEOUT, nla_get_u16); | |
| 6228 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, mask, | |
| 6229 | + NL80211_MESHCONF_CONFIRM_TIMEOUT, | |
| 6230 | + nla_get_u16); | |
| 6231 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, mask, | |
| 6232 | + NL80211_MESHCONF_HOLDING_TIMEOUT, | |
| 6233 | + nla_get_u16); | |
| 6234 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, mask, | |
| 6235 | + NL80211_MESHCONF_MAX_PEER_LINKS, | |
| 6236 | + nla_get_u16); | |
| 6237 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, mask, | |
| 6238 | + NL80211_MESHCONF_MAX_RETRIES, nla_get_u8); | |
| 6239 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, mask, | |
| 6240 | + NL80211_MESHCONF_TTL, nla_get_u8); | |
| 6241 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, mask, | |
| 6242 | + NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8); | |
| 6243 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, mask, | |
| 6244 | + NL80211_MESHCONF_AUTO_OPEN_PLINKS, | |
| 6245 | + nla_get_u8); | |
| 6290 | 6246 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor, |
| 6291 | − 1, 255, mask, | |
| 6247 | + mask, | |
| 6292 | 6248 | NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, |
| 6293 | − nl80211_check_u32); | |
| 6294 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255, | |
| 6295 | − mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | |
| 6296 | − nl80211_check_u8); | |
| 6297 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535, | |
| 6298 | − mask, NL80211_MESHCONF_PATH_REFRESH_TIME, | |
| 6299 | − nl80211_check_u32); | |
| 6300 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535, | |
| 6301 | − mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | |
| 6302 | − nl80211_check_u16); | |
| 6249 | + nla_get_u32); | |
| 6250 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, mask, | |
| 6251 | + NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | |
| 6252 | + nla_get_u8); | |
| 6253 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, mask, | |
| 6254 | + NL80211_MESHCONF_PATH_REFRESH_TIME, | |
| 6255 | + nla_get_u32); | |
| 6256 | + if (mask & BIT(NL80211_MESHCONF_PATH_REFRESH_TIME) && | |
| 6257 | + (cfg->path_refresh_time < 1 || cfg->path_refresh_time > 65535)) | |
| 6258 | + return -EINVAL; | |
| 6259 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, mask, | |
| 6260 | + NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | |
| 6261 | + nla_get_u16); | |
| 6303 | 6262 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, |
| 6304 | − 1, 65535, mask, | |
| 6263 | + mask, | |
| 6305 | 6264 | NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, |
| 6306 | − nl80211_check_u32); | |
| 6307 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, | |
| 6308 | − 1, 65535, mask, | |
| 6265 | + nla_get_u32); | |
| 6266 | + if (mask & BIT(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT) && | |
| 6267 | + (cfg->dot11MeshHWMPactivePathTimeout < 1 || | |
| 6268 | + cfg->dot11MeshHWMPactivePathTimeout > 65535)) | |
| 6269 | + return -EINVAL; | |
| 6270 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask, | |
| 6309 | 6271 | NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, |
| 6310 | − nl80211_check_u16); | |
| 6311 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, | |
| 6312 | − 1, 65535, mask, | |
| 6272 | + nla_get_u16); | |
| 6273 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, mask, | |
| 6313 | 6274 | NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, |
| 6314 | − nl80211_check_u16); | |
| 6275 | + nla_get_u16); | |
| 6315 | 6276 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, |
| 6316 | − dot11MeshHWMPnetDiameterTraversalTime, | |
| 6317 | − 1, 65535, mask, | |
| 6277 | + dot11MeshHWMPnetDiameterTraversalTime, mask, | |
| 6318 | 6278 | NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, |
| 6319 | − nl80211_check_u16); | |
| 6320 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4, | |
| 6321 | − mask, NL80211_MESHCONF_HWMP_ROOTMODE, | |
| 6322 | − nl80211_check_u8); | |
| 6323 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535, | |
| 6324 | − mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL, | |
| 6325 | − nl80211_check_u16); | |
| 6326 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, | |
| 6327 | − dot11MeshGateAnnouncementProtocol, 0, 1, | |
| 6279 | + nla_get_u16); | |
| 6280 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask, | |
| 6281 | + NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8); | |
| 6282 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask, | |
| 6283 | + NL80211_MESHCONF_HWMP_RANN_INTERVAL, | |
| 6284 | + nla_get_u16); | |
| 6285 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshGateAnnouncementProtocol, | |
| 6328 | 6286 | mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, |
| 6329 | − nl80211_check_bool); | |
| 6330 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1, | |
| 6331 | − mask, NL80211_MESHCONF_FORWARDING, | |
| 6332 | − nl80211_check_bool); | |
| 6333 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0, | |
| 6334 | − mask, NL80211_MESHCONF_RSSI_THRESHOLD, | |
| 6335 | − nl80211_check_s32); | |
| 6287 | + nla_get_u8); | |
| 6288 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, mask, | |
| 6289 | + NL80211_MESHCONF_FORWARDING, nla_get_u8); | |
| 6290 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask, | |
| 6291 | + NL80211_MESHCONF_RSSI_THRESHOLD, | |
| 6292 | + nla_get_s32); | |
| 6336 | 6293 | /* |
| 6337 | 6294 | * Check HT operation mode based on |
| 6338 | 6295 | * IEEE 802.11-2016 9.4.2.57 HT Operation element. |
| @@ -6351,29 +6308,27 @@ do { \ · 12 unmodified lines | ||
| 6351 | 6308 | cfg->ht_opmode = ht_opmode; |
| 6352 | 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 | 6311 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, |
| 6362 | − dot11MeshHWMPconfirmationInterval, | |
| 6363 | − 1, 65535, mask, | |
| 6312 | + dot11MeshHWMPactivePathToRootTimeout, mask, | |
| 6313 | + NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, | |
| 6314 | + nla_get_u32); | |
| 6315 | + if (mask & BIT(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT) && | |
| 6316 | + (cfg->dot11MeshHWMPactivePathToRootTimeout < 1 || | |
| 6317 | + cfg->dot11MeshHWMPactivePathToRootTimeout > 65535)) | |
| 6318 | + return -EINVAL; | |
| 6319 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, mask, | |
| 6320 | + NL80211_MESHCONF_HWMP_ROOT_INTERVAL, | |
| 6321 | + nla_get_u16); | |
| 6322 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPconfirmationInterval, | |
| 6323 | + mask, | |
| 6364 | 6324 | NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, |
| 6365 | − nl80211_check_u16); | |
| 6366 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, | |
| 6367 | − NL80211_MESH_POWER_ACTIVE, | |
| 6368 | − NL80211_MESH_POWER_MAX, | |
| 6369 | − mask, NL80211_MESHCONF_POWER_MODE, | |
| 6370 | − nl80211_check_power_mode); | |
| 6371 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, | |
| 6372 | − 0, 65535, mask, | |
| 6373 | − NL80211_MESHCONF_AWAKE_WINDOW, nl80211_check_u16); | |
| 6374 | − FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff, | |
| 6375 | − mask, NL80211_MESHCONF_PLINK_TIMEOUT, | |
| 6376 | − nl80211_check_u32); | |
| 6325 | + nla_get_u16); | |
| 6326 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, mask, | |
| 6327 | + NL80211_MESHCONF_POWER_MODE, nla_get_u32); | |
| 6328 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, mask, | |
| 6329 | + NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); | |
| 6330 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, mask, | |
| 6331 | + NL80211_MESHCONF_PLINK_TIMEOUT, nla_get_u32); | |
| 6377 | 6332 | if (mask_out) |
| 6378 | 6333 | *mask_out = mask; |
| 6379 | 6334 | |
| @@ -6416,8 +6371,6 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, · 36 unmodified lines | ||
| 6416 | 6371 | if (tb[NL80211_MESH_SETUP_IE]) { |
| 6417 | 6372 | struct nlattr *ieattr = |
| 6418 | 6373 | tb[NL80211_MESH_SETUP_IE]; |
| 6419 | − if (!is_valid_ie_attr(ieattr)) | |
| 6420 | − return -EINVAL; | |
| 6421 | 6374 | setup->ie = nla_data(ieattr); |
| 6422 | 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 | 7003 | int err, tmp, n_ssids = 0, n_channels, i; |
| 7051 | 7004 | size_t ie_len; |
| 7052 | 7005 | |
| 7053 | − if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | |
| 7054 | − return -EINVAL; | |
| 7055 | − | |
| 7056 | 7006 | wiphy = &rdev->wiphy; |
| 7057 | 7007 | |
| 7058 | 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 | 7356 | struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; |
| 7407 | 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 | 7359 | if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
| 7413 | 7360 | n_channels = validate_scan_freqs( |
| 7414 | 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 | 7716 | if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1) { |
| 7770 | 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 | 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 | 7891 | if (!need_new_beacon) |
| 7945 | 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 | 7895 | if (err) |
| 7949 | 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 | 7901 | if (err) |
| 7955 | 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 | 7905 | if (err) |
| 7959 | 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 | 8138 | int err; |
| 8192 | 8139 | |
| 8193 | 8140 | rtnl_lock(); |
| 8194 | − err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | |
| 8141 | + err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); | |
| 8195 | 8142 | if (err) { |
| 8196 | 8143 | rtnl_unlock(); |
| 8197 | 8144 | return err; |
| @@ -8312,7 +8259,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) · 114 unmodified lines | ||
| 8312 | 8259 | bool radio_stats; |
| 8313 | 8260 | |
| 8314 | 8261 | rtnl_lock(); |
| 8315 | − res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | |
| 8262 | + res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); | |
| 8316 | 8263 | if (res) |
| 8317 | 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 | 8323 | struct key_parse key; |
| 8377 | 8324 | bool local_state_change; |
| 8378 | 8325 | |
| 8379 | − if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | |
| 8380 | − return -EINVAL; | |
| 8381 | − | |
| 8382 | 8326 | if (!info->attrs[NL80211_ATTR_MAC]) |
| 8383 | 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 | 8561 | dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid) |
| 8618 | 8562 | return -EPERM; |
| 8619 | 8563 | |
| 8620 | − if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | |
| 8621 | − return -EINVAL; | |
| 8622 | − | |
| 8623 | 8564 | if (!info->attrs[NL80211_ATTR_MAC] || |
| 8624 | 8565 | !info->attrs[NL80211_ATTR_SSID] || |
| 8625 | 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 | 8684 | dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid) |
| 8744 | 8685 | return -EPERM; |
| 8745 | 8686 | |
| 8746 | − if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | |
| 8747 | − return -EINVAL; | |
| 8748 | − | |
| 8749 | 8687 | if (!info->attrs[NL80211_ATTR_MAC]) |
| 8750 | 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 | 8732 | dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid) |
| 8795 | 8733 | return -EPERM; |
| 8796 | 8734 | |
| 8797 | − if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | |
| 8798 | − return -EINVAL; | |
| 8799 | − | |
| 8800 | 8735 | if (!info->attrs[NL80211_ATTR_MAC]) |
| 8801 | 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 | 8807 | memset(&ibss, 0, sizeof(ibss)); |
| 8873 | 8808 | |
| 8874 | − if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | |
| 8875 | − return -EINVAL; | |
| 8876 | − | |
| 8877 | 8809 | if (!info->attrs[NL80211_ATTR_SSID] || |
| 8878 | 8810 | !nla_len(info->attrs[NL80211_ATTR_SSID])) |
| 8879 | 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 | 9244 | memset(&connect, 0, sizeof(connect)); |
| 9313 | 9245 | |
| 9314 | − if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | |
| 9315 | − return -EINVAL; | |
| 9316 | − | |
| 9317 | 9246 | if (!info->attrs[NL80211_ATTR_SSID] || |
| 9318 | 9247 | !nla_len(info->attrs[NL80211_ATTR_SSID])) |
| 9319 | 9248 | return -EINVAL; |
| @@ -9372,11 +9301,6 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) · 52 unmodified lines | ||
| 9372 | 9301 | !wiphy_ext_feature_isset(&rdev->wiphy, |
| 9373 | 9302 | NL80211_EXT_FEATURE_MFP_OPTIONAL)) |
| 9374 | 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 | 9304 | } else { |
| 9381 | 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 | 9473 | return -EOPNOTSUPP; |
| 9550 | 9474 | |
| 9551 | 9475 | if (info->attrs[NL80211_ATTR_IE]) { |
| 9552 | − if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | |
| 9553 | − return -EINVAL; | |
| 9554 | 9476 | connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]); |
| 9555 | 9477 | connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
| 9556 | 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 | 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 | 10060 | wdev = dev->ieee80211_ptr; |
| 10142 | 10061 | |
| 10143 | 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 | 10619 | if (!scan_plan) |
| 10701 | 10620 | return -ENOBUFS; |
| 10702 | 10621 | |
| 10703 | − if (!scan_plan || | |
| 10704 | − nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL, | |
| 10622 | + if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL, | |
| 10705 | 10623 | req->scan_plans[i].interval) || |
| 10706 | 10624 | (req->scan_plans[i].iterations && |
| 10707 | 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 | 11217 | if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION]) |
| 11300 | 11218 | new_rule->condition = |
| 11301 | 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 | 11221 | if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN]) |
| 11307 | 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 | 11570 | conf.master_pref = |
| 11656 | 11571 | nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]); |
| 11657 | − if (!conf.master_pref) | |
| 11658 | − return -EINVAL; | |
| 11659 | 11572 | |
| 11660 | 11573 | if (info->attrs[NL80211_ATTR_BANDS]) { |
| 11661 | 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 | 11686 | if (!func) |
| 11774 | 11687 | return -ENOMEM; |
| 11775 | 11688 | |
| 11776 | − func->cookie = wdev->wiphy->cookie_counter++; | |
| 11689 | + func->cookie = cfg80211_assign_cookie(rdev); | |
| 11777 | 11690 | |
| 11778 | 11691 | if (!tb[NL80211_NAN_FUNC_TYPE] || |
| 11779 | 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 | 12132 | return -EOPNOTSUPP; |
| 12220 | 12133 | |
| 12221 | 12134 | if (!info->attrs[NL80211_ATTR_MDID] || |
| 12222 | − !info->attrs[NL80211_ATTR_IE] || | |
| 12223 | − !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | |
| 12135 | + !info->attrs[NL80211_ATTR_IE]) | |
| 12224 | 12136 | return -EINVAL; |
| 12225 | 12137 | |
| 12226 | 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 | 12552 | return -EINVAL; |
| 12641 | 12553 | |
| 12642 | 12554 | tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]); |
| 12643 | − if (tsid >= IEEE80211_NUM_TIDS) | |
| 12644 | − return -EINVAL; | |
| 12645 | − | |
| 12646 | 12555 | up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]); |
| 12647 | − if (up >= IEEE80211_NUM_UPS) | |
| 12648 | − return -EINVAL; | |
| 12649 | 12556 | |
| 12650 | 12557 | /* WMM uses TIDs 0-7 even for TSPEC */ |
| 12651 | 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 | 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 | 12983 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
| 13007 | 12984 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
| 13008 | 12985 | #define NL80211_FLAG_NEED_RTNL 0x04 |
| @@ -13914,6 +13891,13 @@ static const struct genl_ops nl80211_ops[] = { · 905 unmodified lines | ||
| 13914 | 13891 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
| 13915 | 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 | 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 | 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 | 1250 | #endif /* __CFG80211_RDEV_OPS */ |
| @@ -3831,6 +3831,15 @@ static int __init regulatory_init_db(void) · 3830 unmodified lines | ||
| 3831 | 3831 | { |
| 3832 | 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 | 3843 | err = load_builtin_regdb_keys(); |
| 3835 | 3844 | if (err) |
| 3836 | 3845 | return err; |
| @@ -2368,6 +2368,140 @@ TRACE_EVENT(rdev_external_auth, · 2367 unmodified lines | ||
| 2368 | 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 | 2506 | * cfg80211 exported functions traces * |
| 2373 | 2507 | *************************************************************/ |
| @@ -3160,105 +3294,6 @@ TRACE_EVENT(cfg80211_stop_iface, · 786 unmodified lines | ||
| 3160 | 3294 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, |
| 3161 | 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 | 3297 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ |
| 3263 | 3298 | |
| 3264 | 3299 | #undef TRACE_INCLUDE_PATH |