Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

+1306 -560
+2 -2
include/linux/ieee80211.h
··· 1391 1391 #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 1392 1392 #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 1393 1393 #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 1394 - #define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 1395 - #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00030000 1394 + #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX 0x0000e000 1395 + #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00070000 1396 1396 #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 1397 1397 #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 1398 1398 #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
+9
include/net/cfg80211.h
··· 437 437 u32 prohibited_flags); 438 438 439 439 /** 440 + * cfg80211_chandef_dfs_required - checks if radar detection is required 441 + * @wiphy: the wiphy to validate against 442 + * @chandef: the channel definition to check 443 + * Return: 1 if radar detection is required, 0 if it is not, < 0 on error 444 + */ 445 + int cfg80211_chandef_dfs_required(struct wiphy *wiphy, 446 + const struct cfg80211_chan_def *chandef); 447 + 448 + /** 440 449 * ieee80211_chandef_rate_flags - returns rate flags for a channel 441 450 * 442 451 * In some channel types, not all rates may be used - for example CCK
+42
include/net/mac80211.h
··· 829 829 * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 830 830 * @RX_FLAG_10MHZ: 10 MHz (half channel) was used 831 831 * @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used 832 + * @RX_FLAG_AMSDU_MORE: Some drivers may prefer to report separate A-MSDU 833 + * subframes instead of a one huge frame for performance reasons. 834 + * All, but the last MSDU from an A-MSDU should have this flag set. E.g. 835 + * if an A-MSDU has 3 frames, the first 2 must have the flag set, while 836 + * the 3rd (last) one must not have this flag set. The flag is used to 837 + * deal with retransmission/duplication recovery properly since A-MSDU 838 + * subframes share the same sequence number. Reported subframes can be 839 + * either regular MSDU or singly A-MSDUs. Subframes must not be 840 + * interleaved with other frames. 832 841 */ 833 842 enum mac80211_rx_flags { 834 843 RX_FLAG_MMIC_ERROR = BIT(0), ··· 868 859 RX_FLAG_STBC_MASK = BIT(26) | BIT(27), 869 860 RX_FLAG_10MHZ = BIT(28), 870 861 RX_FLAG_5MHZ = BIT(29), 862 + RX_FLAG_AMSDU_MORE = BIT(30), 871 863 }; 872 864 873 865 #define RX_FLAG_STBC_SHIFT 26 ··· 1502 1492 * 1503 1493 * @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames 1504 1494 * only, to allow getting TBTT of a DTIM beacon. 1495 + * 1496 + * @IEEE80211_HW_CHANCTX_STA_CSA: Support 802.11h based channel-switch (CSA) 1497 + * for a single active channel while using channel contexts. When support 1498 + * is not enabled the default action is to disconnect when getting the 1499 + * CSA frame. 1505 1500 */ 1506 1501 enum ieee80211_hw_flags { 1507 1502 IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, ··· 1537 1522 IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, 1538 1523 IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26, 1539 1524 IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27, 1525 + IEEE80211_HW_CHANCTX_STA_CSA = 1<<28, 1540 1526 }; 1541 1527 1542 1528 /** ··· 2682 2666 * zero using ieee80211_csa_is_complete() after the beacon has been 2683 2667 * transmitted and then call ieee80211_csa_finish(). 2684 2668 * 2669 + * @join_ibss: Join an IBSS (on an IBSS interface); this is called after all 2670 + * information in bss_conf is set up and the beacon can be retrieved. A 2671 + * channel context is bound before this is called. 2672 + * @leave_ibss: Leave the IBSS again. 2685 2673 */ 2686 2674 struct ieee80211_ops { 2687 2675 void (*tx)(struct ieee80211_hw *hw, ··· 2877 2857 void (*channel_switch_beacon)(struct ieee80211_hw *hw, 2878 2858 struct ieee80211_vif *vif, 2879 2859 struct cfg80211_chan_def *chandef); 2860 + 2861 + int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 2862 + void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 2880 2863 }; 2881 2864 2882 2865 /** ··· 3941 3918 u8 *mac, 3942 3919 struct ieee80211_vif *vif), 3943 3920 void *data); 3921 + 3922 + /** 3923 + * ieee80211_iterate_active_interfaces_rtnl - iterate active interfaces 3924 + * 3925 + * This function iterates over the interfaces associated with a given 3926 + * hardware that are currently active and calls the callback for them. 3927 + * This version can only be used while holding the RTNL. 3928 + * 3929 + * @hw: the hardware struct of which the interfaces should be iterated over 3930 + * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags 3931 + * @iterator: the iterator function to call, cannot sleep 3932 + * @data: first argument of the iterator function 3933 + */ 3934 + void ieee80211_iterate_active_interfaces_rtnl(struct ieee80211_hw *hw, 3935 + u32 iter_flags, 3936 + void (*iterator)(void *data, 3937 + u8 *mac, 3938 + struct ieee80211_vif *vif), 3939 + void *data); 3944 3940 3945 3941 /** 3946 3942 * ieee80211_queue_work - add work onto the mac80211 workqueue
+69 -23
net/mac80211/cfg.c
··· 2865 2865 if (!ieee80211_sdata_running(sdata)) 2866 2866 return; 2867 2867 2868 - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP)) 2869 - return; 2870 - 2871 2868 sdata->radar_required = sdata->csa_radar_required; 2872 2869 err = ieee80211_vif_change_channel(sdata, &local->csa_chandef, 2873 2870 &changed); 2874 2871 if (WARN_ON(err < 0)) 2875 2872 return; 2876 2873 2877 - err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); 2878 - if (err < 0) 2879 - return; 2874 + if (!local->use_chanctx) { 2875 + local->_oper_chandef = local->csa_chandef; 2876 + ieee80211_hw_config(local, 0); 2877 + } 2880 2878 2881 - changed |= err; 2882 - kfree(sdata->u.ap.next_beacon); 2883 - sdata->u.ap.next_beacon = NULL; 2879 + ieee80211_bss_info_change_notify(sdata, changed); 2880 + 2881 + switch (sdata->vif.type) { 2882 + case NL80211_IFTYPE_AP: 2883 + err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); 2884 + if (err < 0) 2885 + return; 2886 + changed |= err; 2887 + kfree(sdata->u.ap.next_beacon); 2888 + sdata->u.ap.next_beacon = NULL; 2889 + 2890 + ieee80211_bss_info_change_notify(sdata, err); 2891 + break; 2892 + case NL80211_IFTYPE_ADHOC: 2893 + ieee80211_ibss_finish_csa(sdata); 2894 + break; 2895 + default: 2896 + WARN_ON(1); 2897 + return; 2898 + } 2884 2899 sdata->vif.csa_active = false; 2885 2900 2886 2901 ieee80211_wake_queues_by_reason(&sdata->local->hw, 2887 2902 IEEE80211_MAX_QUEUE_MAP, 2888 2903 IEEE80211_QUEUE_STOP_REASON_CSA); 2889 - 2890 - ieee80211_bss_info_change_notify(sdata, changed); 2891 2904 2892 2905 cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef); 2893 2906 } ··· 2949 2936 if (sdata->vif.csa_active) 2950 2937 return -EBUSY; 2951 2938 2952 - /* only handle AP for now. */ 2953 2939 switch (sdata->vif.type) { 2954 2940 case NL80211_IFTYPE_AP: 2941 + sdata->csa_counter_offset_beacon = 2942 + params->counter_offset_beacon; 2943 + sdata->csa_counter_offset_presp = params->counter_offset_presp; 2944 + sdata->u.ap.next_beacon = 2945 + cfg80211_beacon_dup(&params->beacon_after); 2946 + if (!sdata->u.ap.next_beacon) 2947 + return -ENOMEM; 2948 + 2949 + err = ieee80211_assign_beacon(sdata, &params->beacon_csa); 2950 + if (err < 0) { 2951 + kfree(sdata->u.ap.next_beacon); 2952 + return err; 2953 + } 2954 + break; 2955 + case NL80211_IFTYPE_ADHOC: 2956 + if (!sdata->vif.bss_conf.ibss_joined) 2957 + return -EINVAL; 2958 + 2959 + if (params->chandef.width != sdata->u.ibss.chandef.width) 2960 + return -EINVAL; 2961 + 2962 + switch (params->chandef.width) { 2963 + case NL80211_CHAN_WIDTH_40: 2964 + if (cfg80211_get_chandef_type(&params->chandef) != 2965 + cfg80211_get_chandef_type(&sdata->u.ibss.chandef)) 2966 + return -EINVAL; 2967 + case NL80211_CHAN_WIDTH_5: 2968 + case NL80211_CHAN_WIDTH_10: 2969 + case NL80211_CHAN_WIDTH_20_NOHT: 2970 + case NL80211_CHAN_WIDTH_20: 2971 + break; 2972 + default: 2973 + return -EINVAL; 2974 + } 2975 + 2976 + /* changes into another band are not supported */ 2977 + if (sdata->u.ibss.chandef.chan->band != 2978 + params->chandef.chan->band) 2979 + return -EINVAL; 2980 + 2981 + err = ieee80211_ibss_csa_beacon(sdata, params); 2982 + if (err < 0) 2983 + return err; 2955 2984 break; 2956 2985 default: 2957 2986 return -EOPNOTSUPP; 2958 2987 } 2959 2988 2960 - sdata->u.ap.next_beacon = cfg80211_beacon_dup(&params->beacon_after); 2961 - if (!sdata->u.ap.next_beacon) 2962 - return -ENOMEM; 2963 - 2964 - sdata->csa_counter_offset_beacon = params->counter_offset_beacon; 2965 - sdata->csa_counter_offset_presp = params->counter_offset_presp; 2966 2989 sdata->csa_radar_required = params->radar_required; 2967 2990 2968 2991 if (params->block_tx) 2969 2992 ieee80211_stop_queues_by_reason(&local->hw, 2970 2993 IEEE80211_MAX_QUEUE_MAP, 2971 2994 IEEE80211_QUEUE_STOP_REASON_CSA); 2972 - 2973 - err = ieee80211_assign_beacon(sdata, &params->beacon_csa); 2974 - if (err < 0) 2975 - return err; 2976 2995 2977 2996 local->csa_chandef = params->chandef; 2978 2997 sdata->vif.csa_active = true; ··· 3059 3014 need_offchan = true; 3060 3015 if (!ieee80211_is_action(mgmt->frame_control) || 3061 3016 mgmt->u.action.category == WLAN_CATEGORY_PUBLIC || 3062 - mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED) 3017 + mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED || 3018 + mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) 3063 3019 break; 3064 3020 rcu_read_lock(); 3065 3021 sta = sta_info_get(sdata, mgmt->da);
-5
net/mac80211/chan.c
··· 453 453 chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL; 454 454 drv_change_chanctx(local, ctx, chanctx_changed); 455 455 456 - if (!local->use_chanctx) { 457 - local->_oper_chandef = *chandef; 458 - ieee80211_hw_config(local, 0); 459 - } 460 - 461 456 ieee80211_recalc_chanctx_chantype(local, ctx); 462 457 ieee80211_recalc_smps_chanctx(local, ctx); 463 458 ieee80211_recalc_radar_chanctx(local, ctx);
+29 -26
net/mac80211/debugfs.c
··· 103 103 if (!buf) 104 104 return 0; 105 105 106 - sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); 106 + sf += scnprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); 107 107 if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) 108 - sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); 108 + sf += scnprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); 109 109 if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) 110 - sf += snprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n"); 110 + sf += scnprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n"); 111 111 if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) 112 - sf += snprintf(buf + sf, mxln - sf, 113 - "HOST_BCAST_PS_BUFFERING\n"); 112 + sf += scnprintf(buf + sf, mxln - sf, 113 + "HOST_BCAST_PS_BUFFERING\n"); 114 114 if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE) 115 - sf += snprintf(buf + sf, mxln - sf, 116 - "2GHZ_SHORT_SLOT_INCAPABLE\n"); 115 + sf += scnprintf(buf + sf, mxln - sf, 116 + "2GHZ_SHORT_SLOT_INCAPABLE\n"); 117 117 if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE) 118 - sf += snprintf(buf + sf, mxln - sf, 119 - "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); 118 + sf += scnprintf(buf + sf, mxln - sf, 119 + "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); 120 120 if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) 121 - sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); 121 + sf += scnprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); 122 122 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 123 - sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); 123 + sf += scnprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); 124 124 if (local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC) 125 - sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_BEFORE_ASSOC\n"); 125 + sf += scnprintf(buf + sf, mxln - sf, 126 + "NEED_DTIM_BEFORE_ASSOC\n"); 126 127 if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) 127 - sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); 128 + sf += scnprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); 128 129 if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) 129 - sf += snprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n"); 130 + sf += scnprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n"); 130 131 if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS) 131 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n"); 132 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n"); 132 133 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) 133 - sf += snprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n"); 134 + sf += scnprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n"); 134 135 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) 135 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); 136 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); 136 137 if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) 137 - sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); 138 + sf += scnprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); 138 139 if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) 139 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); 140 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); 140 141 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) 141 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_SMPS\n"); 142 + sf += scnprintf(buf + sf, mxln - sf, 143 + "SUPPORTS_DYNAMIC_SMPS\n"); 142 144 if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) 143 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); 145 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); 144 146 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) 145 - sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n"); 147 + sf += scnprintf(buf + sf, mxln - sf, 148 + "REPORTS_TX_ACK_STATUS\n"); 146 149 if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) 147 - sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); 150 + sf += scnprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); 148 151 if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) 149 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); 152 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); 150 153 if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) 151 - sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); 154 + sf += scnprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); 152 155 if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) 153 - sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); 156 + sf += scnprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); 154 157 155 158 rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); 156 159 kfree(buf);
+27
net/mac80211/driver-ops.h
··· 1085 1085 } 1086 1086 } 1087 1087 1088 + static inline int drv_join_ibss(struct ieee80211_local *local, 1089 + struct ieee80211_sub_if_data *sdata) 1090 + { 1091 + int ret = 0; 1092 + 1093 + might_sleep(); 1094 + check_sdata_in_driver(sdata); 1095 + 1096 + trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); 1097 + if (local->ops->join_ibss) 1098 + ret = local->ops->join_ibss(&local->hw, &sdata->vif); 1099 + trace_drv_return_int(local, ret); 1100 + return ret; 1101 + } 1102 + 1103 + static inline void drv_leave_ibss(struct ieee80211_local *local, 1104 + struct ieee80211_sub_if_data *sdata) 1105 + { 1106 + might_sleep(); 1107 + check_sdata_in_driver(sdata); 1108 + 1109 + trace_drv_leave_ibss(local, sdata); 1110 + if (local->ops->leave_ibss) 1111 + local->ops->leave_ibss(&local->hw, &sdata->vif); 1112 + trace_drv_return_void(local); 1113 + } 1114 + 1088 1115 #endif /* __MAC80211_DRIVER_OPS */
+520 -88
net/mac80211/ibss.c
··· 39 39 const int beacon_int, const u32 basic_rates, 40 40 const u16 capability, u64 tsf, 41 41 struct cfg80211_chan_def *chandef, 42 - bool *have_higher_than_11mbit) 42 + bool *have_higher_than_11mbit, 43 + struct cfg80211_csa_settings *csa_settings) 43 44 { 44 45 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 45 46 struct ieee80211_local *local = sdata->local; ··· 60 59 2 + 8 /* max Supported Rates */ + 61 60 3 /* max DS params */ + 62 61 4 /* IBSS params */ + 62 + 5 /* Channel Switch Announcement */ + 63 63 2 + (IEEE80211_MAX_SUPP_RATES - 8) + 64 64 2 + sizeof(struct ieee80211_ht_cap) + 65 65 2 + sizeof(struct ieee80211_ht_operation) + ··· 136 134 /* FIX: set ATIM window based on scan results */ 137 135 *pos++ = 0; 138 136 *pos++ = 0; 137 + 138 + if (csa_settings) { 139 + *pos++ = WLAN_EID_CHANNEL_SWITCH; 140 + *pos++ = 3; 141 + *pos++ = csa_settings->block_tx ? 1 : 0; 142 + *pos++ = ieee80211_frequency_to_channel( 143 + csa_settings->chandef.chan->center_freq); 144 + sdata->csa_counter_offset_beacon = (pos - presp->head); 145 + *pos++ = csa_settings->count; 146 + } 139 147 140 148 /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */ 141 149 if (rates_n > 8) { ··· 229 217 struct beacon_data *presp; 230 218 enum nl80211_bss_scan_width scan_width; 231 219 bool have_higher_than_11mbit; 220 + int err; 232 221 233 222 sdata_assert_lock(sdata); 234 223 ··· 248 235 ieee80211_bss_info_change_notify(sdata, 249 236 BSS_CHANGED_IBSS | 250 237 BSS_CHANGED_BEACON_ENABLED); 238 + drv_leave_ibss(local, sdata); 251 239 } 252 240 253 241 presp = rcu_dereference_protected(ifibss->presp, ··· 290 276 291 277 presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, 292 278 capability, tsf, &chandef, 293 - &have_higher_than_11mbit); 279 + &have_higher_than_11mbit, NULL); 294 280 if (!presp) 295 281 return; 296 282 ··· 331 317 else 332 318 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; 333 319 320 + ieee80211_set_wmm_default(sdata, true); 321 + 334 322 sdata->vif.bss_conf.ibss_joined = true; 335 323 sdata->vif.bss_conf.ibss_creator = creator; 336 - ieee80211_bss_info_change_notify(sdata, bss_change); 337 324 338 - ieee80211_set_wmm_default(sdata, true); 325 + err = drv_join_ibss(local, sdata); 326 + if (err) { 327 + sdata->vif.bss_conf.ibss_joined = false; 328 + sdata->vif.bss_conf.ibss_creator = false; 329 + sdata->vif.bss_conf.enable_beacon = false; 330 + sdata->vif.bss_conf.ssid_len = 0; 331 + RCU_INIT_POINTER(ifibss->presp, NULL); 332 + kfree_rcu(presp, rcu_head); 333 + ieee80211_vif_release_channel(sdata); 334 + sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n", 335 + err); 336 + return; 337 + } 338 + 339 + ieee80211_bss_info_change_notify(sdata, bss_change); 339 340 340 341 ifibss->state = IEEE80211_IBSS_MLME_JOINED; 341 342 mod_timer(&ifibss->timer, ··· 445 416 tsf, false); 446 417 } 447 418 419 + static int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, 420 + struct cfg80211_csa_settings *csa_settings) 421 + { 422 + struct sk_buff *skb; 423 + struct ieee80211_mgmt *mgmt; 424 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 425 + struct ieee80211_local *local = sdata->local; 426 + int freq; 427 + int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) + 428 + sizeof(mgmt->u.action.u.chan_switch); 429 + u8 *pos; 430 + 431 + skb = dev_alloc_skb(local->tx_headroom + hdr_len + 432 + 5 + /* channel switch announcement element */ 433 + 3); /* secondary channel offset element */ 434 + if (!skb) 435 + return -1; 436 + 437 + skb_reserve(skb, local->tx_headroom); 438 + mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len); 439 + memset(mgmt, 0, hdr_len); 440 + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 441 + IEEE80211_STYPE_ACTION); 442 + 443 + eth_broadcast_addr(mgmt->da); 444 + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 445 + memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); 446 + mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; 447 + mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH; 448 + pos = skb_put(skb, 5); 449 + *pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */ 450 + *pos++ = 3; /* IE length */ 451 + *pos++ = csa_settings->block_tx ? 1 : 0; /* CSA mode */ 452 + freq = csa_settings->chandef.chan->center_freq; 453 + *pos++ = ieee80211_frequency_to_channel(freq); /* channel */ 454 + *pos++ = csa_settings->count; /* count */ 455 + 456 + if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) { 457 + enum nl80211_channel_type ch_type; 458 + 459 + skb_put(skb, 3); 460 + *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */ 461 + *pos++ = 1; /* IE length */ 462 + ch_type = cfg80211_get_chandef_type(&csa_settings->chandef); 463 + if (ch_type == NL80211_CHAN_HT40PLUS) 464 + *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; 465 + else 466 + *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW; 467 + } 468 + 469 + ieee80211_tx_skb(sdata, skb); 470 + return 0; 471 + } 472 + 473 + int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, 474 + struct cfg80211_csa_settings *csa_settings) 475 + { 476 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 477 + struct beacon_data *presp, *old_presp; 478 + struct cfg80211_bss *cbss; 479 + const struct cfg80211_bss_ies *ies; 480 + u16 capability; 481 + u64 tsf; 482 + int ret = 0; 483 + 484 + sdata_assert_lock(sdata); 485 + 486 + capability = WLAN_CAPABILITY_IBSS; 487 + 488 + if (ifibss->privacy) 489 + capability |= WLAN_CAPABILITY_PRIVACY; 490 + 491 + cbss = cfg80211_get_bss(sdata->local->hw.wiphy, ifibss->chandef.chan, 492 + ifibss->bssid, ifibss->ssid, 493 + ifibss->ssid_len, WLAN_CAPABILITY_IBSS | 494 + WLAN_CAPABILITY_PRIVACY, 495 + capability); 496 + 497 + if (WARN_ON(!cbss)) { 498 + ret = -EINVAL; 499 + goto out; 500 + } 501 + 502 + rcu_read_lock(); 503 + ies = rcu_dereference(cbss->ies); 504 + tsf = ies->tsf; 505 + rcu_read_unlock(); 506 + cfg80211_put_bss(sdata->local->hw.wiphy, cbss); 507 + 508 + old_presp = rcu_dereference_protected(ifibss->presp, 509 + lockdep_is_held(&sdata->wdev.mtx)); 510 + 511 + presp = ieee80211_ibss_build_presp(sdata, 512 + sdata->vif.bss_conf.beacon_int, 513 + sdata->vif.bss_conf.basic_rates, 514 + capability, tsf, &ifibss->chandef, 515 + NULL, csa_settings); 516 + if (!presp) { 517 + ret = -ENOMEM; 518 + goto out; 519 + } 520 + 521 + rcu_assign_pointer(ifibss->presp, presp); 522 + if (old_presp) 523 + kfree_rcu(old_presp, rcu_head); 524 + 525 + /* it might not send the beacon for a while. send an action frame 526 + * immediately to announce the channel switch. 527 + */ 528 + if (csa_settings) 529 + ieee80211_send_action_csa(sdata, csa_settings); 530 + 531 + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); 532 + out: 533 + return ret; 534 + } 535 + 536 + int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) 537 + { 538 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 539 + struct cfg80211_bss *cbss; 540 + int err; 541 + u16 capability; 542 + 543 + sdata_lock(sdata); 544 + /* update cfg80211 bss information with the new channel */ 545 + if (!is_zero_ether_addr(ifibss->bssid)) { 546 + capability = WLAN_CAPABILITY_IBSS; 547 + 548 + if (ifibss->privacy) 549 + capability |= WLAN_CAPABILITY_PRIVACY; 550 + 551 + cbss = cfg80211_get_bss(sdata->local->hw.wiphy, 552 + ifibss->chandef.chan, 553 + ifibss->bssid, ifibss->ssid, 554 + ifibss->ssid_len, WLAN_CAPABILITY_IBSS | 555 + WLAN_CAPABILITY_PRIVACY, 556 + capability); 557 + /* XXX: should not really modify cfg80211 data */ 558 + if (cbss) { 559 + cbss->channel = sdata->local->csa_chandef.chan; 560 + cfg80211_put_bss(sdata->local->hw.wiphy, cbss); 561 + } 562 + } 563 + 564 + ifibss->chandef = sdata->local->csa_chandef; 565 + 566 + /* generate the beacon */ 567 + err = ieee80211_ibss_csa_beacon(sdata, NULL); 568 + sdata_unlock(sdata); 569 + if (err < 0) 570 + return err; 571 + 572 + return 0; 573 + } 574 + 575 + void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) 576 + { 577 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 578 + 579 + cancel_work_sync(&ifibss->csa_connection_drop_work); 580 + } 581 + 448 582 static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) 449 583 __acquires(RCU) 450 584 { ··· 689 497 ieee80211_mandatory_rates(sband, scan_width); 690 498 691 499 return ieee80211_ibss_finish_sta(sta); 500 + } 501 + 502 + static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) 503 + { 504 + struct ieee80211_local *local = sdata->local; 505 + int active = 0; 506 + struct sta_info *sta; 507 + 508 + sdata_assert_lock(sdata); 509 + 510 + rcu_read_lock(); 511 + 512 + list_for_each_entry_rcu(sta, &local->sta_list, list) { 513 + if (sta->sdata == sdata && 514 + time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, 515 + jiffies)) { 516 + active++; 517 + break; 518 + } 519 + } 520 + 521 + rcu_read_unlock(); 522 + 523 + return active; 524 + } 525 + 526 + static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) 527 + { 528 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 529 + struct ieee80211_local *local = sdata->local; 530 + struct cfg80211_bss *cbss; 531 + struct beacon_data *presp; 532 + struct sta_info *sta; 533 + int active_ibss; 534 + u16 capability; 535 + 536 + active_ibss = ieee80211_sta_active_ibss(sdata); 537 + 538 + if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { 539 + capability = WLAN_CAPABILITY_IBSS; 540 + 541 + if (ifibss->privacy) 542 + capability |= WLAN_CAPABILITY_PRIVACY; 543 + 544 + cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan, 545 + ifibss->bssid, ifibss->ssid, 546 + ifibss->ssid_len, WLAN_CAPABILITY_IBSS | 547 + WLAN_CAPABILITY_PRIVACY, 548 + capability); 549 + 550 + if (cbss) { 551 + cfg80211_unlink_bss(local->hw.wiphy, cbss); 552 + cfg80211_put_bss(sdata->local->hw.wiphy, cbss); 553 + } 554 + } 555 + 556 + ifibss->state = IEEE80211_IBSS_MLME_SEARCH; 557 + 558 + sta_info_flush(sdata); 559 + 560 + spin_lock_bh(&ifibss->incomplete_lock); 561 + while (!list_empty(&ifibss->incomplete_stations)) { 562 + sta = list_first_entry(&ifibss->incomplete_stations, 563 + struct sta_info, list); 564 + list_del(&sta->list); 565 + spin_unlock_bh(&ifibss->incomplete_lock); 566 + 567 + sta_info_free(local, sta); 568 + spin_lock_bh(&ifibss->incomplete_lock); 569 + } 570 + spin_unlock_bh(&ifibss->incomplete_lock); 571 + 572 + netif_carrier_off(sdata->dev); 573 + 574 + sdata->vif.bss_conf.ibss_joined = false; 575 + sdata->vif.bss_conf.ibss_creator = false; 576 + sdata->vif.bss_conf.enable_beacon = false; 577 + sdata->vif.bss_conf.ssid_len = 0; 578 + 579 + /* remove beacon */ 580 + presp = rcu_dereference_protected(ifibss->presp, 581 + lockdep_is_held(&sdata->wdev.mtx)); 582 + RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); 583 + if (presp) 584 + kfree_rcu(presp, rcu_head); 585 + 586 + clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 587 + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | 588 + BSS_CHANGED_IBSS); 589 + drv_leave_ibss(local, sdata); 590 + ieee80211_vif_release_channel(sdata); 591 + } 592 + 593 + static void ieee80211_csa_connection_drop_work(struct work_struct *work) 594 + { 595 + struct ieee80211_sub_if_data *sdata = 596 + container_of(work, struct ieee80211_sub_if_data, 597 + u.ibss.csa_connection_drop_work); 598 + 599 + ieee80211_ibss_disconnect(sdata); 600 + synchronize_rcu(); 601 + skb_queue_purge(&sdata->skb_queue); 602 + 603 + /* trigger a scan to find another IBSS network to join */ 604 + ieee80211_queue_work(&sdata->local->hw, &sdata->work); 605 + } 606 + 607 + static bool 608 + ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, 609 + struct ieee802_11_elems *elems, 610 + bool beacon) 611 + { 612 + struct cfg80211_csa_settings params; 613 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 614 + struct ieee80211_chanctx_conf *chanctx_conf; 615 + struct ieee80211_chanctx *chanctx; 616 + enum nl80211_channel_type ch_type; 617 + int err, num_chanctx; 618 + u32 sta_flags; 619 + u8 mode; 620 + 621 + if (sdata->vif.csa_active) 622 + return true; 623 + 624 + if (!sdata->vif.bss_conf.ibss_joined) 625 + return false; 626 + 627 + sta_flags = IEEE80211_STA_DISABLE_VHT; 628 + switch (ifibss->chandef.width) { 629 + case NL80211_CHAN_WIDTH_5: 630 + case NL80211_CHAN_WIDTH_10: 631 + case NL80211_CHAN_WIDTH_20_NOHT: 632 + sta_flags |= IEEE80211_STA_DISABLE_HT; 633 + /* fall through */ 634 + case NL80211_CHAN_WIDTH_20: 635 + sta_flags |= IEEE80211_STA_DISABLE_40MHZ; 636 + break; 637 + default: 638 + break; 639 + } 640 + 641 + memset(&params, 0, sizeof(params)); 642 + err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, 643 + ifibss->chandef.chan->band, 644 + sta_flags, ifibss->bssid, 645 + &params.count, &mode, 646 + &params.chandef); 647 + 648 + /* can't switch to destination channel, fail */ 649 + if (err < 0) 650 + goto disconnect; 651 + 652 + /* did not contain a CSA */ 653 + if (err) 654 + return false; 655 + 656 + if (ifibss->chandef.chan->band != params.chandef.chan->band) 657 + goto disconnect; 658 + 659 + switch (ifibss->chandef.width) { 660 + case NL80211_CHAN_WIDTH_20_NOHT: 661 + case NL80211_CHAN_WIDTH_20: 662 + case NL80211_CHAN_WIDTH_40: 663 + /* keep our current HT mode (HT20/HT40+/HT40-), even if 664 + * another mode has been announced. The mode is not adopted 665 + * within the beacon while doing CSA and we should therefore 666 + * keep the mode which we announce. 667 + */ 668 + ch_type = cfg80211_get_chandef_type(&ifibss->chandef); 669 + cfg80211_chandef_create(&params.chandef, params.chandef.chan, 670 + ch_type); 671 + break; 672 + case NL80211_CHAN_WIDTH_5: 673 + case NL80211_CHAN_WIDTH_10: 674 + if (params.chandef.width != ifibss->chandef.width) { 675 + sdata_info(sdata, 676 + "IBSS %pM received channel switch from incompatible channel width (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", 677 + ifibss->bssid, 678 + params.chandef.chan->center_freq, 679 + params.chandef.width, 680 + params.chandef.center_freq1, 681 + params.chandef.center_freq2); 682 + goto disconnect; 683 + } 684 + break; 685 + default: 686 + /* should not happen, sta_flags should prevent VHT modes. */ 687 + WARN_ON(1); 688 + goto disconnect; 689 + } 690 + 691 + if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, &params.chandef, 692 + IEEE80211_CHAN_DISABLED)) { 693 + sdata_info(sdata, 694 + "IBSS %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", 695 + ifibss->bssid, 696 + params.chandef.chan->center_freq, 697 + params.chandef.width, 698 + params.chandef.center_freq1, 699 + params.chandef.center_freq2); 700 + goto disconnect; 701 + } 702 + 703 + err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, 704 + &params.chandef); 705 + if (err < 0) 706 + goto disconnect; 707 + if (err) { 708 + params.radar_required = true; 709 + 710 + /* TODO: IBSS-DFS not (yet) supported, disconnect. */ 711 + goto disconnect; 712 + } 713 + 714 + rcu_read_lock(); 715 + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 716 + if (!chanctx_conf) { 717 + rcu_read_unlock(); 718 + goto disconnect; 719 + } 720 + 721 + /* don't handle for multi-VIF cases */ 722 + chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); 723 + if (chanctx->refcount > 1) { 724 + rcu_read_unlock(); 725 + goto disconnect; 726 + } 727 + num_chanctx = 0; 728 + list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list) 729 + num_chanctx++; 730 + 731 + if (num_chanctx > 1) { 732 + rcu_read_unlock(); 733 + goto disconnect; 734 + } 735 + rcu_read_unlock(); 736 + 737 + /* all checks done, now perform the channel switch. */ 738 + ibss_dbg(sdata, 739 + "received channel switch announcement to go to channel %d MHz\n", 740 + params.chandef.chan->center_freq); 741 + 742 + params.block_tx = !!mode; 743 + 744 + ieee80211_ibss_csa_beacon(sdata, &params); 745 + sdata->csa_radar_required = params.radar_required; 746 + 747 + if (params.block_tx) 748 + ieee80211_stop_queues_by_reason(&sdata->local->hw, 749 + IEEE80211_MAX_QUEUE_MAP, 750 + IEEE80211_QUEUE_STOP_REASON_CSA); 751 + 752 + sdata->local->csa_chandef = params.chandef; 753 + sdata->vif.csa_active = true; 754 + 755 + ieee80211_bss_info_change_notify(sdata, err); 756 + drv_channel_switch_beacon(sdata, &params.chandef); 757 + 758 + return true; 759 + disconnect: 760 + ibss_dbg(sdata, "Can't handle channel switch, disconnect\n"); 761 + ieee80211_queue_work(&sdata->local->hw, 762 + &ifibss->csa_connection_drop_work); 763 + 764 + return true; 765 + } 766 + 767 + static void 768 + ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata, 769 + struct ieee80211_mgmt *mgmt, size_t len, 770 + struct ieee80211_rx_status *rx_status, 771 + struct ieee802_11_elems *elems) 772 + { 773 + int required_len; 774 + 775 + if (len < IEEE80211_MIN_ACTION_SIZE + 1) 776 + return; 777 + 778 + /* CSA is the only action we handle for now */ 779 + if (mgmt->u.action.u.measurement.action_code != 780 + WLAN_ACTION_SPCT_CHL_SWITCH) 781 + return; 782 + 783 + required_len = IEEE80211_MIN_ACTION_SIZE + 784 + sizeof(mgmt->u.action.u.chan_switch); 785 + if (len < required_len) 786 + return; 787 + 788 + ieee80211_ibss_process_chanswitch(sdata, elems, false); 692 789 } 693 790 694 791 static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, ··· 1142 661 1143 662 /* check if we need to merge IBSS */ 1144 663 1145 - /* we use a fixed BSSID */ 1146 - if (sdata->u.ibss.fixed_bssid) 1147 - goto put_bss; 1148 - 1149 664 /* not an IBSS */ 1150 665 if (!(cbss->capability & WLAN_CAPABILITY_IBSS)) 1151 666 goto put_bss; ··· 1157 680 sdata->u.ibss.ssid_len)) 1158 681 goto put_bss; 1159 682 683 + /* process channel switch */ 684 + if (ieee80211_ibss_process_chanswitch(sdata, elems, true)) 685 + goto put_bss; 686 + 1160 687 /* same BSSID */ 1161 688 if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid)) 689 + goto put_bss; 690 + 691 + /* we use a fixed BSSID */ 692 + if (sdata->u.ibss.fixed_bssid) 1162 693 goto put_bss; 1163 694 1164 695 if (ieee80211_have_rx_timestamp(rx_status)) { ··· 1258 773 list_add(&sta->list, &ifibss->incomplete_stations); 1259 774 spin_unlock(&ifibss->incomplete_lock); 1260 775 ieee80211_queue_work(&local->hw, &sdata->work); 1261 - } 1262 - 1263 - static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) 1264 - { 1265 - struct ieee80211_local *local = sdata->local; 1266 - int active = 0; 1267 - struct sta_info *sta; 1268 - 1269 - sdata_assert_lock(sdata); 1270 - 1271 - rcu_read_lock(); 1272 - 1273 - list_for_each_entry_rcu(sta, &local->sta_list, list) { 1274 - if (sta->sdata == sdata && 1275 - time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, 1276 - jiffies)) { 1277 - active++; 1278 - break; 1279 - } 1280 - } 1281 - 1282 - rcu_read_unlock(); 1283 - 1284 - return active; 1285 776 } 1286 777 1287 778 static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata) ··· 1537 1076 struct ieee80211_rx_status *rx_status; 1538 1077 struct ieee80211_mgmt *mgmt; 1539 1078 u16 fc; 1079 + struct ieee802_11_elems elems; 1080 + int ies_len; 1540 1081 1541 1082 rx_status = IEEE80211_SKB_RXCB(skb); 1542 1083 mgmt = (struct ieee80211_mgmt *) skb->data; ··· 1564 1101 case IEEE80211_STYPE_DEAUTH: 1565 1102 ieee80211_rx_mgmt_deauth_ibss(sdata, mgmt, skb->len); 1566 1103 break; 1104 + case IEEE80211_STYPE_ACTION: 1105 + switch (mgmt->u.action.category) { 1106 + case WLAN_CATEGORY_SPECTRUM_MGMT: 1107 + ies_len = skb->len - 1108 + offsetof(struct ieee80211_mgmt, 1109 + u.action.u.chan_switch.variable); 1110 + 1111 + if (ies_len < 0) 1112 + break; 1113 + 1114 + ieee802_11_parse_elems( 1115 + mgmt->u.action.u.chan_switch.variable, 1116 + ies_len, true, &elems); 1117 + 1118 + if (elems.parse_error) 1119 + break; 1120 + 1121 + ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, skb->len, 1122 + rx_status, &elems); 1123 + break; 1124 + } 1567 1125 } 1568 1126 1569 1127 mgmt_out: ··· 1651 1167 (unsigned long) sdata); 1652 1168 INIT_LIST_HEAD(&ifibss->incomplete_stations); 1653 1169 spin_lock_init(&ifibss->incomplete_lock); 1170 + INIT_WORK(&ifibss->csa_connection_drop_work, 1171 + ieee80211_csa_connection_drop_work); 1654 1172 } 1655 1173 1656 1174 /* scan finished notification */ ··· 1751 1265 int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) 1752 1266 { 1753 1267 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 1754 - struct ieee80211_local *local = sdata->local; 1755 - struct cfg80211_bss *cbss; 1756 - u16 capability; 1757 - int active_ibss; 1758 - struct sta_info *sta; 1759 - struct beacon_data *presp; 1760 1268 1761 - active_ibss = ieee80211_sta_active_ibss(sdata); 1762 - 1763 - if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { 1764 - capability = WLAN_CAPABILITY_IBSS; 1765 - 1766 - if (ifibss->privacy) 1767 - capability |= WLAN_CAPABILITY_PRIVACY; 1768 - 1769 - cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan, 1770 - ifibss->bssid, ifibss->ssid, 1771 - ifibss->ssid_len, WLAN_CAPABILITY_IBSS | 1772 - WLAN_CAPABILITY_PRIVACY, 1773 - capability); 1774 - 1775 - if (cbss) { 1776 - cfg80211_unlink_bss(local->hw.wiphy, cbss); 1777 - cfg80211_put_bss(local->hw.wiphy, cbss); 1778 - } 1779 - } 1780 - 1781 - ifibss->state = IEEE80211_IBSS_MLME_SEARCH; 1782 - memset(ifibss->bssid, 0, ETH_ALEN); 1269 + ieee80211_ibss_disconnect(sdata); 1783 1270 ifibss->ssid_len = 0; 1784 - 1785 - sta_info_flush(sdata); 1786 - 1787 - spin_lock_bh(&ifibss->incomplete_lock); 1788 - while (!list_empty(&ifibss->incomplete_stations)) { 1789 - sta = list_first_entry(&ifibss->incomplete_stations, 1790 - struct sta_info, list); 1791 - list_del(&sta->list); 1792 - spin_unlock_bh(&ifibss->incomplete_lock); 1793 - 1794 - sta_info_free(local, sta); 1795 - spin_lock_bh(&ifibss->incomplete_lock); 1796 - } 1797 - spin_unlock_bh(&ifibss->incomplete_lock); 1798 - 1799 - netif_carrier_off(sdata->dev); 1271 + memset(ifibss->bssid, 0, ETH_ALEN); 1800 1272 1801 1273 /* remove beacon */ 1802 1274 kfree(sdata->u.ibss.ie); 1803 - presp = rcu_dereference_protected(ifibss->presp, 1804 - lockdep_is_held(&sdata->wdev.mtx)); 1805 - RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); 1806 1275 1807 1276 /* on the next join, re-program HT parameters */ 1808 1277 memset(&ifibss->ht_capa, 0, sizeof(ifibss->ht_capa)); 1809 1278 memset(&ifibss->ht_capa_mask, 0, sizeof(ifibss->ht_capa_mask)); 1810 1279 1811 - sdata->vif.bss_conf.ibss_joined = false; 1812 - sdata->vif.bss_conf.ibss_creator = false; 1813 - sdata->vif.bss_conf.enable_beacon = false; 1814 - sdata->vif.bss_conf.ssid_len = 0; 1815 - clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 1816 - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | 1817 - BSS_CHANGED_IBSS); 1818 - ieee80211_vif_release_channel(sdata); 1819 1280 synchronize_rcu(); 1820 - kfree(presp); 1821 1281 1822 1282 skb_queue_purge(&sdata->skb_queue); 1823 1283
+29 -1
net/mac80211/ieee80211_i.h
··· 322 322 323 323 /* flags used in struct ieee80211_if_managed.flags */ 324 324 enum ieee80211_sta_flags { 325 - IEEE80211_STA_BEACON_POLL = BIT(0), 326 325 IEEE80211_STA_CONNECTION_POLL = BIT(1), 327 326 IEEE80211_STA_CONTROL_PORT = BIT(2), 328 327 IEEE80211_STA_DISABLE_HT = BIT(4), ··· 486 487 487 488 struct ieee80211_if_ibss { 488 489 struct timer_list timer; 490 + struct work_struct csa_connection_drop_work; 489 491 490 492 unsigned long last_scan_completed; 491 493 ··· 1330 1330 void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); 1331 1331 void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, 1332 1332 struct sk_buff *skb); 1333 + int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, 1334 + struct cfg80211_csa_settings *csa_settings); 1335 + int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata); 1336 + void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata); 1333 1337 1334 1338 /* mesh code */ 1335 1339 void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); ··· 1485 1481 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, 1486 1482 struct ieee80211_mgmt *mgmt, 1487 1483 size_t len); 1484 + /** 1485 + * ieee80211_parse_ch_switch_ie - parses channel switch IEs 1486 + * @sdata: the sdata of the interface which has received the frame 1487 + * @elems: parsed 802.11 elements received with the frame 1488 + * @beacon: indicates if the frame was a beacon or probe response 1489 + * @current_band: indicates the current band 1490 + * @sta_flags: contains information about own capabilities and restrictions 1491 + * to decide which channel switch announcements can be accepted. Only the 1492 + * following subset of &enum ieee80211_sta_flags are evaluated: 1493 + * %IEEE80211_STA_DISABLE_HT, %IEEE80211_STA_DISABLE_VHT, 1494 + * %IEEE80211_STA_DISABLE_40MHZ, %IEEE80211_STA_DISABLE_80P80MHZ, 1495 + * %IEEE80211_STA_DISABLE_160MHZ. 1496 + * @count: to be filled with the counter until the switch (on success only) 1497 + * @bssid: the currently connected bssid (for reporting) 1498 + * @mode: to be filled with CSA mode (on success only) 1499 + * @new_chandef: to be filled with destination chandef (on success only) 1500 + * Return: 0 on success, <0 on error and >0 if there is nothing to parse. 1501 + */ 1502 + int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, 1503 + struct ieee802_11_elems *elems, bool beacon, 1504 + enum ieee80211_band current_band, 1505 + u32 sta_flags, u8 *bssid, u8 *count, u8 *mode, 1506 + struct cfg80211_chan_def *new_chandef); 1488 1507 1489 1508 /* Suspend/resume and hw reconfiguration */ 1490 1509 int ieee80211_reconfig(struct ieee80211_local *local); ··· 1681 1654 void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, 1682 1655 const struct ieee80211_ht_operation *ht_oper, 1683 1656 struct cfg80211_chan_def *chandef); 1657 + u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c); 1684 1658 1685 1659 int __must_check 1686 1660 ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
+4
net/mac80211/iface.c
··· 766 766 if (sdata->vif.type == NL80211_IFTYPE_STATION) 767 767 ieee80211_mgd_stop(sdata); 768 768 769 + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 770 + ieee80211_ibss_stop(sdata); 771 + 772 + 769 773 /* 770 774 * Remove all stations associated with this interface. 771 775 *
+1 -1
net/mac80211/key.c
··· 879 879 keyconf->keylen, keyconf->key, 880 880 0, NULL); 881 881 if (IS_ERR(key)) 882 - return ERR_PTR(PTR_ERR(key)); 882 + return ERR_CAST(key); 883 883 884 884 if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) 885 885 key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
+70 -268
net/mac80211/mlme.c
··· 145 145 return (1 << ecw) - 1; 146 146 } 147 147 148 - static u32 chandef_downgrade(struct cfg80211_chan_def *c) 149 - { 150 - u32 ret; 151 - int tmp; 152 - 153 - switch (c->width) { 154 - case NL80211_CHAN_WIDTH_20: 155 - c->width = NL80211_CHAN_WIDTH_20_NOHT; 156 - ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 157 - break; 158 - case NL80211_CHAN_WIDTH_40: 159 - c->width = NL80211_CHAN_WIDTH_20; 160 - c->center_freq1 = c->chan->center_freq; 161 - ret = IEEE80211_STA_DISABLE_40MHZ | 162 - IEEE80211_STA_DISABLE_VHT; 163 - break; 164 - case NL80211_CHAN_WIDTH_80: 165 - tmp = (30 + c->chan->center_freq - c->center_freq1)/20; 166 - /* n_P40 */ 167 - tmp /= 2; 168 - /* freq_P40 */ 169 - c->center_freq1 = c->center_freq1 - 20 + 40 * tmp; 170 - c->width = NL80211_CHAN_WIDTH_40; 171 - ret = IEEE80211_STA_DISABLE_VHT; 172 - break; 173 - case NL80211_CHAN_WIDTH_80P80: 174 - c->center_freq2 = 0; 175 - c->width = NL80211_CHAN_WIDTH_80; 176 - ret = IEEE80211_STA_DISABLE_80P80MHZ | 177 - IEEE80211_STA_DISABLE_160MHZ; 178 - break; 179 - case NL80211_CHAN_WIDTH_160: 180 - /* n_P20 */ 181 - tmp = (70 + c->chan->center_freq - c->center_freq1)/20; 182 - /* n_P80 */ 183 - tmp /= 4; 184 - c->center_freq1 = c->center_freq1 - 40 + 80 * tmp; 185 - c->width = NL80211_CHAN_WIDTH_80; 186 - ret = IEEE80211_STA_DISABLE_80P80MHZ | 187 - IEEE80211_STA_DISABLE_160MHZ; 188 - break; 189 - default: 190 - case NL80211_CHAN_WIDTH_20_NOHT: 191 - WARN_ON_ONCE(1); 192 - c->width = NL80211_CHAN_WIDTH_20_NOHT; 193 - ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 194 - break; 195 - case NL80211_CHAN_WIDTH_5: 196 - case NL80211_CHAN_WIDTH_10: 197 - WARN_ON_ONCE(1); 198 - /* keep c->width */ 199 - ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 200 - break; 201 - } 202 - 203 - WARN_ON_ONCE(!cfg80211_chandef_valid(c)); 204 - 205 - return ret; 206 - } 207 - 208 148 static u32 209 149 ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, 210 150 struct ieee80211_supported_band *sband, ··· 292 352 break; 293 353 } 294 354 295 - ret |= chandef_downgrade(chandef); 355 + ret |= ieee80211_chandef_downgrade(chandef); 296 356 } 297 357 298 358 if (chandef->width != vht_chandef.width && !tracking) ··· 346 406 */ 347 407 if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ && 348 408 chandef.width == NL80211_CHAN_WIDTH_80P80) 349 - flags |= chandef_downgrade(&chandef); 409 + flags |= ieee80211_chandef_downgrade(&chandef); 350 410 if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ && 351 411 chandef.width == NL80211_CHAN_WIDTH_160) 352 - flags |= chandef_downgrade(&chandef); 412 + flags |= ieee80211_chandef_downgrade(&chandef); 353 413 if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ && 354 414 chandef.width > NL80211_CHAN_WIDTH_20) 355 - flags |= chandef_downgrade(&chandef); 415 + flags |= ieee80211_chandef_downgrade(&chandef); 356 416 357 417 if (cfg80211_chandef_identical(&chandef, &sdata->vif.bss_conf.chandef)) 358 418 return 0; ··· 833 893 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) 834 894 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 835 895 836 - if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 837 - IEEE80211_STA_CONNECTION_POLL)) 896 + if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) 838 897 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; 839 898 840 899 ieee80211_tx_skb(sdata, skb); ··· 876 937 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); 877 938 struct ieee80211_local *local = sdata->local; 878 939 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 940 + u32 changed = 0; 941 + int ret; 879 942 880 943 if (!ieee80211_sdata_running(sdata)) 881 944 return; ··· 886 945 if (!ifmgd->associated) 887 946 goto out; 888 947 889 - local->_oper_chandef = local->csa_chandef; 948 + ret = ieee80211_vif_change_channel(sdata, &local->csa_chandef, 949 + &changed); 950 + if (ret) { 951 + sdata_info(sdata, 952 + "vif channel switch failed, disconnecting\n"); 953 + ieee80211_queue_work(&sdata->local->hw, 954 + &ifmgd->csa_connection_drop_work); 955 + goto out; 956 + } 890 957 891 - if (!local->ops->channel_switch) { 892 - /* call "hw_config" only if doing sw channel switch */ 893 - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 894 - } else { 895 - /* update the device channel directly */ 896 - local->hw.conf.chandef = local->_oper_chandef; 958 + if (!local->use_chanctx) { 959 + local->_oper_chandef = local->csa_chandef; 960 + /* Call "hw_config" only if doing sw channel switch. 961 + * Otherwise update the channel directly 962 + */ 963 + if (!local->ops->channel_switch) 964 + ieee80211_hw_config(local, 0); 965 + else 966 + local->hw.conf.chandef = local->_oper_chandef; 897 967 } 898 968 899 969 /* XXX: shouldn't really modify cfg80211-owned data! */ 900 - ifmgd->associated->channel = local->_oper_chandef.chan; 970 + ifmgd->associated->channel = local->csa_chandef.chan; 901 971 902 972 /* XXX: wait for a beacon first? */ 903 973 ieee80211_wake_queues_by_reason(&local->hw, 904 974 IEEE80211_MAX_QUEUE_MAP, 905 975 IEEE80211_QUEUE_STOP_REASON_CSA); 976 + 977 + ieee80211_bss_info_change_notify(sdata, changed); 978 + 906 979 out: 980 + sdata->vif.csa_active = false; 907 981 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; 908 982 sdata_unlock(sdata); 909 983 } ··· 956 1000 struct ieee80211_local *local = sdata->local; 957 1001 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 958 1002 struct cfg80211_bss *cbss = ifmgd->associated; 959 - struct ieee80211_bss *bss; 960 1003 struct ieee80211_chanctx *chanctx; 961 - enum ieee80211_band new_band; 962 - int new_freq; 963 - u8 new_chan_no; 1004 + enum ieee80211_band current_band; 964 1005 u8 count; 965 1006 u8 mode; 966 - struct ieee80211_channel *new_chan; 967 1007 struct cfg80211_chan_def new_chandef = {}; 968 - struct cfg80211_chan_def new_vht_chandef = {}; 969 - const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; 970 - const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; 971 - const struct ieee80211_ht_operation *ht_oper; 972 - int secondary_channel_offset = -1; 1008 + int res; 973 1009 974 1010 sdata_assert_lock(sdata); 975 1011 ··· 975 1027 if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) 976 1028 return; 977 1029 978 - sec_chan_offs = elems->sec_chan_offs; 979 - wide_bw_chansw_ie = elems->wide_bw_chansw_ie; 980 - ht_oper = elems->ht_operation; 981 - 982 - if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | 983 - IEEE80211_STA_DISABLE_40MHZ)) { 984 - sec_chan_offs = NULL; 985 - wide_bw_chansw_ie = NULL; 986 - /* only used for bandwidth here */ 987 - ht_oper = NULL; 988 - } 989 - 990 - if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) 991 - wide_bw_chansw_ie = NULL; 992 - 993 - if (elems->ext_chansw_ie) { 994 - if (!ieee80211_operating_class_to_band( 995 - elems->ext_chansw_ie->new_operating_class, 996 - &new_band)) { 997 - sdata_info(sdata, 998 - "cannot understand ECSA IE operating class %d, disconnecting\n", 999 - elems->ext_chansw_ie->new_operating_class); 1000 - ieee80211_queue_work(&local->hw, 1001 - &ifmgd->csa_connection_drop_work); 1002 - } 1003 - new_chan_no = elems->ext_chansw_ie->new_ch_num; 1004 - count = elems->ext_chansw_ie->count; 1005 - mode = elems->ext_chansw_ie->mode; 1006 - } else if (elems->ch_switch_ie) { 1007 - new_band = cbss->channel->band; 1008 - new_chan_no = elems->ch_switch_ie->new_ch_num; 1009 - count = elems->ch_switch_ie->count; 1010 - mode = elems->ch_switch_ie->mode; 1011 - } else { 1012 - /* nothing here we understand */ 1013 - return; 1014 - } 1015 - 1016 - bss = (void *)cbss->priv; 1017 - 1018 - new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); 1019 - new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); 1020 - if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { 1021 - sdata_info(sdata, 1022 - "AP %pM switches to unsupported channel (%d MHz), disconnecting\n", 1023 - ifmgd->associated->bssid, new_freq); 1030 + current_band = cbss->channel->band; 1031 + res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, 1032 + ifmgd->flags, 1033 + ifmgd->associated->bssid, &count, 1034 + &mode, &new_chandef); 1035 + if (res < 0) 1024 1036 ieee80211_queue_work(&local->hw, 1025 1037 &ifmgd->csa_connection_drop_work); 1038 + if (res) 1026 1039 return; 1027 - } 1028 - 1029 - if (!beacon && sec_chan_offs) { 1030 - secondary_channel_offset = sec_chan_offs->sec_chan_offs; 1031 - } else if (beacon && ht_oper) { 1032 - secondary_channel_offset = 1033 - ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; 1034 - } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { 1035 - /* 1036 - * If it's not a beacon, HT is enabled and the IE not present, 1037 - * it's 20 MHz, 802.11-2012 8.5.2.6: 1038 - * This element [the Secondary Channel Offset Element] is 1039 - * present when switching to a 40 MHz channel. It may be 1040 - * present when switching to a 20 MHz channel (in which 1041 - * case the secondary channel offset is set to SCN). 1042 - */ 1043 - secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; 1044 - } 1045 - 1046 - switch (secondary_channel_offset) { 1047 - default: 1048 - /* secondary_channel_offset was present but is invalid */ 1049 - case IEEE80211_HT_PARAM_CHA_SEC_NONE: 1050 - cfg80211_chandef_create(&new_chandef, new_chan, 1051 - NL80211_CHAN_HT20); 1052 - break; 1053 - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 1054 - cfg80211_chandef_create(&new_chandef, new_chan, 1055 - NL80211_CHAN_HT40PLUS); 1056 - break; 1057 - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 1058 - cfg80211_chandef_create(&new_chandef, new_chan, 1059 - NL80211_CHAN_HT40MINUS); 1060 - break; 1061 - case -1: 1062 - cfg80211_chandef_create(&new_chandef, new_chan, 1063 - NL80211_CHAN_NO_HT); 1064 - /* keep width for 5/10 MHz channels */ 1065 - switch (sdata->vif.bss_conf.chandef.width) { 1066 - case NL80211_CHAN_WIDTH_5: 1067 - case NL80211_CHAN_WIDTH_10: 1068 - new_chandef.width = sdata->vif.bss_conf.chandef.width; 1069 - break; 1070 - default: 1071 - break; 1072 - } 1073 - break; 1074 - } 1075 - 1076 - if (wide_bw_chansw_ie) { 1077 - new_vht_chandef.chan = new_chan; 1078 - new_vht_chandef.center_freq1 = 1079 - ieee80211_channel_to_frequency( 1080 - wide_bw_chansw_ie->new_center_freq_seg0, 1081 - new_band); 1082 - 1083 - switch (wide_bw_chansw_ie->new_channel_width) { 1084 - default: 1085 - /* hmmm, ignore VHT and use HT if present */ 1086 - case IEEE80211_VHT_CHANWIDTH_USE_HT: 1087 - new_vht_chandef.chan = NULL; 1088 - break; 1089 - case IEEE80211_VHT_CHANWIDTH_80MHZ: 1090 - new_vht_chandef.width = NL80211_CHAN_WIDTH_80; 1091 - break; 1092 - case IEEE80211_VHT_CHANWIDTH_160MHZ: 1093 - new_vht_chandef.width = NL80211_CHAN_WIDTH_160; 1094 - break; 1095 - case IEEE80211_VHT_CHANWIDTH_80P80MHZ: 1096 - /* field is otherwise reserved */ 1097 - new_vht_chandef.center_freq2 = 1098 - ieee80211_channel_to_frequency( 1099 - wide_bw_chansw_ie->new_center_freq_seg1, 1100 - new_band); 1101 - new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80; 1102 - break; 1103 - } 1104 - if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ && 1105 - new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80) 1106 - chandef_downgrade(&new_vht_chandef); 1107 - if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ && 1108 - new_vht_chandef.width == NL80211_CHAN_WIDTH_160) 1109 - chandef_downgrade(&new_vht_chandef); 1110 - if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ && 1111 - new_vht_chandef.width > NL80211_CHAN_WIDTH_20) 1112 - chandef_downgrade(&new_vht_chandef); 1113 - } 1114 - 1115 - /* if VHT data is there validate & use it */ 1116 - if (new_vht_chandef.chan) { 1117 - if (!cfg80211_chandef_compatible(&new_vht_chandef, 1118 - &new_chandef)) { 1119 - sdata_info(sdata, 1120 - "AP %pM CSA has inconsistent channel data, disconnecting\n", 1121 - ifmgd->associated->bssid); 1122 - ieee80211_queue_work(&local->hw, 1123 - &ifmgd->csa_connection_drop_work); 1124 - return; 1125 - } 1126 - new_chandef = new_vht_chandef; 1127 - } 1128 1040 1129 1041 if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef, 1130 1042 IEEE80211_CHAN_DISABLED)) { 1131 1043 sdata_info(sdata, 1132 1044 "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", 1133 - ifmgd->associated->bssid, new_freq, 1045 + ifmgd->associated->bssid, 1046 + new_chandef.chan->center_freq, 1134 1047 new_chandef.width, new_chandef.center_freq1, 1135 1048 new_chandef.center_freq2); 1136 1049 ieee80211_queue_work(&local->hw, ··· 1000 1191 } 1001 1192 1002 1193 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; 1003 - 1004 - if (local->use_chanctx) { 1005 - sdata_info(sdata, 1006 - "not handling channel switch with channel contexts\n"); 1007 - ieee80211_queue_work(&local->hw, 1008 - &ifmgd->csa_connection_drop_work); 1009 - return; 1010 - } 1194 + sdata->vif.csa_active = true; 1011 1195 1012 1196 mutex_lock(&local->chanctx_mtx); 1197 + if (local->use_chanctx) { 1198 + u32 num_chanctx = 0; 1199 + list_for_each_entry(chanctx, &local->chanctx_list, list) 1200 + num_chanctx++; 1201 + 1202 + if (num_chanctx > 1 || 1203 + !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) { 1204 + sdata_info(sdata, 1205 + "not handling chan-switch with channel contexts\n"); 1206 + ieee80211_queue_work(&local->hw, 1207 + &ifmgd->csa_connection_drop_work); 1208 + mutex_unlock(&local->chanctx_mtx); 1209 + return; 1210 + } 1211 + } 1212 + 1013 1213 if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) { 1214 + ieee80211_queue_work(&local->hw, 1215 + &ifmgd->csa_connection_drop_work); 1014 1216 mutex_unlock(&local->chanctx_mtx); 1015 1217 return; 1016 1218 } ··· 1194 1374 if (!mgd->associated) 1195 1375 return false; 1196 1376 1197 - if (mgd->flags & (IEEE80211_STA_BEACON_POLL | 1198 - IEEE80211_STA_CONNECTION_POLL)) 1377 + if (mgd->flags & IEEE80211_STA_CONNECTION_POLL) 1199 1378 return false; 1200 1379 1201 1380 if (!mgd->have_beacon) ··· 1510 1691 { 1511 1692 lockdep_assert_held(&sdata->local->mtx); 1512 1693 1513 - sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | 1514 - IEEE80211_STA_BEACON_POLL); 1694 + sdata->u.mgd.flags &= ~IEEE80211_STA_CONNECTION_POLL; 1515 1695 ieee80211_run_deferred_scan(sdata->local); 1516 1696 } 1517 1697 ··· 1772 1954 struct ieee80211_local *local = sdata->local; 1773 1955 1774 1956 mutex_lock(&local->mtx); 1775 - if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 1776 - IEEE80211_STA_CONNECTION_POLL))) { 1777 - mutex_unlock(&local->mtx); 1778 - return; 1779 - } 1957 + if (!(ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)) 1958 + goto out; 1780 1959 1781 1960 __ieee80211_stop_poll(sdata); 1782 1961 ··· 1909 2094 * because otherwise we would reset the timer every time and 1910 2095 * never check whether we received a probe response! 1911 2096 */ 1912 - if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 1913 - IEEE80211_STA_CONNECTION_POLL)) 2097 + if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) 1914 2098 already = true; 1915 - 1916 - if (beacon) 1917 - ifmgd->flags |= IEEE80211_STA_BEACON_POLL; 1918 - else 1919 - ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL; 1920 2099 1921 2100 mutex_unlock(&sdata->local->mtx); 1922 2101 ··· 1983 2174 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 1984 2175 true, frame_buf); 1985 2176 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; 2177 + sdata->vif.csa_active = false; 1986 2178 ieee80211_wake_queues_by_reason(&sdata->local->hw, 1987 2179 IEEE80211_MAX_QUEUE_MAP, 1988 2180 IEEE80211_QUEUE_STOP_REASON_CSA); ··· 2871 3061 } 2872 3062 } 2873 3063 2874 - if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { 3064 + if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) { 2875 3065 mlme_dbg_ratelimited(sdata, 2876 3066 "cancelling AP probe due to a received beacon\n"); 2877 - mutex_lock(&local->mtx); 2878 - ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; 2879 - ieee80211_run_deferred_scan(local); 2880 - mutex_unlock(&local->mtx); 2881 - 2882 - mutex_lock(&local->iflist_mtx); 2883 - ieee80211_recalc_ps(local, -1); 2884 - mutex_unlock(&local->iflist_mtx); 3067 + ieee80211_reset_ap_probe(sdata); 2885 3068 } 2886 3069 2887 3070 /* ··· 3346 3543 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) 3347 3544 run_again(sdata, ifmgd->assoc_data->timeout); 3348 3545 3349 - if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 3350 - IEEE80211_STA_CONNECTION_POLL) && 3546 + if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL && 3351 3547 ifmgd->associated) { 3352 3548 u8 bssid[ETH_ALEN]; 3353 3549 int max_tries; ··· 3678 3876 return ret; 3679 3877 3680 3878 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { 3681 - ifmgd->flags |= chandef_downgrade(&chandef); 3879 + ifmgd->flags |= ieee80211_chandef_downgrade(&chandef); 3682 3880 ret = ieee80211_vif_use_channel(sdata, &chandef, 3683 3881 IEEE80211_CHANCTX_SHARED); 3684 3882 }
+14
net/mac80211/rc80211_minstrel.c
··· 203 203 memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); 204 204 mi->max_prob_rate = tmp_prob_rate; 205 205 206 + #ifdef CONFIG_MAC80211_DEBUGFS 207 + /* use fixed index if set */ 208 + if (mp->fixed_rate_idx != -1) { 209 + mi->max_tp_rate[0] = mp->fixed_rate_idx; 210 + mi->max_tp_rate[1] = mp->fixed_rate_idx; 211 + mi->max_prob_rate = mp->fixed_rate_idx; 212 + } 213 + #endif 214 + 206 215 /* Reset update timer */ 207 216 mi->stats_update = jiffies; 208 217 ··· 318 309 319 310 /* increase sum packet counter */ 320 311 mi->packet_count++; 312 + 313 + #ifdef CONFIG_MAC80211_DEBUGFS 314 + if (mp->fixed_rate_idx != -1) 315 + return; 316 + #endif 321 317 322 318 delta = (mi->packet_count * sampling_ratio / 100) - 323 319 (mi->sample_count + mi->sample_deferred / 2);
+13 -10
net/mac80211/rc80211_minstrel_ht.c
··· 365 365 } 366 366 } 367 367 368 + #ifdef CONFIG_MAC80211_DEBUGFS 369 + /* use fixed index if set */ 370 + if (mp->fixed_rate_idx != -1) { 371 + mi->max_tp_rate = mp->fixed_rate_idx; 372 + mi->max_tp_rate2 = mp->fixed_rate_idx; 373 + mi->max_prob_rate = mp->fixed_rate_idx; 374 + } 375 + #endif 368 376 369 377 mi->stats_update = jiffies; 370 378 } ··· 782 774 info->flags |= mi->tx_flags; 783 775 minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble); 784 776 777 + #ifdef CONFIG_MAC80211_DEBUGFS 778 + if (mp->fixed_rate_idx != -1) 779 + return; 780 + #endif 781 + 785 782 /* Don't use EAPOL frames for sampling on non-mrr hw */ 786 783 if (mp->hw->max_rates == 1 && 787 784 (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) 788 785 sample_idx = -1; 789 786 else 790 787 sample_idx = minstrel_get_sample_rate(mp, mi); 791 - 792 - #ifdef CONFIG_MAC80211_DEBUGFS 793 - /* use fixed index if set */ 794 - if (mp->fixed_rate_idx != -1) { 795 - mi->max_tp_rate = mp->fixed_rate_idx; 796 - mi->max_tp_rate2 = mp->fixed_rate_idx; 797 - mi->max_prob_rate = mp->fixed_rate_idx; 798 - sample_idx = -1; 799 - } 800 - #endif 801 788 802 789 mi->total_packets++; 803 790
+13 -13
net/mac80211/rc80211_pid_debugfs.c
··· 167 167 * provide large enough buffers. */ 168 168 length = length < RC_PID_PRINT_BUF_SIZE ? 169 169 length : RC_PID_PRINT_BUF_SIZE; 170 - p = snprintf(pb, length, "%u %lu ", ev->id, ev->timestamp); 170 + p = scnprintf(pb, length, "%u %lu ", ev->id, ev->timestamp); 171 171 switch (ev->type) { 172 172 case RC_PID_EVENT_TYPE_TX_STATUS: 173 - p += snprintf(pb + p, length - p, "tx_status %u %u", 174 - !(ev->data.flags & IEEE80211_TX_STAT_ACK), 175 - ev->data.tx_status.status.rates[0].idx); 173 + p += scnprintf(pb + p, length - p, "tx_status %u %u", 174 + !(ev->data.flags & IEEE80211_TX_STAT_ACK), 175 + ev->data.tx_status.status.rates[0].idx); 176 176 break; 177 177 case RC_PID_EVENT_TYPE_RATE_CHANGE: 178 - p += snprintf(pb + p, length - p, "rate_change %d %d", 179 - ev->data.index, ev->data.rate); 178 + p += scnprintf(pb + p, length - p, "rate_change %d %d", 179 + ev->data.index, ev->data.rate); 180 180 break; 181 181 case RC_PID_EVENT_TYPE_TX_RATE: 182 - p += snprintf(pb + p, length - p, "tx_rate %d %d", 183 - ev->data.index, ev->data.rate); 182 + p += scnprintf(pb + p, length - p, "tx_rate %d %d", 183 + ev->data.index, ev->data.rate); 184 184 break; 185 185 case RC_PID_EVENT_TYPE_PF_SAMPLE: 186 - p += snprintf(pb + p, length - p, 187 - "pf_sample %d %d %d %d", 188 - ev->data.pf_sample, ev->data.prop_err, 189 - ev->data.int_err, ev->data.der_err); 186 + p += scnprintf(pb + p, length - p, 187 + "pf_sample %d %d %d %d", 188 + ev->data.pf_sample, ev->data.prop_err, 189 + ev->data.int_err, ev->data.der_err); 190 190 break; 191 191 } 192 - p += snprintf(pb + p, length - p, "\n"); 192 + p += scnprintf(pb + p, length - p, "\n"); 193 193 194 194 spin_unlock_irqrestore(&events->lock, status); 195 195
+29 -12
net/mac80211/rx.c
··· 995 995 rx->sta->num_duplicates++; 996 996 } 997 997 return RX_DROP_UNUSABLE; 998 - } else 998 + } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) { 999 999 rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; 1000 + } 1000 1001 } 1001 1002 1002 1003 if (unlikely(rx->skb->len < 16)) { ··· 2403 2402 return RX_DROP_UNUSABLE; 2404 2403 2405 2404 if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC && 2406 - mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED) 2405 + mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED && 2406 + mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) 2407 2407 return RX_DROP_UNUSABLE; 2408 2408 2409 2409 if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) ··· 2568 2566 2569 2567 goto queue; 2570 2568 case WLAN_CATEGORY_SPECTRUM_MGMT: 2571 - if (status->band != IEEE80211_BAND_5GHZ) 2572 - break; 2573 - 2574 - if (sdata->vif.type != NL80211_IFTYPE_STATION) 2575 - break; 2576 - 2577 2569 /* verify action_code is present */ 2578 2570 if (len < IEEE80211_MIN_ACTION_SIZE + 1) 2579 2571 break; 2580 2572 2581 2573 switch (mgmt->u.action.u.measurement.action_code) { 2582 2574 case WLAN_ACTION_SPCT_MSR_REQ: 2575 + if (status->band != IEEE80211_BAND_5GHZ) 2576 + break; 2577 + 2583 2578 if (len < (IEEE80211_MIN_ACTION_SIZE + 2584 2579 sizeof(mgmt->u.action.u.measurement))) 2585 2580 break; 2586 - ieee80211_process_measurement_req(sdata, mgmt, len); 2587 - goto handled; 2588 - case WLAN_ACTION_SPCT_CHL_SWITCH: 2581 + 2589 2582 if (sdata->vif.type != NL80211_IFTYPE_STATION) 2590 2583 break; 2591 2584 2592 - if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid)) 2585 + ieee80211_process_measurement_req(sdata, mgmt, len); 2586 + goto handled; 2587 + case WLAN_ACTION_SPCT_CHL_SWITCH: { 2588 + u8 *bssid; 2589 + if (len < (IEEE80211_MIN_ACTION_SIZE + 2590 + sizeof(mgmt->u.action.u.chan_switch))) 2591 + break; 2592 + 2593 + if (sdata->vif.type != NL80211_IFTYPE_STATION && 2594 + sdata->vif.type != NL80211_IFTYPE_ADHOC) 2595 + break; 2596 + 2597 + if (sdata->vif.type == NL80211_IFTYPE_STATION) 2598 + bssid = sdata->u.mgd.bssid; 2599 + else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 2600 + bssid = sdata->u.ibss.bssid; 2601 + else 2602 + break; 2603 + 2604 + if (!ether_addr_equal(mgmt->bssid, bssid)) 2593 2605 break; 2594 2606 2595 2607 goto queue; 2608 + } 2596 2609 } 2597 2610 break; 2598 2611 case WLAN_CATEGORY_SA_QUERY:
+1 -2
net/mac80211/scan.c
··· 391 391 return false; 392 392 393 393 if (sdata->vif.type == NL80211_IFTYPE_STATION && 394 - sdata->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | 395 - IEEE80211_STA_CONNECTION_POLL)) 394 + sdata->u.mgd.flags & IEEE80211_STA_CONNECTION_POLL) 396 395 return false; 397 396 398 397 return true;
+162
net/mac80211/spectmgmt.c
··· 21 21 #include "sta_info.h" 22 22 #include "wme.h" 23 23 24 + int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, 25 + struct ieee802_11_elems *elems, bool beacon, 26 + enum ieee80211_band current_band, 27 + u32 sta_flags, u8 *bssid, u8 *count, u8 *mode, 28 + struct cfg80211_chan_def *new_chandef) 29 + { 30 + enum ieee80211_band new_band; 31 + int new_freq; 32 + u8 new_chan_no; 33 + struct ieee80211_channel *new_chan; 34 + struct cfg80211_chan_def new_vht_chandef = {}; 35 + const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; 36 + const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; 37 + const struct ieee80211_ht_operation *ht_oper; 38 + int secondary_channel_offset = -1; 39 + 40 + sec_chan_offs = elems->sec_chan_offs; 41 + wide_bw_chansw_ie = elems->wide_bw_chansw_ie; 42 + ht_oper = elems->ht_operation; 43 + 44 + if (sta_flags & (IEEE80211_STA_DISABLE_HT | 45 + IEEE80211_STA_DISABLE_40MHZ)) { 46 + sec_chan_offs = NULL; 47 + wide_bw_chansw_ie = NULL; 48 + /* only used for bandwidth here */ 49 + ht_oper = NULL; 50 + } 51 + 52 + if (sta_flags & IEEE80211_STA_DISABLE_VHT) 53 + wide_bw_chansw_ie = NULL; 54 + 55 + if (elems->ext_chansw_ie) { 56 + if (!ieee80211_operating_class_to_band( 57 + elems->ext_chansw_ie->new_operating_class, 58 + &new_band)) { 59 + sdata_info(sdata, 60 + "cannot understand ECSA IE operating class %d, disconnecting\n", 61 + elems->ext_chansw_ie->new_operating_class); 62 + return -EINVAL; 63 + } 64 + new_chan_no = elems->ext_chansw_ie->new_ch_num; 65 + *count = elems->ext_chansw_ie->count; 66 + *mode = elems->ext_chansw_ie->mode; 67 + } else if (elems->ch_switch_ie) { 68 + new_band = current_band; 69 + new_chan_no = elems->ch_switch_ie->new_ch_num; 70 + *count = elems->ch_switch_ie->count; 71 + *mode = elems->ch_switch_ie->mode; 72 + } else { 73 + /* nothing here we understand */ 74 + return 1; 75 + } 76 + 77 + new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); 78 + new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); 79 + if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { 80 + sdata_info(sdata, 81 + "BSS %pM switches to unsupported channel (%d MHz), disconnecting\n", 82 + bssid, new_freq); 83 + return -EINVAL; 84 + } 85 + 86 + if (!beacon && sec_chan_offs) { 87 + secondary_channel_offset = sec_chan_offs->sec_chan_offs; 88 + } else if (beacon && ht_oper) { 89 + secondary_channel_offset = 90 + ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; 91 + } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) { 92 + /* If it's not a beacon, HT is enabled and the IE not present, 93 + * it's 20 MHz, 802.11-2012 8.5.2.6: 94 + * This element [the Secondary Channel Offset Element] is 95 + * present when switching to a 40 MHz channel. It may be 96 + * present when switching to a 20 MHz channel (in which 97 + * case the secondary channel offset is set to SCN). 98 + */ 99 + secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; 100 + } 101 + 102 + switch (secondary_channel_offset) { 103 + default: 104 + /* secondary_channel_offset was present but is invalid */ 105 + case IEEE80211_HT_PARAM_CHA_SEC_NONE: 106 + cfg80211_chandef_create(new_chandef, new_chan, 107 + NL80211_CHAN_HT20); 108 + break; 109 + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 110 + cfg80211_chandef_create(new_chandef, new_chan, 111 + NL80211_CHAN_HT40PLUS); 112 + break; 113 + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 114 + cfg80211_chandef_create(new_chandef, new_chan, 115 + NL80211_CHAN_HT40MINUS); 116 + break; 117 + case -1: 118 + cfg80211_chandef_create(new_chandef, new_chan, 119 + NL80211_CHAN_NO_HT); 120 + /* keep width for 5/10 MHz channels */ 121 + switch (sdata->vif.bss_conf.chandef.width) { 122 + case NL80211_CHAN_WIDTH_5: 123 + case NL80211_CHAN_WIDTH_10: 124 + new_chandef->width = sdata->vif.bss_conf.chandef.width; 125 + break; 126 + default: 127 + break; 128 + } 129 + break; 130 + } 131 + 132 + if (wide_bw_chansw_ie) { 133 + new_vht_chandef.chan = new_chan; 134 + new_vht_chandef.center_freq1 = 135 + ieee80211_channel_to_frequency( 136 + wide_bw_chansw_ie->new_center_freq_seg0, 137 + new_band); 138 + 139 + switch (wide_bw_chansw_ie->new_channel_width) { 140 + default: 141 + /* hmmm, ignore VHT and use HT if present */ 142 + case IEEE80211_VHT_CHANWIDTH_USE_HT: 143 + new_vht_chandef.chan = NULL; 144 + break; 145 + case IEEE80211_VHT_CHANWIDTH_80MHZ: 146 + new_vht_chandef.width = NL80211_CHAN_WIDTH_80; 147 + break; 148 + case IEEE80211_VHT_CHANWIDTH_160MHZ: 149 + new_vht_chandef.width = NL80211_CHAN_WIDTH_160; 150 + break; 151 + case IEEE80211_VHT_CHANWIDTH_80P80MHZ: 152 + /* field is otherwise reserved */ 153 + new_vht_chandef.center_freq2 = 154 + ieee80211_channel_to_frequency( 155 + wide_bw_chansw_ie->new_center_freq_seg1, 156 + new_band); 157 + new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80; 158 + break; 159 + } 160 + if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ && 161 + new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80) 162 + ieee80211_chandef_downgrade(&new_vht_chandef); 163 + if (sta_flags & IEEE80211_STA_DISABLE_160MHZ && 164 + new_vht_chandef.width == NL80211_CHAN_WIDTH_160) 165 + ieee80211_chandef_downgrade(&new_vht_chandef); 166 + if (sta_flags & IEEE80211_STA_DISABLE_40MHZ && 167 + new_vht_chandef.width > NL80211_CHAN_WIDTH_20) 168 + ieee80211_chandef_downgrade(&new_vht_chandef); 169 + } 170 + 171 + /* if VHT data is there validate & use it */ 172 + if (new_vht_chandef.chan) { 173 + if (!cfg80211_chandef_compatible(&new_vht_chandef, 174 + new_chandef)) { 175 + sdata_info(sdata, 176 + "BSS %pM: CSA has inconsistent channel data, disconnecting\n", 177 + bssid); 178 + return -EINVAL; 179 + } 180 + *new_chandef = new_vht_chandef; 181 + } 182 + 183 + return 0; 184 + } 185 + 24 186 static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, 25 187 struct ieee80211_msrment_ie *request_ie, 26 188 const u8 *da, const u8 *bssid,
+35
net/mac80211/trace.h
··· 1475 1475 ); 1476 1476 #endif 1477 1477 1478 + TRACE_EVENT(drv_join_ibss, 1479 + TP_PROTO(struct ieee80211_local *local, 1480 + struct ieee80211_sub_if_data *sdata, 1481 + struct ieee80211_bss_conf *info), 1482 + 1483 + TP_ARGS(local, sdata, info), 1484 + 1485 + TP_STRUCT__entry( 1486 + LOCAL_ENTRY 1487 + VIF_ENTRY 1488 + __field(u8, dtimper) 1489 + __field(u16, bcnint) 1490 + __dynamic_array(u8, ssid, info->ssid_len); 1491 + ), 1492 + 1493 + TP_fast_assign( 1494 + LOCAL_ASSIGN; 1495 + VIF_ASSIGN; 1496 + __entry->dtimper = info->dtim_period; 1497 + __entry->bcnint = info->beacon_int; 1498 + memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); 1499 + ), 1500 + 1501 + TP_printk( 1502 + LOCAL_PR_FMT VIF_PR_FMT, 1503 + LOCAL_PR_ARG, VIF_PR_ARG 1504 + ) 1505 + ); 1506 + 1507 + DEFINE_EVENT(local_sdata_evt, drv_leave_ibss, 1508 + TP_PROTO(struct ieee80211_local *local, 1509 + struct ieee80211_sub_if_data *sdata), 1510 + TP_ARGS(local, sdata) 1511 + ); 1512 + 1478 1513 /* 1479 1514 * Tracing for API calls that drivers call. 1480 1515 */
+35 -6
net/mac80211/tx.c
··· 1981 1981 * EAPOL frames from the local station. 1982 1982 */ 1983 1983 if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) && 1984 - !is_multicast_ether_addr(hdr.addr1) && !authorized && 1984 + !multicast && !authorized && 1985 1985 (cpu_to_be16(ethertype) != sdata->control_port_protocol || 1986 1986 !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) { 1987 1987 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG ··· 2357 2357 struct probe_resp *resp; 2358 2358 int counter_offset_beacon = sdata->csa_counter_offset_beacon; 2359 2359 int counter_offset_presp = sdata->csa_counter_offset_presp; 2360 + u8 *beacon_data; 2361 + size_t beacon_data_len; 2360 2362 2361 - /* warn if the driver did not check for/react to csa completeness */ 2362 - if (WARN_ON(((u8 *)beacon->tail)[counter_offset_beacon] == 0)) 2363 + switch (sdata->vif.type) { 2364 + case NL80211_IFTYPE_AP: 2365 + beacon_data = beacon->tail; 2366 + beacon_data_len = beacon->tail_len; 2367 + break; 2368 + case NL80211_IFTYPE_ADHOC: 2369 + beacon_data = beacon->head; 2370 + beacon_data_len = beacon->head_len; 2371 + break; 2372 + default: 2373 + return; 2374 + } 2375 + if (WARN_ON(counter_offset_beacon >= beacon_data_len)) 2363 2376 return; 2364 2377 2365 - ((u8 *)beacon->tail)[counter_offset_beacon]--; 2378 + /* warn if the driver did not check for/react to csa completeness */ 2379 + if (WARN_ON(beacon_data[counter_offset_beacon] == 0)) 2380 + return; 2366 2381 2367 - if (sdata->vif.type == NL80211_IFTYPE_AP && 2368 - counter_offset_presp) { 2382 + beacon_data[counter_offset_beacon]--; 2383 + 2384 + if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) { 2369 2385 rcu_read_lock(); 2370 2386 resp = rcu_dereference(sdata->u.ap.probe_resp); 2371 2387 ··· 2416 2400 goto out; 2417 2401 beacon_data = beacon->tail; 2418 2402 beacon_data_len = beacon->tail_len; 2403 + } else if (vif->type == NL80211_IFTYPE_ADHOC) { 2404 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 2405 + 2406 + beacon = rcu_dereference(ifibss->presp); 2407 + if (!beacon) 2408 + goto out; 2409 + 2410 + beacon_data = beacon->head; 2411 + beacon_data_len = beacon->head_len; 2419 2412 } else { 2420 2413 WARN_ON(1); 2421 2414 goto out; ··· 2508 2483 2509 2484 if (!presp) 2510 2485 goto out; 2486 + 2487 + if (sdata->vif.csa_active) 2488 + ieee80211_update_csa(sdata, presp); 2489 + 2511 2490 2512 2491 skb = dev_alloc_skb(local->tx_headroom + presp->head_len); 2513 2492 if (!skb)
+123 -65
net/mac80211/util.c
··· 567 567 IEEE80211_QUEUE_STOP_REASON_FLUSH); 568 568 } 569 569 570 - void ieee80211_iterate_active_interfaces( 571 - struct ieee80211_hw *hw, u32 iter_flags, 572 - void (*iterator)(void *data, u8 *mac, 573 - struct ieee80211_vif *vif), 574 - void *data) 570 + static void __iterate_active_interfaces(struct ieee80211_local *local, 571 + u32 iter_flags, 572 + void (*iterator)(void *data, u8 *mac, 573 + struct ieee80211_vif *vif), 574 + void *data) 575 575 { 576 - struct ieee80211_local *local = hw_to_local(hw); 577 576 struct ieee80211_sub_if_data *sdata; 578 - 579 - mutex_lock(&local->iflist_mtx); 580 - 581 - list_for_each_entry(sdata, &local->interfaces, list) { 582 - switch (sdata->vif.type) { 583 - case NL80211_IFTYPE_MONITOR: 584 - if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) 585 - continue; 586 - break; 587 - case NL80211_IFTYPE_AP_VLAN: 588 - continue; 589 - default: 590 - break; 591 - } 592 - if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) && 593 - !(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) 594 - continue; 595 - if (ieee80211_sdata_running(sdata)) 596 - iterator(data, sdata->vif.addr, 597 - &sdata->vif); 598 - } 599 - 600 - sdata = rcu_dereference_protected(local->monitor_sdata, 601 - lockdep_is_held(&local->iflist_mtx)); 602 - if (sdata && 603 - (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || 604 - sdata->flags & IEEE80211_SDATA_IN_DRIVER)) 605 - iterator(data, sdata->vif.addr, &sdata->vif); 606 - 607 - mutex_unlock(&local->iflist_mtx); 608 - } 609 - EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); 610 - 611 - void ieee80211_iterate_active_interfaces_atomic( 612 - struct ieee80211_hw *hw, u32 iter_flags, 613 - void (*iterator)(void *data, u8 *mac, 614 - struct ieee80211_vif *vif), 615 - void *data) 616 - { 617 - struct ieee80211_local *local = hw_to_local(hw); 618 - struct ieee80211_sub_if_data *sdata; 619 - 620 - rcu_read_lock(); 621 577 622 578 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 623 579 switch (sdata->vif.type) { ··· 594 638 &sdata->vif); 595 639 } 596 640 597 - sdata = rcu_dereference(local->monitor_sdata); 641 + sdata = rcu_dereference_check(local->monitor_sdata, 642 + lockdep_is_held(&local->iflist_mtx) || 643 + lockdep_rtnl_is_held()); 598 644 if (sdata && 599 645 (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || 600 646 sdata->flags & IEEE80211_SDATA_IN_DRIVER)) 601 647 iterator(data, sdata->vif.addr, &sdata->vif); 648 + } 602 649 650 + void ieee80211_iterate_active_interfaces( 651 + struct ieee80211_hw *hw, u32 iter_flags, 652 + void (*iterator)(void *data, u8 *mac, 653 + struct ieee80211_vif *vif), 654 + void *data) 655 + { 656 + struct ieee80211_local *local = hw_to_local(hw); 657 + 658 + mutex_lock(&local->iflist_mtx); 659 + __iterate_active_interfaces(local, iter_flags, iterator, data); 660 + mutex_unlock(&local->iflist_mtx); 661 + } 662 + EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); 663 + 664 + void ieee80211_iterate_active_interfaces_atomic( 665 + struct ieee80211_hw *hw, u32 iter_flags, 666 + void (*iterator)(void *data, u8 *mac, 667 + struct ieee80211_vif *vif), 668 + void *data) 669 + { 670 + struct ieee80211_local *local = hw_to_local(hw); 671 + 672 + rcu_read_lock(); 673 + __iterate_active_interfaces(local, iter_flags, iterator, data); 603 674 rcu_read_unlock(); 604 675 } 605 676 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); 677 + 678 + void ieee80211_iterate_active_interfaces_rtnl( 679 + struct ieee80211_hw *hw, u32 iter_flags, 680 + void (*iterator)(void *data, u8 *mac, 681 + struct ieee80211_vif *vif), 682 + void *data) 683 + { 684 + struct ieee80211_local *local = hw_to_local(hw); 685 + 686 + ASSERT_RTNL(); 687 + 688 + __iterate_active_interfaces(local, iter_flags, iterator, data); 689 + } 690 + EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl); 606 691 607 692 /* 608 693 * Nothing should have been stuffed into the workqueue during ··· 1004 1007 */ 1005 1008 enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION); 1006 1009 1007 - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 1008 - /* Set defaults according to 802.11-2007 Table 7-37 */ 1009 - aCWmax = 1023; 1010 - if (use_11b) 1011 - aCWmin = 31; 1012 - else 1013 - aCWmin = 15; 1010 + /* Set defaults according to 802.11-2007 Table 7-37 */ 1011 + aCWmax = 1023; 1012 + if (use_11b) 1013 + aCWmin = 31; 1014 + else 1015 + aCWmin = 15; 1014 1016 1017 + /* Confiure old 802.11b/g medium access rules. */ 1018 + qparam.cw_max = aCWmax; 1019 + qparam.cw_min = aCWmin; 1020 + qparam.txop = 0; 1021 + qparam.aifs = 2; 1022 + 1023 + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 1024 + /* Update if QoS is enabled. */ 1015 1025 if (enable_qos) { 1016 1026 switch (ac) { 1017 1027 case IEEE80211_AC_BK: ··· 1054 1050 qparam.aifs = 2; 1055 1051 break; 1056 1052 } 1057 - } else { 1058 - /* Confiure old 802.11b/g medium access rules. */ 1059 - qparam.cw_max = aCWmax; 1060 - qparam.cw_min = aCWmin; 1061 - qparam.txop = 0; 1062 - qparam.aifs = 2; 1063 1053 } 1064 1054 1065 1055 qparam.uapsd = false; ··· 1082 1084 struct ieee80211_mgmt *mgmt; 1083 1085 int err; 1084 1086 1085 - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 1086 - sizeof(*mgmt) + 6 + extra_len); 1087 + /* 24 + 6 = header + auth_algo + auth_transaction + status_code */ 1088 + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 6 + extra_len); 1087 1089 if (!skb) 1088 1090 return; 1089 1091 ··· 2293 2295 ieee80211_queue_work(hw, &local->radar_detected_work); 2294 2296 } 2295 2297 EXPORT_SYMBOL(ieee80211_radar_detected); 2298 + 2299 + u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) 2300 + { 2301 + u32 ret; 2302 + int tmp; 2303 + 2304 + switch (c->width) { 2305 + case NL80211_CHAN_WIDTH_20: 2306 + c->width = NL80211_CHAN_WIDTH_20_NOHT; 2307 + ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 2308 + break; 2309 + case NL80211_CHAN_WIDTH_40: 2310 + c->width = NL80211_CHAN_WIDTH_20; 2311 + c->center_freq1 = c->chan->center_freq; 2312 + ret = IEEE80211_STA_DISABLE_40MHZ | 2313 + IEEE80211_STA_DISABLE_VHT; 2314 + break; 2315 + case NL80211_CHAN_WIDTH_80: 2316 + tmp = (30 + c->chan->center_freq - c->center_freq1)/20; 2317 + /* n_P40 */ 2318 + tmp /= 2; 2319 + /* freq_P40 */ 2320 + c->center_freq1 = c->center_freq1 - 20 + 40 * tmp; 2321 + c->width = NL80211_CHAN_WIDTH_40; 2322 + ret = IEEE80211_STA_DISABLE_VHT; 2323 + break; 2324 + case NL80211_CHAN_WIDTH_80P80: 2325 + c->center_freq2 = 0; 2326 + c->width = NL80211_CHAN_WIDTH_80; 2327 + ret = IEEE80211_STA_DISABLE_80P80MHZ | 2328 + IEEE80211_STA_DISABLE_160MHZ; 2329 + break; 2330 + case NL80211_CHAN_WIDTH_160: 2331 + /* n_P20 */ 2332 + tmp = (70 + c->chan->center_freq - c->center_freq1)/20; 2333 + /* n_P80 */ 2334 + tmp /= 4; 2335 + c->center_freq1 = c->center_freq1 - 40 + 80 * tmp; 2336 + c->width = NL80211_CHAN_WIDTH_80; 2337 + ret = IEEE80211_STA_DISABLE_80P80MHZ | 2338 + IEEE80211_STA_DISABLE_160MHZ; 2339 + break; 2340 + default: 2341 + case NL80211_CHAN_WIDTH_20_NOHT: 2342 + WARN_ON_ONCE(1); 2343 + c->width = NL80211_CHAN_WIDTH_20_NOHT; 2344 + ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 2345 + break; 2346 + case NL80211_CHAN_WIDTH_5: 2347 + case NL80211_CHAN_WIDTH_10: 2348 + WARN_ON_ONCE(1); 2349 + /* keep c->width */ 2350 + ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 2351 + break; 2352 + } 2353 + 2354 + WARN_ON_ONCE(!cfg80211_chandef_valid(c)); 2355 + 2356 + return ret; 2357 + }
+2 -2
net/mac80211/vht.c
··· 185 185 if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) { 186 186 vht_cap->cap |= cap_info & 187 187 (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | 188 - IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX | 189 188 IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX); 190 189 } 191 190 192 191 if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) 193 192 vht_cap->cap |= cap_info & 194 - IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; 193 + (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | 194 + IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX); 195 195 196 196 if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) 197 197 vht_cap->cap |= cap_info &
+1
net/wireless/chan.c
··· 328 328 return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2, 329 329 width); 330 330 } 331 + EXPORT_SYMBOL(cfg80211_chandef_dfs_required); 331 332 332 333 static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, 333 334 u32 center_freq, u32 bandwidth,
-9
net/wireless/core.h
··· 382 382 enum cfg80211_chan_mode chanmode, 383 383 u8 radar_detect); 384 384 385 - /** 386 - * cfg80211_chandef_dfs_required - checks if radar detection is required 387 - * @wiphy: the wiphy to validate against 388 - * @chandef: the channel definition to check 389 - * Return: 1 if radar detection is required, 0 if it is not, < 0 on error 390 - */ 391 - int cfg80211_chandef_dfs_required(struct wiphy *wiphy, 392 - const struct cfg80211_chan_def *c); 393 - 394 385 void cfg80211_set_dfs_state(struct wiphy *wiphy, 395 386 const struct cfg80211_chan_def *chandef, 396 387 enum nl80211_dfs_state dfs_state);
+12 -10
net/wireless/debugfs.c
··· 47 47 return 0; 48 48 49 49 if (chan->flags & IEEE80211_CHAN_DISABLED) 50 - return snprintf(buf + offset, 51 - buf_size - offset, 52 - "%d Disabled\n", 53 - chan->center_freq); 50 + return scnprintf(buf + offset, 51 + buf_size - offset, 52 + "%d Disabled\n", 53 + chan->center_freq); 54 54 55 - return snprintf(buf + offset, 56 - buf_size - offset, 57 - "%d HT40 %c%c\n", 58 - chan->center_freq, 59 - (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? ' ' : '-', 60 - (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? ' ' : '+'); 55 + return scnprintf(buf + offset, 56 + buf_size - offset, 57 + "%d HT40 %c%c\n", 58 + chan->center_freq, 59 + (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? 60 + ' ' : '-', 61 + (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? 62 + ' ' : '+'); 61 63 } 62 64 63 65 static ssize_t ht40allow_map_read(struct file *file,
+6
net/wireless/genregdb.awk
··· 46 46 sub(/:/, "", country) 47 47 printf "static const struct ieee80211_regdomain regdom_%s = {\n", country 48 48 printf "\t.alpha2 = \"%s\",\n", country 49 + if ($NF ~ /DFS-ETSI/) 50 + printf "\t.dfs_region = NL80211_DFS_ETSI,\n" 51 + else if ($NF ~ /DFS-FCC/) 52 + printf "\t.dfs_region = NL80211_DFS_FCC,\n" 53 + else if ($NF ~ /DFS-JP/) 54 + printf "\t.dfs_region = NL80211_DFS_JP,\n" 49 55 printf "\t.reg_rules = {\n" 50 56 active = 1 51 57 regdb = regdb "\t&regdom_" country ",\n"
+37 -15
net/wireless/nl80211.c
··· 5591 5591 if (err) 5592 5592 return err; 5593 5593 5594 + if (netif_carrier_ok(dev)) 5595 + return -EBUSY; 5596 + 5594 5597 if (wdev->cac_started) 5595 5598 return -EBUSY; 5596 5599 ··· 5637 5634 static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; 5638 5635 u8 radar_detect_width = 0; 5639 5636 int err; 5637 + bool need_new_beacon = false; 5640 5638 5641 5639 if (!rdev->ops->channel_switch || 5642 5640 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) 5643 5641 return -EOPNOTSUPP; 5644 5642 5645 - /* may add IBSS support later */ 5646 - if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 5647 - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 5643 + switch (dev->ieee80211_ptr->iftype) { 5644 + case NL80211_IFTYPE_AP: 5645 + case NL80211_IFTYPE_P2P_GO: 5646 + need_new_beacon = true; 5647 + 5648 + /* useless if AP is not running */ 5649 + if (!wdev->beacon_interval) 5650 + return -EINVAL; 5651 + break; 5652 + case NL80211_IFTYPE_ADHOC: 5653 + break; 5654 + default: 5648 5655 return -EOPNOTSUPP; 5656 + } 5649 5657 5650 5658 memset(&params, 0, sizeof(params)); 5651 5659 ··· 5665 5651 return -EINVAL; 5666 5652 5667 5653 /* only important for AP, IBSS and mesh create IEs internally */ 5668 - if (!info->attrs[NL80211_ATTR_CSA_IES]) 5669 - return -EINVAL; 5670 - 5671 - /* useless if AP is not running */ 5672 - if (!wdev->beacon_interval) 5654 + if (need_new_beacon && 5655 + (!info->attrs[NL80211_ATTR_CSA_IES] || 5656 + !info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON])) 5673 5657 return -EINVAL; 5674 5658 5675 5659 params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); 5660 + 5661 + if (!need_new_beacon) 5662 + goto skip_beacons; 5676 5663 5677 5664 err = nl80211_parse_beacon(info->attrs, &params.beacon_after); 5678 5665 if (err) ··· 5714 5699 return -EINVAL; 5715 5700 } 5716 5701 5702 + skip_beacons: 5717 5703 err = nl80211_parse_chandef(rdev, info, &params.chandef); 5718 5704 if (err) 5719 5705 return err; ··· 5722 5706 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef)) 5723 5707 return -EINVAL; 5724 5708 5725 - err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef); 5726 - if (err < 0) { 5727 - return err; 5728 - } else if (err) { 5729 - radar_detect_width = BIT(params.chandef.width); 5730 - params.radar_required = true; 5709 + /* DFS channels are only supported for AP/P2P GO ... for now. */ 5710 + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || 5711 + dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { 5712 + err = cfg80211_chandef_dfs_required(wdev->wiphy, 5713 + &params.chandef); 5714 + if (err < 0) { 5715 + return err; 5716 + } else if (err) { 5717 + radar_detect_width = BIT(params.chandef.width); 5718 + params.radar_required = true; 5719 + } 5731 5720 } 5732 5721 5733 5722 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, ··· 10761 10740 wdev_lock(wdev); 10762 10741 10763 10742 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && 10764 - wdev->iftype != NL80211_IFTYPE_P2P_GO)) 10743 + wdev->iftype != NL80211_IFTYPE_P2P_GO && 10744 + wdev->iftype != NL80211_IFTYPE_ADHOC)) 10765 10745 goto out; 10766 10746 10767 10747 wdev->channel = chandef->chan;
+12 -2
net/wireless/reg.c
··· 172 172 NL80211_RRF_NO_IBSS | 173 173 NL80211_RRF_NO_OFDM), 174 174 /* IEEE 802.11a, channel 36..48 */ 175 - REG_RULE(5180-10, 5240+10, 80, 6, 20, 175 + REG_RULE(5180-10, 5240+10, 160, 6, 20, 176 176 NL80211_RRF_PASSIVE_SCAN | 177 177 NL80211_RRF_NO_IBSS), 178 178 179 - /* NB: 5260 MHz - 5700 MHz requires DFS */ 179 + /* IEEE 802.11a, channel 52..64 - DFS required */ 180 + REG_RULE(5260-10, 5320+10, 160, 6, 20, 181 + NL80211_RRF_PASSIVE_SCAN | 182 + NL80211_RRF_NO_IBSS | 183 + NL80211_RRF_DFS), 184 + 185 + /* IEEE 802.11a, channel 100..144 - DFS required */ 186 + REG_RULE(5500-10, 5720+10, 160, 6, 20, 187 + NL80211_RRF_PASSIVE_SCAN | 188 + NL80211_RRF_NO_IBSS | 189 + NL80211_RRF_DFS), 180 190 181 191 /* IEEE 802.11a, channel 149..165 */ 182 192 REG_RULE(5745-10, 5825+10, 80, 6, 20,
+9
net/wireless/util.c
··· 10 10 #include <net/cfg80211.h> 11 11 #include <net/ip.h> 12 12 #include <net/dsfield.h> 13 + #include <linux/if_vlan.h> 13 14 #include "core.h" 14 15 #include "rdev-ops.h" 15 16 ··· 692 691 unsigned int cfg80211_classify8021d(struct sk_buff *skb) 693 692 { 694 693 unsigned int dscp; 694 + unsigned char vlan_priority; 695 695 696 696 /* skb->priority values from 256->263 are magic values to 697 697 * directly indicate a specific 802.1d priority. This is used ··· 701 699 */ 702 700 if (skb->priority >= 256 && skb->priority <= 263) 703 701 return skb->priority - 256; 702 + 703 + if (vlan_tx_tag_present(skb)) { 704 + vlan_priority = (vlan_tx_tag_get(skb) & VLAN_PRIO_MASK) 705 + >> VLAN_PRIO_SHIFT; 706 + if (vlan_priority > 0) 707 + return vlan_priority; 708 + } 704 709 705 710 switch (skb->protocol) { 706 711 case htons(ETH_P_IP):