diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 123 |
1 files changed, 80 insertions, 43 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 95667b088c5b..754069cbb756 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -133,7 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
133 | struct key_params *params) | 133 | struct key_params *params) |
134 | { | 134 | { |
135 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 135 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
136 | struct ieee80211_local *local = sdata->local; | ||
136 | struct sta_info *sta = NULL; | 137 | struct sta_info *sta = NULL; |
138 | const struct ieee80211_cipher_scheme *cs = NULL; | ||
137 | struct ieee80211_key *key; | 139 | struct ieee80211_key *key; |
138 | int err; | 140 | int err; |
139 | 141 | ||
@@ -145,22 +147,28 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
145 | case WLAN_CIPHER_SUITE_WEP40: | 147 | case WLAN_CIPHER_SUITE_WEP40: |
146 | case WLAN_CIPHER_SUITE_TKIP: | 148 | case WLAN_CIPHER_SUITE_TKIP: |
147 | case WLAN_CIPHER_SUITE_WEP104: | 149 | case WLAN_CIPHER_SUITE_WEP104: |
148 | if (IS_ERR(sdata->local->wep_tx_tfm)) | 150 | if (IS_ERR(local->wep_tx_tfm)) |
149 | return -EINVAL; | 151 | return -EINVAL; |
150 | break; | 152 | break; |
153 | case WLAN_CIPHER_SUITE_CCMP: | ||
154 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
155 | case WLAN_CIPHER_SUITE_GCMP: | ||
156 | break; | ||
151 | default: | 157 | default: |
158 | cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type); | ||
152 | break; | 159 | break; |
153 | } | 160 | } |
154 | 161 | ||
155 | key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, | 162 | key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, |
156 | params->key, params->seq_len, params->seq); | 163 | params->key, params->seq_len, params->seq, |
164 | cs); | ||
157 | if (IS_ERR(key)) | 165 | if (IS_ERR(key)) |
158 | return PTR_ERR(key); | 166 | return PTR_ERR(key); |
159 | 167 | ||
160 | if (pairwise) | 168 | if (pairwise) |
161 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | 169 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; |
162 | 170 | ||
163 | mutex_lock(&sdata->local->sta_mtx); | 171 | mutex_lock(&local->sta_mtx); |
164 | 172 | ||
165 | if (mac_addr) { | 173 | if (mac_addr) { |
166 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 174 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
@@ -216,10 +224,13 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
216 | break; | 224 | break; |
217 | } | 225 | } |
218 | 226 | ||
227 | if (sta) | ||
228 | sta->cipher_scheme = cs; | ||
229 | |||
219 | err = ieee80211_key_link(key, sdata, sta); | 230 | err = ieee80211_key_link(key, sdata, sta); |
220 | 231 | ||
221 | out_unlock: | 232 | out_unlock: |
222 | mutex_unlock(&sdata->local->sta_mtx); | 233 | mutex_unlock(&local->sta_mtx); |
223 | 234 | ||
224 | return err; | 235 | return err; |
225 | } | 236 | } |
@@ -244,7 +255,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
244 | goto out_unlock; | 255 | goto out_unlock; |
245 | 256 | ||
246 | if (pairwise) | 257 | if (pairwise) |
247 | key = key_mtx_dereference(local, sta->ptk); | 258 | key = key_mtx_dereference(local, sta->ptk[key_idx]); |
248 | else | 259 | else |
249 | key = key_mtx_dereference(local, sta->gtk[key_idx]); | 260 | key = key_mtx_dereference(local, sta->gtk[key_idx]); |
250 | } else | 261 | } else |
@@ -291,7 +302,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
291 | goto out; | 302 | goto out; |
292 | 303 | ||
293 | if (pairwise) | 304 | if (pairwise) |
294 | key = rcu_dereference(sta->ptk); | 305 | key = rcu_dereference(sta->ptk[key_idx]); |
295 | else if (key_idx < NUM_DEFAULT_KEYS) | 306 | else if (key_idx < NUM_DEFAULT_KEYS) |
296 | key = rcu_dereference(sta->gtk[key_idx]); | 307 | key = rcu_dereference(sta->gtk[key_idx]); |
297 | } else | 308 | } else |
@@ -521,8 +532,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
521 | STATION_INFO_PEER_PM | | 532 | STATION_INFO_PEER_PM | |
522 | STATION_INFO_NONPEER_PM; | 533 | STATION_INFO_NONPEER_PM; |
523 | 534 | ||
524 | sinfo->llid = le16_to_cpu(sta->llid); | 535 | sinfo->llid = sta->llid; |
525 | sinfo->plid = le16_to_cpu(sta->plid); | 536 | sinfo->plid = sta->plid; |
526 | sinfo->plink_state = sta->plink_state; | 537 | sinfo->plink_state = sta->plink_state; |
527 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | 538 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { |
528 | sinfo->filled |= STATION_INFO_T_OFFSET; | 539 | sinfo->filled |= STATION_INFO_T_OFFSET; |
@@ -846,7 +857,7 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
846 | if (!resp || !resp_len) | 857 | if (!resp || !resp_len) |
847 | return 1; | 858 | return 1; |
848 | 859 | ||
849 | old = rtnl_dereference(sdata->u.ap.probe_resp); | 860 | old = sdata_dereference(sdata->u.ap.probe_resp, sdata); |
850 | 861 | ||
851 | new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL); | 862 | new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL); |
852 | if (!new) | 863 | if (!new) |
@@ -870,7 +881,8 @@ int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, | |||
870 | int size, err; | 881 | int size, err; |
871 | u32 changed = BSS_CHANGED_BEACON; | 882 | u32 changed = BSS_CHANGED_BEACON; |
872 | 883 | ||
873 | old = rtnl_dereference(sdata->u.ap.beacon); | 884 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
885 | |||
874 | 886 | ||
875 | /* Need to have a beacon head if we don't have one yet */ | 887 | /* Need to have a beacon head if we don't have one yet */ |
876 | if (!params->head && !old) | 888 | if (!params->head && !old) |
@@ -947,7 +959,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
947 | BSS_CHANGED_P2P_PS; | 959 | BSS_CHANGED_P2P_PS; |
948 | int err; | 960 | int err; |
949 | 961 | ||
950 | old = rtnl_dereference(sdata->u.ap.beacon); | 962 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
951 | if (old) | 963 | if (old) |
952 | return -EALREADY; | 964 | return -EALREADY; |
953 | 965 | ||
@@ -968,11 +980,19 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
968 | */ | 980 | */ |
969 | sdata->control_port_protocol = params->crypto.control_port_ethertype; | 981 | sdata->control_port_protocol = params->crypto.control_port_ethertype; |
970 | sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; | 982 | sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; |
983 | sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local, | ||
984 | ¶ms->crypto, | ||
985 | sdata->vif.type); | ||
986 | |||
971 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { | 987 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { |
972 | vlan->control_port_protocol = | 988 | vlan->control_port_protocol = |
973 | params->crypto.control_port_ethertype; | 989 | params->crypto.control_port_ethertype; |
974 | vlan->control_port_no_encrypt = | 990 | vlan->control_port_no_encrypt = |
975 | params->crypto.control_port_no_encrypt; | 991 | params->crypto.control_port_no_encrypt; |
992 | vlan->encrypt_headroom = | ||
993 | ieee80211_cs_headroom(sdata->local, | ||
994 | ¶ms->crypto, | ||
995 | vlan->vif.type); | ||
976 | } | 996 | } |
977 | 997 | ||
978 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 998 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
@@ -1001,7 +1021,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
1001 | 1021 | ||
1002 | err = drv_start_ap(sdata->local, sdata); | 1022 | err = drv_start_ap(sdata->local, sdata); |
1003 | if (err) { | 1023 | if (err) { |
1004 | old = rtnl_dereference(sdata->u.ap.beacon); | 1024 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
1025 | |||
1005 | if (old) | 1026 | if (old) |
1006 | kfree_rcu(old, rcu_head); | 1027 | kfree_rcu(old, rcu_head); |
1007 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | 1028 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
@@ -1032,7 +1053,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
1032 | if (sdata->vif.csa_active) | 1053 | if (sdata->vif.csa_active) |
1033 | return -EBUSY; | 1054 | return -EBUSY; |
1034 | 1055 | ||
1035 | old = rtnl_dereference(sdata->u.ap.beacon); | 1056 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
1036 | if (!old) | 1057 | if (!old) |
1037 | return -ENOENT; | 1058 | return -ENOENT; |
1038 | 1059 | ||
@@ -1050,15 +1071,18 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1050 | struct ieee80211_local *local = sdata->local; | 1071 | struct ieee80211_local *local = sdata->local; |
1051 | struct beacon_data *old_beacon; | 1072 | struct beacon_data *old_beacon; |
1052 | struct probe_resp *old_probe_resp; | 1073 | struct probe_resp *old_probe_resp; |
1074 | struct cfg80211_chan_def chandef; | ||
1053 | 1075 | ||
1054 | old_beacon = rtnl_dereference(sdata->u.ap.beacon); | 1076 | old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); |
1055 | if (!old_beacon) | 1077 | if (!old_beacon) |
1056 | return -ENOENT; | 1078 | return -ENOENT; |
1057 | old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp); | 1079 | old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata); |
1058 | 1080 | ||
1059 | /* abort any running channel switch */ | 1081 | /* abort any running channel switch */ |
1060 | sdata->vif.csa_active = false; | 1082 | sdata->vif.csa_active = false; |
1061 | cancel_work_sync(&sdata->csa_finalize_work); | 1083 | kfree(sdata->u.ap.next_beacon); |
1084 | sdata->u.ap.next_beacon = NULL; | ||
1085 | |||
1062 | cancel_work_sync(&sdata->u.ap.request_smps_work); | 1086 | cancel_work_sync(&sdata->u.ap.request_smps_work); |
1063 | 1087 | ||
1064 | /* turn off carrier for this interface and dependent VLANs */ | 1088 | /* turn off carrier for this interface and dependent VLANs */ |
@@ -1091,8 +1115,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1091 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 1115 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
1092 | 1116 | ||
1093 | if (sdata->wdev.cac_started) { | 1117 | if (sdata->wdev.cac_started) { |
1118 | chandef = sdata->vif.bss_conf.chandef; | ||
1094 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 1119 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
1095 | cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, | 1120 | cfg80211_cac_event(sdata->dev, &chandef, |
1121 | NL80211_RADAR_CAC_ABORTED, | ||
1096 | GFP_KERNEL); | 1122 | GFP_KERNEL); |
1097 | } | 1123 | } |
1098 | 1124 | ||
@@ -1953,7 +1979,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1953 | enum ieee80211_band band; | 1979 | enum ieee80211_band band; |
1954 | u32 changed = 0; | 1980 | u32 changed = 0; |
1955 | 1981 | ||
1956 | if (!rtnl_dereference(sdata->u.ap.beacon)) | 1982 | if (!sdata_dereference(sdata->u.ap.beacon, sdata)) |
1957 | return -ENOENT; | 1983 | return -ENOENT; |
1958 | 1984 | ||
1959 | band = ieee80211_get_sdata_band(sdata); | 1985 | band = ieee80211_get_sdata_band(sdata); |
@@ -2964,27 +2990,33 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
2964 | struct ieee80211_local *local = sdata->local; | 2990 | struct ieee80211_local *local = sdata->local; |
2965 | int err, changed = 0; | 2991 | int err, changed = 0; |
2966 | 2992 | ||
2993 | sdata_lock(sdata); | ||
2994 | /* AP might have been stopped while waiting for the lock. */ | ||
2995 | if (!sdata->vif.csa_active) | ||
2996 | goto unlock; | ||
2997 | |||
2967 | if (!ieee80211_sdata_running(sdata)) | 2998 | if (!ieee80211_sdata_running(sdata)) |
2968 | return; | 2999 | goto unlock; |
2969 | 3000 | ||
2970 | sdata->radar_required = sdata->csa_radar_required; | 3001 | sdata->radar_required = sdata->csa_radar_required; |
2971 | err = ieee80211_vif_change_channel(sdata, &local->csa_chandef, | 3002 | err = ieee80211_vif_change_channel(sdata, &changed); |
2972 | &changed); | ||
2973 | if (WARN_ON(err < 0)) | 3003 | if (WARN_ON(err < 0)) |
2974 | return; | 3004 | goto unlock; |
2975 | 3005 | ||
2976 | if (!local->use_chanctx) { | 3006 | if (!local->use_chanctx) { |
2977 | local->_oper_chandef = local->csa_chandef; | 3007 | local->_oper_chandef = sdata->csa_chandef; |
2978 | ieee80211_hw_config(local, 0); | 3008 | ieee80211_hw_config(local, 0); |
2979 | } | 3009 | } |
2980 | 3010 | ||
2981 | ieee80211_bss_info_change_notify(sdata, changed); | 3011 | ieee80211_bss_info_change_notify(sdata, changed); |
2982 | 3012 | ||
3013 | sdata->vif.csa_active = false; | ||
2983 | switch (sdata->vif.type) { | 3014 | switch (sdata->vif.type) { |
2984 | case NL80211_IFTYPE_AP: | 3015 | case NL80211_IFTYPE_AP: |
2985 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); | 3016 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); |
2986 | if (err < 0) | 3017 | if (err < 0) |
2987 | return; | 3018 | goto unlock; |
3019 | |||
2988 | changed |= err; | 3020 | changed |= err; |
2989 | kfree(sdata->u.ap.next_beacon); | 3021 | kfree(sdata->u.ap.next_beacon); |
2990 | sdata->u.ap.next_beacon = NULL; | 3022 | sdata->u.ap.next_beacon = NULL; |
@@ -2998,20 +3030,22 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
2998 | case NL80211_IFTYPE_MESH_POINT: | 3030 | case NL80211_IFTYPE_MESH_POINT: |
2999 | err = ieee80211_mesh_finish_csa(sdata); | 3031 | err = ieee80211_mesh_finish_csa(sdata); |
3000 | if (err < 0) | 3032 | if (err < 0) |
3001 | return; | 3033 | goto unlock; |
3002 | break; | 3034 | break; |
3003 | #endif | 3035 | #endif |
3004 | default: | 3036 | default: |
3005 | WARN_ON(1); | 3037 | WARN_ON(1); |
3006 | return; | 3038 | goto unlock; |
3007 | } | 3039 | } |
3008 | sdata->vif.csa_active = false; | ||
3009 | 3040 | ||
3010 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 3041 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
3011 | IEEE80211_MAX_QUEUE_MAP, | 3042 | IEEE80211_MAX_QUEUE_MAP, |
3012 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3043 | IEEE80211_QUEUE_STOP_REASON_CSA); |
3013 | 3044 | ||
3014 | cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef); | 3045 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); |
3046 | |||
3047 | unlock: | ||
3048 | sdata_unlock(sdata); | ||
3015 | } | 3049 | } |
3016 | 3050 | ||
3017 | static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3051 | static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, |
@@ -3024,6 +3058,8 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3024 | struct ieee80211_if_mesh __maybe_unused *ifmsh; | 3058 | struct ieee80211_if_mesh __maybe_unused *ifmsh; |
3025 | int err, num_chanctx; | 3059 | int err, num_chanctx; |
3026 | 3060 | ||
3061 | lockdep_assert_held(&sdata->wdev.mtx); | ||
3062 | |||
3027 | if (!list_empty(&local->roc_list) || local->scanning) | 3063 | if (!list_empty(&local->roc_list) || local->scanning) |
3028 | return -EBUSY; | 3064 | return -EBUSY; |
3029 | 3065 | ||
@@ -3136,7 +3172,7 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3136 | IEEE80211_MAX_QUEUE_MAP, | 3172 | IEEE80211_MAX_QUEUE_MAP, |
3137 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3173 | IEEE80211_QUEUE_STOP_REASON_CSA); |
3138 | 3174 | ||
3139 | local->csa_chandef = params->chandef; | 3175 | sdata->csa_chandef = params->chandef; |
3140 | sdata->vif.csa_active = true; | 3176 | sdata->vif.csa_active = true; |
3141 | 3177 | ||
3142 | ieee80211_bss_info_change_notify(sdata, err); | 3178 | ieee80211_bss_info_change_notify(sdata, err); |
@@ -3146,26 +3182,25 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3146 | } | 3182 | } |
3147 | 3183 | ||
3148 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 3184 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
3149 | struct ieee80211_channel *chan, bool offchan, | 3185 | struct cfg80211_mgmt_tx_params *params, |
3150 | unsigned int wait, const u8 *buf, size_t len, | 3186 | u64 *cookie) |
3151 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) | ||
3152 | { | 3187 | { |
3153 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | 3188 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
3154 | struct ieee80211_local *local = sdata->local; | 3189 | struct ieee80211_local *local = sdata->local; |
3155 | struct sk_buff *skb; | 3190 | struct sk_buff *skb; |
3156 | struct sta_info *sta; | 3191 | struct sta_info *sta; |
3157 | const struct ieee80211_mgmt *mgmt = (void *)buf; | 3192 | const struct ieee80211_mgmt *mgmt = (void *)params->buf; |
3158 | bool need_offchan = false; | 3193 | bool need_offchan = false; |
3159 | u32 flags; | 3194 | u32 flags; |
3160 | int ret; | 3195 | int ret; |
3161 | 3196 | ||
3162 | if (dont_wait_for_ack) | 3197 | if (params->dont_wait_for_ack) |
3163 | flags = IEEE80211_TX_CTL_NO_ACK; | 3198 | flags = IEEE80211_TX_CTL_NO_ACK; |
3164 | else | 3199 | else |
3165 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | 3200 | flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | |
3166 | IEEE80211_TX_CTL_REQ_TX_STATUS; | 3201 | IEEE80211_TX_CTL_REQ_TX_STATUS; |
3167 | 3202 | ||
3168 | if (no_cck) | 3203 | if (params->no_cck) |
3169 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | 3204 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; |
3170 | 3205 | ||
3171 | switch (sdata->vif.type) { | 3206 | switch (sdata->vif.type) { |
@@ -3213,7 +3248,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3213 | /* configurations requiring offchan cannot work if no channel has been | 3248 | /* configurations requiring offchan cannot work if no channel has been |
3214 | * specified | 3249 | * specified |
3215 | */ | 3250 | */ |
3216 | if (need_offchan && !chan) | 3251 | if (need_offchan && !params->chan) |
3217 | return -EINVAL; | 3252 | return -EINVAL; |
3218 | 3253 | ||
3219 | mutex_lock(&local->mtx); | 3254 | mutex_lock(&local->mtx); |
@@ -3226,8 +3261,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3226 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 3261 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
3227 | 3262 | ||
3228 | if (chanctx_conf) { | 3263 | if (chanctx_conf) { |
3229 | need_offchan = chan && (chan != chanctx_conf->def.chan); | 3264 | need_offchan = params->chan && |
3230 | } else if (!chan) { | 3265 | (params->chan != |
3266 | chanctx_conf->def.chan); | ||
3267 | } else if (!params->chan) { | ||
3231 | ret = -EINVAL; | 3268 | ret = -EINVAL; |
3232 | rcu_read_unlock(); | 3269 | rcu_read_unlock(); |
3233 | goto out_unlock; | 3270 | goto out_unlock; |
@@ -3237,19 +3274,19 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3237 | rcu_read_unlock(); | 3274 | rcu_read_unlock(); |
3238 | } | 3275 | } |
3239 | 3276 | ||
3240 | if (need_offchan && !offchan) { | 3277 | if (need_offchan && !params->offchan) { |
3241 | ret = -EBUSY; | 3278 | ret = -EBUSY; |
3242 | goto out_unlock; | 3279 | goto out_unlock; |
3243 | } | 3280 | } |
3244 | 3281 | ||
3245 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | 3282 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + params->len); |
3246 | if (!skb) { | 3283 | if (!skb) { |
3247 | ret = -ENOMEM; | 3284 | ret = -ENOMEM; |
3248 | goto out_unlock; | 3285 | goto out_unlock; |
3249 | } | 3286 | } |
3250 | skb_reserve(skb, local->hw.extra_tx_headroom); | 3287 | skb_reserve(skb, local->hw.extra_tx_headroom); |
3251 | 3288 | ||
3252 | memcpy(skb_put(skb, len), buf, len); | 3289 | memcpy(skb_put(skb, params->len), params->buf, params->len); |
3253 | 3290 | ||
3254 | IEEE80211_SKB_CB(skb)->flags = flags; | 3291 | IEEE80211_SKB_CB(skb)->flags = flags; |
3255 | 3292 | ||
@@ -3269,8 +3306,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3269 | local->hw.offchannel_tx_hw_queue; | 3306 | local->hw.offchannel_tx_hw_queue; |
3270 | 3307 | ||
3271 | /* This will handle all kinds of coalescing and immediate TX */ | 3308 | /* This will handle all kinds of coalescing and immediate TX */ |
3272 | ret = ieee80211_start_roc_work(local, sdata, chan, | 3309 | ret = ieee80211_start_roc_work(local, sdata, params->chan, |
3273 | wait, cookie, skb, | 3310 | params->wait, cookie, skb, |
3274 | IEEE80211_ROC_TYPE_MGMT_TX); | 3311 | IEEE80211_ROC_TYPE_MGMT_TX); |
3275 | if (ret) | 3312 | if (ret) |
3276 | kfree_skb(skb); | 3313 | kfree_skb(skb); |