diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-08-16 14:24:51 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-08-16 14:24:51 -0400 |
commit | d0746663667f37e7be5646bf68cb452c8375a23d (patch) | |
tree | 85ae5a3d5e5bae53815baba5dba372e4d53a9745 /net | |
parent | 41caa760d6acaf47cbd44c3d78307fb9be089111 (diff) | |
parent | 27b3eb9c06a7193bdc9800cd00764a130343bc8a (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 15 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 196 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/key.c | 154 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 9 | ||||
-rw-r--r-- | net/mac80211/rate.c | 23 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 5 | ||||
-rw-r--r-- | net/mac80211/rx.c | 404 | ||||
-rw-r--r-- | net/mac80211/tx.c | 8 | ||||
-rw-r--r-- | net/mac80211/util.c | 2 | ||||
-rw-r--r-- | net/rfkill/rfkill-regulator.c | 8 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 74 | ||||
-rw-r--r-- | net/wireless/rdev-ops.h | 5 | ||||
-rw-r--r-- | net/wireless/trace.h | 8 |
14 files changed, 570 insertions, 344 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 31fc2247bc37..2e7855a1b10d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2302,14 +2302,25 @@ static void ieee80211_rfkill_poll(struct wiphy *wiphy) | |||
2302 | } | 2302 | } |
2303 | 2303 | ||
2304 | #ifdef CONFIG_NL80211_TESTMODE | 2304 | #ifdef CONFIG_NL80211_TESTMODE |
2305 | static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) | 2305 | static int ieee80211_testmode_cmd(struct wiphy *wiphy, |
2306 | struct wireless_dev *wdev, | ||
2307 | void *data, int len) | ||
2306 | { | 2308 | { |
2307 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2309 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2310 | struct ieee80211_vif *vif = NULL; | ||
2308 | 2311 | ||
2309 | if (!local->ops->testmode_cmd) | 2312 | if (!local->ops->testmode_cmd) |
2310 | return -EOPNOTSUPP; | 2313 | return -EOPNOTSUPP; |
2311 | 2314 | ||
2312 | return local->ops->testmode_cmd(&local->hw, data, len); | 2315 | if (wdev) { |
2316 | struct ieee80211_sub_if_data *sdata; | ||
2317 | |||
2318 | sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
2319 | if (sdata->flags & IEEE80211_SDATA_IN_DRIVER) | ||
2320 | vif = &sdata->vif; | ||
2321 | } | ||
2322 | |||
2323 | return local->ops->testmode_cmd(&local->hw, vif, data, len); | ||
2313 | } | 2324 | } |
2314 | 2325 | ||
2315 | static int ieee80211_testmode_dump(struct wiphy *wiphy, | 2326 | static int ieee80211_testmode_dump(struct wiphy *wiphy, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index e08387cdc8fd..74de0f10558a 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -34,13 +34,12 @@ | |||
34 | 34 | ||
35 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 | 35 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 |
36 | 36 | ||
37 | 37 | static struct beacon_data * | |
38 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 38 | ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, |
39 | const u8 *bssid, const int beacon_int, | 39 | const int beacon_int, const u32 basic_rates, |
40 | struct ieee80211_channel *chan, | 40 | const u16 capability, u64 tsf, |
41 | const u32 basic_rates, | 41 | struct cfg80211_chan_def *chandef, |
42 | const u16 capability, u64 tsf, | 42 | bool *have_higher_than_11mbit) |
43 | bool creator) | ||
44 | { | 43 | { |
45 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 44 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
46 | struct ieee80211_local *local = sdata->local; | 45 | struct ieee80211_local *local = sdata->local; |
@@ -48,70 +47,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
48 | struct ieee80211_mgmt *mgmt; | 47 | struct ieee80211_mgmt *mgmt; |
49 | u8 *pos; | 48 | u8 *pos; |
50 | struct ieee80211_supported_band *sband; | 49 | struct ieee80211_supported_band *sband; |
51 | struct cfg80211_bss *bss; | 50 | u32 rate_flags, rates = 0, rates_added = 0; |
52 | u32 bss_change, rate_flags, rates = 0, rates_added = 0; | ||
53 | struct cfg80211_chan_def chandef; | ||
54 | enum nl80211_bss_scan_width scan_width; | ||
55 | bool have_higher_than_11mbit = false; | ||
56 | struct beacon_data *presp; | 51 | struct beacon_data *presp; |
57 | int frame_len; | 52 | int frame_len; |
58 | int shift; | 53 | int shift; |
59 | 54 | ||
60 | sdata_assert_lock(sdata); | ||
61 | |||
62 | /* Reset own TSF to allow time synchronization work. */ | ||
63 | drv_reset_tsf(local, sdata); | ||
64 | |||
65 | if (!ether_addr_equal(ifibss->bssid, bssid)) | ||
66 | sta_info_flush(sdata); | ||
67 | |||
68 | /* if merging, indicate to driver that we leave the old IBSS */ | ||
69 | if (sdata->vif.bss_conf.ibss_joined) { | ||
70 | sdata->vif.bss_conf.ibss_joined = false; | ||
71 | sdata->vif.bss_conf.ibss_creator = false; | ||
72 | sdata->vif.bss_conf.enable_beacon = false; | ||
73 | netif_carrier_off(sdata->dev); | ||
74 | ieee80211_bss_info_change_notify(sdata, | ||
75 | BSS_CHANGED_IBSS | | ||
76 | BSS_CHANGED_BEACON_ENABLED); | ||
77 | } | ||
78 | |||
79 | presp = rcu_dereference_protected(ifibss->presp, | ||
80 | lockdep_is_held(&sdata->wdev.mtx)); | ||
81 | rcu_assign_pointer(ifibss->presp, NULL); | ||
82 | if (presp) | ||
83 | kfree_rcu(presp, rcu_head); | ||
84 | |||
85 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | ||
86 | |||
87 | chandef = ifibss->chandef; | ||
88 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { | ||
89 | if (chandef.width == NL80211_CHAN_WIDTH_5 || | ||
90 | chandef.width == NL80211_CHAN_WIDTH_10 || | ||
91 | chandef.width == NL80211_CHAN_WIDTH_20_NOHT || | ||
92 | chandef.width == NL80211_CHAN_WIDTH_20) { | ||
93 | sdata_info(sdata, | ||
94 | "Failed to join IBSS, beacons forbidden\n"); | ||
95 | return; | ||
96 | } | ||
97 | chandef.width = NL80211_CHAN_WIDTH_20; | ||
98 | chandef.center_freq1 = chan->center_freq; | ||
99 | } | ||
100 | |||
101 | ieee80211_vif_release_channel(sdata); | ||
102 | if (ieee80211_vif_use_channel(sdata, &chandef, | ||
103 | ifibss->fixed_channel ? | ||
104 | IEEE80211_CHANCTX_SHARED : | ||
105 | IEEE80211_CHANCTX_EXCLUSIVE)) { | ||
106 | sdata_info(sdata, "Failed to join IBSS, no channel context\n"); | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | ||
111 | |||
112 | sband = local->hw.wiphy->bands[chan->band]; | ||
113 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
114 | |||
115 | /* Build IBSS probe response */ | 55 | /* Build IBSS probe response */ |
116 | frame_len = sizeof(struct ieee80211_hdr_3addr) + | 56 | frame_len = sizeof(struct ieee80211_hdr_3addr) + |
117 | 12 /* struct ieee80211_mgmt.u.beacon */ + | 57 | 12 /* struct ieee80211_mgmt.u.beacon */ + |
@@ -125,7 +65,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
125 | ifibss->ie_len; | 65 | ifibss->ie_len; |
126 | presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL); | 66 | presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL); |
127 | if (!presp) | 67 | if (!presp) |
128 | return; | 68 | return NULL; |
129 | 69 | ||
130 | presp->head = (void *)(presp + 1); | 70 | presp->head = (void *)(presp + 1); |
131 | 71 | ||
@@ -146,12 +86,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
146 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); | 86 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); |
147 | pos += ifibss->ssid_len; | 87 | pos += ifibss->ssid_len; |
148 | 88 | ||
149 | rate_flags = ieee80211_chandef_rate_flags(&chandef); | 89 | sband = local->hw.wiphy->bands[chandef->chan->band]; |
90 | rate_flags = ieee80211_chandef_rate_flags(chandef); | ||
91 | shift = ieee80211_chandef_get_shift(chandef); | ||
92 | rates_n = 0; | ||
93 | if (have_higher_than_11mbit) | ||
94 | *have_higher_than_11mbit = false; | ||
95 | |||
150 | for (i = 0; i < sband->n_bitrates; i++) { | 96 | for (i = 0; i < sband->n_bitrates; i++) { |
151 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | 97 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) |
152 | continue; | 98 | continue; |
153 | if (sband->bitrates[i].bitrate > 110) | 99 | if (sband->bitrates[i].bitrate > 110 && |
154 | have_higher_than_11mbit = true; | 100 | have_higher_than_11mbit) |
101 | *have_higher_than_11mbit = true; | ||
155 | 102 | ||
156 | rates |= BIT(i); | 103 | rates |= BIT(i); |
157 | rates_n++; | 104 | rates_n++; |
@@ -178,7 +125,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
178 | if (sband->band == IEEE80211_BAND_2GHZ) { | 125 | if (sband->band == IEEE80211_BAND_2GHZ) { |
179 | *pos++ = WLAN_EID_DS_PARAMS; | 126 | *pos++ = WLAN_EID_DS_PARAMS; |
180 | *pos++ = 1; | 127 | *pos++ = 1; |
181 | *pos++ = ieee80211_frequency_to_channel(chan->center_freq); | 128 | *pos++ = ieee80211_frequency_to_channel( |
129 | chandef->chan->center_freq); | ||
182 | } | 130 | } |
183 | 131 | ||
184 | *pos++ = WLAN_EID_IBSS_PARAMS; | 132 | *pos++ = WLAN_EID_IBSS_PARAMS; |
@@ -210,9 +158,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
210 | } | 158 | } |
211 | 159 | ||
212 | /* add HT capability and information IEs */ | 160 | /* add HT capability and information IEs */ |
213 | if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && | 161 | if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT && |
214 | chandef.width != NL80211_CHAN_WIDTH_5 && | 162 | chandef->width != NL80211_CHAN_WIDTH_5 && |
215 | chandef.width != NL80211_CHAN_WIDTH_10 && | 163 | chandef->width != NL80211_CHAN_WIDTH_10 && |
216 | sband->ht_cap.ht_supported) { | 164 | sband->ht_cap.ht_supported) { |
217 | struct ieee80211_sta_ht_cap ht_cap; | 165 | struct ieee80211_sta_ht_cap ht_cap; |
218 | 166 | ||
@@ -226,7 +174,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
226 | * keep them at 0 | 174 | * keep them at 0 |
227 | */ | 175 | */ |
228 | pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, | 176 | pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, |
229 | &chandef, 0); | 177 | chandef, 0); |
230 | } | 178 | } |
231 | 179 | ||
232 | if (local->hw.queues >= IEEE80211_NUM_ACS) { | 180 | if (local->hw.queues >= IEEE80211_NUM_ACS) { |
@@ -243,9 +191,94 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
243 | 191 | ||
244 | presp->head_len = pos - presp->head; | 192 | presp->head_len = pos - presp->head; |
245 | if (WARN_ON(presp->head_len > frame_len)) | 193 | if (WARN_ON(presp->head_len > frame_len)) |
194 | goto error; | ||
195 | |||
196 | return presp; | ||
197 | error: | ||
198 | kfree(presp); | ||
199 | return NULL; | ||
200 | } | ||
201 | |||
202 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | ||
203 | const u8 *bssid, const int beacon_int, | ||
204 | struct ieee80211_channel *chan, | ||
205 | const u32 basic_rates, | ||
206 | const u16 capability, u64 tsf, | ||
207 | bool creator) | ||
208 | { | ||
209 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
210 | struct ieee80211_local *local = sdata->local; | ||
211 | struct ieee80211_supported_band *sband; | ||
212 | struct ieee80211_mgmt *mgmt; | ||
213 | struct cfg80211_bss *bss; | ||
214 | u32 bss_change; | ||
215 | struct cfg80211_chan_def chandef; | ||
216 | struct beacon_data *presp; | ||
217 | enum nl80211_bss_scan_width scan_width; | ||
218 | bool have_higher_than_11mbit; | ||
219 | |||
220 | sdata_assert_lock(sdata); | ||
221 | |||
222 | /* Reset own TSF to allow time synchronization work. */ | ||
223 | drv_reset_tsf(local, sdata); | ||
224 | |||
225 | if (!ether_addr_equal(ifibss->bssid, bssid)) | ||
226 | sta_info_flush(sdata); | ||
227 | |||
228 | /* if merging, indicate to driver that we leave the old IBSS */ | ||
229 | if (sdata->vif.bss_conf.ibss_joined) { | ||
230 | sdata->vif.bss_conf.ibss_joined = false; | ||
231 | sdata->vif.bss_conf.ibss_creator = false; | ||
232 | sdata->vif.bss_conf.enable_beacon = false; | ||
233 | netif_carrier_off(sdata->dev); | ||
234 | ieee80211_bss_info_change_notify(sdata, | ||
235 | BSS_CHANGED_IBSS | | ||
236 | BSS_CHANGED_BEACON_ENABLED); | ||
237 | } | ||
238 | |||
239 | presp = rcu_dereference_protected(ifibss->presp, | ||
240 | lockdep_is_held(&sdata->wdev.mtx)); | ||
241 | rcu_assign_pointer(ifibss->presp, NULL); | ||
242 | if (presp) | ||
243 | kfree_rcu(presp, rcu_head); | ||
244 | |||
245 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | ||
246 | |||
247 | chandef = ifibss->chandef; | ||
248 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { | ||
249 | if (chandef.width == NL80211_CHAN_WIDTH_5 || | ||
250 | chandef.width == NL80211_CHAN_WIDTH_10 || | ||
251 | chandef.width == NL80211_CHAN_WIDTH_20_NOHT || | ||
252 | chandef.width == NL80211_CHAN_WIDTH_20) { | ||
253 | sdata_info(sdata, | ||
254 | "Failed to join IBSS, beacons forbidden\n"); | ||
255 | return; | ||
256 | } | ||
257 | chandef.width = NL80211_CHAN_WIDTH_20; | ||
258 | chandef.center_freq1 = chan->center_freq; | ||
259 | } | ||
260 | |||
261 | ieee80211_vif_release_channel(sdata); | ||
262 | if (ieee80211_vif_use_channel(sdata, &chandef, | ||
263 | ifibss->fixed_channel ? | ||
264 | IEEE80211_CHANCTX_SHARED : | ||
265 | IEEE80211_CHANCTX_EXCLUSIVE)) { | ||
266 | sdata_info(sdata, "Failed to join IBSS, no channel context\n"); | ||
267 | return; | ||
268 | } | ||
269 | |||
270 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | ||
271 | |||
272 | sband = local->hw.wiphy->bands[chan->band]; | ||
273 | |||
274 | presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, | ||
275 | capability, tsf, &chandef, | ||
276 | &have_higher_than_11mbit); | ||
277 | if (!presp) | ||
246 | return; | 278 | return; |
247 | 279 | ||
248 | rcu_assign_pointer(ifibss->presp, presp); | 280 | rcu_assign_pointer(ifibss->presp, presp); |
281 | mgmt = (void *)presp->head; | ||
249 | 282 | ||
250 | sdata->vif.bss_conf.enable_beacon = true; | 283 | sdata->vif.bss_conf.enable_beacon = true; |
251 | sdata->vif.bss_conf.beacon_int = beacon_int; | 284 | sdata->vif.bss_conf.beacon_int = beacon_int; |
@@ -891,6 +924,17 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
891 | return; | 924 | return; |
892 | } | 925 | } |
893 | 926 | ||
927 | /* if a fixed bssid and a fixed freq have been provided create the IBSS | ||
928 | * directly and do not waste time scanning | ||
929 | */ | ||
930 | if (ifibss->fixed_bssid && ifibss->fixed_channel) { | ||
931 | sdata_info(sdata, "Created IBSS using preconfigured BSSID %pM\n", | ||
932 | bssid); | ||
933 | ieee80211_sta_create_ibss(sdata); | ||
934 | return; | ||
935 | } | ||
936 | |||
937 | |||
894 | ibss_dbg(sdata, "sta_find_ibss: did not try to join ibss\n"); | 938 | ibss_dbg(sdata, "sta_find_ibss: did not try to join ibss\n"); |
895 | 939 | ||
896 | /* Selected IBSS not found in current scan results - try to scan */ | 940 | /* Selected IBSS not found in current scan results - try to scan */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e94c84050e9c..b6186517ec56 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -53,9 +53,6 @@ struct ieee80211_local; | |||
53 | * increased memory use (about 2 kB of RAM per entry). */ | 53 | * increased memory use (about 2 kB of RAM per entry). */ |
54 | #define IEEE80211_FRAGMENT_MAX 4 | 54 | #define IEEE80211_FRAGMENT_MAX 4 |
55 | 55 | ||
56 | #define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024)) | ||
57 | #define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x)) | ||
58 | |||
59 | /* power level hasn't been configured (or set to automatic) */ | 56 | /* power level hasn't been configured (or set to automatic) */ |
60 | #define IEEE80211_UNSET_POWER_LEVEL INT_MIN | 57 | #define IEEE80211_UNSET_POWER_LEVEL INT_MIN |
61 | 58 | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index e39cc91d0cf1..620677e897bd 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -93,6 +93,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
93 | 93 | ||
94 | might_sleep(); | 94 | might_sleep(); |
95 | 95 | ||
96 | if (key->flags & KEY_FLAG_TAINTED) | ||
97 | return -EINVAL; | ||
98 | |||
96 | if (!key->local->ops->set_key) | 99 | if (!key->local->ops->set_key) |
97 | goto out_unsupported; | 100 | goto out_unsupported; |
98 | 101 | ||
@@ -455,6 +458,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
455 | struct ieee80211_sub_if_data *sdata, | 458 | struct ieee80211_sub_if_data *sdata, |
456 | struct sta_info *sta) | 459 | struct sta_info *sta) |
457 | { | 460 | { |
461 | struct ieee80211_local *local = sdata->local; | ||
458 | struct ieee80211_key *old_key; | 462 | struct ieee80211_key *old_key; |
459 | int idx, ret; | 463 | int idx, ret; |
460 | bool pairwise; | 464 | bool pairwise; |
@@ -484,10 +488,13 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
484 | 488 | ||
485 | ieee80211_debugfs_key_add(key); | 489 | ieee80211_debugfs_key_add(key); |
486 | 490 | ||
487 | ret = ieee80211_key_enable_hw_accel(key); | 491 | if (!local->wowlan) { |
488 | 492 | ret = ieee80211_key_enable_hw_accel(key); | |
489 | if (ret) | 493 | if (ret) |
490 | ieee80211_key_free(key, true); | 494 | ieee80211_key_free(key, true); |
495 | } else { | ||
496 | ret = 0; | ||
497 | } | ||
491 | 498 | ||
492 | mutex_unlock(&sdata->local->key_mtx); | 499 | mutex_unlock(&sdata->local->key_mtx); |
493 | 500 | ||
@@ -540,7 +547,7 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, | |||
540 | void *iter_data) | 547 | void *iter_data) |
541 | { | 548 | { |
542 | struct ieee80211_local *local = hw_to_local(hw); | 549 | struct ieee80211_local *local = hw_to_local(hw); |
543 | struct ieee80211_key *key; | 550 | struct ieee80211_key *key, *tmp; |
544 | struct ieee80211_sub_if_data *sdata; | 551 | struct ieee80211_sub_if_data *sdata; |
545 | 552 | ||
546 | ASSERT_RTNL(); | 553 | ASSERT_RTNL(); |
@@ -548,13 +555,14 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, | |||
548 | mutex_lock(&local->key_mtx); | 555 | mutex_lock(&local->key_mtx); |
549 | if (vif) { | 556 | if (vif) { |
550 | sdata = vif_to_sdata(vif); | 557 | sdata = vif_to_sdata(vif); |
551 | list_for_each_entry(key, &sdata->key_list, list) | 558 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
552 | iter(hw, &sdata->vif, | 559 | iter(hw, &sdata->vif, |
553 | key->sta ? &key->sta->sta : NULL, | 560 | key->sta ? &key->sta->sta : NULL, |
554 | &key->conf, iter_data); | 561 | &key->conf, iter_data); |
555 | } else { | 562 | } else { |
556 | list_for_each_entry(sdata, &local->interfaces, list) | 563 | list_for_each_entry(sdata, &local->interfaces, list) |
557 | list_for_each_entry(key, &sdata->key_list, list) | 564 | list_for_each_entry_safe(key, tmp, |
565 | &sdata->key_list, list) | ||
558 | iter(hw, &sdata->vif, | 566 | iter(hw, &sdata->vif, |
559 | key->sta ? &key->sta->sta : NULL, | 567 | key->sta ? &key->sta->sta : NULL, |
560 | &key->conf, iter_data); | 568 | &key->conf, iter_data); |
@@ -751,3 +759,135 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf, | |||
751 | } | 759 | } |
752 | } | 760 | } |
753 | EXPORT_SYMBOL(ieee80211_get_key_rx_seq); | 761 | EXPORT_SYMBOL(ieee80211_get_key_rx_seq); |
762 | |||
763 | void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf, | ||
764 | struct ieee80211_key_seq *seq) | ||
765 | { | ||
766 | struct ieee80211_key *key; | ||
767 | u64 pn64; | ||
768 | |||
769 | key = container_of(keyconf, struct ieee80211_key, conf); | ||
770 | |||
771 | switch (key->conf.cipher) { | ||
772 | case WLAN_CIPHER_SUITE_TKIP: | ||
773 | key->u.tkip.tx.iv32 = seq->tkip.iv32; | ||
774 | key->u.tkip.tx.iv16 = seq->tkip.iv16; | ||
775 | break; | ||
776 | case WLAN_CIPHER_SUITE_CCMP: | ||
777 | pn64 = (u64)seq->ccmp.pn[5] | | ||
778 | ((u64)seq->ccmp.pn[4] << 8) | | ||
779 | ((u64)seq->ccmp.pn[3] << 16) | | ||
780 | ((u64)seq->ccmp.pn[2] << 24) | | ||
781 | ((u64)seq->ccmp.pn[1] << 32) | | ||
782 | ((u64)seq->ccmp.pn[0] << 40); | ||
783 | atomic64_set(&key->u.ccmp.tx_pn, pn64); | ||
784 | break; | ||
785 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
786 | pn64 = (u64)seq->aes_cmac.pn[5] | | ||
787 | ((u64)seq->aes_cmac.pn[4] << 8) | | ||
788 | ((u64)seq->aes_cmac.pn[3] << 16) | | ||
789 | ((u64)seq->aes_cmac.pn[2] << 24) | | ||
790 | ((u64)seq->aes_cmac.pn[1] << 32) | | ||
791 | ((u64)seq->aes_cmac.pn[0] << 40); | ||
792 | atomic64_set(&key->u.aes_cmac.tx_pn, pn64); | ||
793 | break; | ||
794 | default: | ||
795 | WARN_ON(1); | ||
796 | break; | ||
797 | } | ||
798 | } | ||
799 | EXPORT_SYMBOL_GPL(ieee80211_set_key_tx_seq); | ||
800 | |||
801 | void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf, | ||
802 | int tid, struct ieee80211_key_seq *seq) | ||
803 | { | ||
804 | struct ieee80211_key *key; | ||
805 | u8 *pn; | ||
806 | |||
807 | key = container_of(keyconf, struct ieee80211_key, conf); | ||
808 | |||
809 | switch (key->conf.cipher) { | ||
810 | case WLAN_CIPHER_SUITE_TKIP: | ||
811 | if (WARN_ON(tid < 0 || tid >= IEEE80211_NUM_TIDS)) | ||
812 | return; | ||
813 | key->u.tkip.rx[tid].iv32 = seq->tkip.iv32; | ||
814 | key->u.tkip.rx[tid].iv16 = seq->tkip.iv16; | ||
815 | break; | ||
816 | case WLAN_CIPHER_SUITE_CCMP: | ||
817 | if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) | ||
818 | return; | ||
819 | if (tid < 0) | ||
820 | pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS]; | ||
821 | else | ||
822 | pn = key->u.ccmp.rx_pn[tid]; | ||
823 | memcpy(pn, seq->ccmp.pn, IEEE80211_CCMP_PN_LEN); | ||
824 | break; | ||
825 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
826 | if (WARN_ON(tid != 0)) | ||
827 | return; | ||
828 | pn = key->u.aes_cmac.rx_pn; | ||
829 | memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN); | ||
830 | break; | ||
831 | default: | ||
832 | WARN_ON(1); | ||
833 | break; | ||
834 | } | ||
835 | } | ||
836 | EXPORT_SYMBOL_GPL(ieee80211_set_key_rx_seq); | ||
837 | |||
838 | void ieee80211_remove_key(struct ieee80211_key_conf *keyconf) | ||
839 | { | ||
840 | struct ieee80211_key *key; | ||
841 | |||
842 | key = container_of(keyconf, struct ieee80211_key, conf); | ||
843 | |||
844 | assert_key_lock(key->local); | ||
845 | |||
846 | /* | ||
847 | * if key was uploaded, we assume the driver will/has remove(d) | ||
848 | * it, so adjust bookkeeping accordingly | ||
849 | */ | ||
850 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | ||
851 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | ||
852 | |||
853 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || | ||
854 | (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) || | ||
855 | (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) | ||
856 | increment_tailroom_need_count(key->sdata); | ||
857 | } | ||
858 | |||
859 | ieee80211_key_free(key, false); | ||
860 | } | ||
861 | EXPORT_SYMBOL_GPL(ieee80211_remove_key); | ||
862 | |||
863 | struct ieee80211_key_conf * | ||
864 | ieee80211_gtk_rekey_add(struct ieee80211_vif *vif, | ||
865 | struct ieee80211_key_conf *keyconf) | ||
866 | { | ||
867 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
868 | struct ieee80211_local *local = sdata->local; | ||
869 | struct ieee80211_key *key; | ||
870 | int err; | ||
871 | |||
872 | if (WARN_ON(!local->wowlan)) | ||
873 | return ERR_PTR(-EINVAL); | ||
874 | |||
875 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | ||
876 | return ERR_PTR(-EINVAL); | ||
877 | |||
878 | key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx, | ||
879 | keyconf->keylen, keyconf->key, | ||
880 | 0, NULL); | ||
881 | if (IS_ERR(key)) | ||
882 | return ERR_PTR(PTR_ERR(key)); | ||
883 | |||
884 | if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) | ||
885 | key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; | ||
886 | |||
887 | err = ieee80211_key_link(key, sdata, NULL); | ||
888 | if (err) | ||
889 | return ERR_PTR(err); | ||
890 | |||
891 | return &key->conf; | ||
892 | } | ||
893 | EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_add); | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 21bccd849b3f..2aab1308690f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1113,6 +1113,15 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1113 | case -1: | 1113 | case -1: |
1114 | cfg80211_chandef_create(&new_chandef, new_chan, | 1114 | cfg80211_chandef_create(&new_chandef, new_chan, |
1115 | NL80211_CHAN_NO_HT); | 1115 | NL80211_CHAN_NO_HT); |
1116 | /* keep width for 5/10 MHz channels */ | ||
1117 | switch (sdata->vif.bss_conf.chandef.width) { | ||
1118 | case NL80211_CHAN_WIDTH_5: | ||
1119 | case NL80211_CHAN_WIDTH_10: | ||
1120 | new_chandef.width = sdata->vif.bss_conf.chandef.width; | ||
1121 | break; | ||
1122 | default: | ||
1123 | break; | ||
1124 | } | ||
1116 | break; | 1125 | break; |
1117 | } | 1126 | } |
1118 | 1127 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index ba63ac851c2b..e126605cec66 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -210,7 +210,7 @@ static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc) | |||
210 | !ieee80211_is_data(fc); | 210 | !ieee80211_is_data(fc); |
211 | } | 211 | } |
212 | 212 | ||
213 | static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, | 213 | static void rc_send_low_basicrate(s8 *idx, u32 basic_rates, |
214 | struct ieee80211_supported_band *sband) | 214 | struct ieee80211_supported_band *sband) |
215 | { | 215 | { |
216 | u8 i; | 216 | u8 i; |
@@ -263,28 +263,37 @@ static void __rate_control_send_low(struct ieee80211_hw *hw, | |||
263 | } | 263 | } |
264 | 264 | ||
265 | 265 | ||
266 | bool rate_control_send_low(struct ieee80211_sta *sta, | 266 | bool rate_control_send_low(struct ieee80211_sta *pubsta, |
267 | void *priv_sta, | 267 | void *priv_sta, |
268 | struct ieee80211_tx_rate_control *txrc) | 268 | struct ieee80211_tx_rate_control *txrc) |
269 | { | 269 | { |
270 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); | 270 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); |
271 | struct ieee80211_supported_band *sband = txrc->sband; | 271 | struct ieee80211_supported_band *sband = txrc->sband; |
272 | struct sta_info *sta; | ||
272 | int mcast_rate; | 273 | int mcast_rate; |
274 | bool use_basicrate = false; | ||
273 | 275 | ||
274 | if (!sta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { | 276 | if (!pubsta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { |
275 | __rate_control_send_low(txrc->hw, sband, sta, info); | 277 | __rate_control_send_low(txrc->hw, sband, pubsta, info); |
276 | 278 | ||
277 | if (!sta && txrc->bss) { | 279 | if (!pubsta && txrc->bss) { |
278 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; | 280 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; |
279 | if (mcast_rate > 0) { | 281 | if (mcast_rate > 0) { |
280 | info->control.rates[0].idx = mcast_rate - 1; | 282 | info->control.rates[0].idx = mcast_rate - 1; |
281 | return true; | 283 | return true; |
282 | } | 284 | } |
285 | use_basicrate = true; | ||
286 | } else if (pubsta) { | ||
287 | sta = container_of(pubsta, struct sta_info, sta); | ||
288 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
289 | use_basicrate = true; | ||
290 | } | ||
283 | 291 | ||
284 | rc_send_low_broadcast(&info->control.rates[0].idx, | 292 | if (use_basicrate) |
293 | rc_send_low_basicrate(&info->control.rates[0].idx, | ||
285 | txrc->bss_conf->basic_rates, | 294 | txrc->bss_conf->basic_rates, |
286 | sband); | 295 | sband); |
287 | } | 296 | |
288 | return true; | 297 | return true; |
289 | } | 298 | } |
290 | return false; | 299 | return false; |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 61569425b723..a9909651dc0b 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -439,12 +439,13 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb) | |||
439 | { | 439 | { |
440 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 440 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
441 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 441 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
442 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
442 | u16 tid; | 443 | u16 tid; |
443 | 444 | ||
444 | if (unlikely(!ieee80211_is_data_qos(hdr->frame_control))) | 445 | if (unlikely(!ieee80211_is_data_qos(hdr->frame_control))) |
445 | return; | 446 | return; |
446 | 447 | ||
447 | if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))) | 448 | if (unlikely(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) |
448 | return; | 449 | return; |
449 | 450 | ||
450 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 451 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
@@ -776,7 +777,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
776 | 777 | ||
777 | /* Don't use EAPOL frames for sampling on non-mrr hw */ | 778 | /* Don't use EAPOL frames for sampling on non-mrr hw */ |
778 | if (mp->hw->max_rates == 1 && | 779 | if (mp->hw->max_rates == 1 && |
779 | txrc->skb->protocol == cpu_to_be16(ETH_P_PAE)) | 780 | (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) |
780 | sample_idx = -1; | 781 | sample_idx = -1; |
781 | else | 782 | else |
782 | sample_idx = minstrel_get_sample_rate(mp, mi); | 783 | sample_idx = minstrel_get_sample_rate(mp, mi); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6b85f95b9ba1..a84f319c11ad 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1055,207 +1055,6 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
1055 | 1055 | ||
1056 | 1056 | ||
1057 | static ieee80211_rx_result debug_noinline | 1057 | static ieee80211_rx_result debug_noinline |
1058 | ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | ||
1059 | { | ||
1060 | struct sk_buff *skb = rx->skb; | ||
1061 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
1062 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1063 | int keyidx; | ||
1064 | int hdrlen; | ||
1065 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | ||
1066 | struct ieee80211_key *sta_ptk = NULL; | ||
1067 | int mmie_keyidx = -1; | ||
1068 | __le16 fc; | ||
1069 | |||
1070 | /* | ||
1071 | * Key selection 101 | ||
1072 | * | ||
1073 | * There are four types of keys: | ||
1074 | * - GTK (group keys) | ||
1075 | * - IGTK (group keys for management frames) | ||
1076 | * - PTK (pairwise keys) | ||
1077 | * - STK (station-to-station pairwise keys) | ||
1078 | * | ||
1079 | * When selecting a key, we have to distinguish between multicast | ||
1080 | * (including broadcast) and unicast frames, the latter can only | ||
1081 | * use PTKs and STKs while the former always use GTKs and IGTKs. | ||
1082 | * Unless, of course, actual WEP keys ("pre-RSNA") are used, then | ||
1083 | * unicast frames can also use key indices like GTKs. Hence, if we | ||
1084 | * don't have a PTK/STK we check the key index for a WEP key. | ||
1085 | * | ||
1086 | * Note that in a regular BSS, multicast frames are sent by the | ||
1087 | * AP only, associated stations unicast the frame to the AP first | ||
1088 | * which then multicasts it on their behalf. | ||
1089 | * | ||
1090 | * There is also a slight problem in IBSS mode: GTKs are negotiated | ||
1091 | * with each station, that is something we don't currently handle. | ||
1092 | * The spec seems to expect that one negotiates the same key with | ||
1093 | * every station but there's no such requirement; VLANs could be | ||
1094 | * possible. | ||
1095 | */ | ||
1096 | |||
1097 | /* | ||
1098 | * No point in finding a key and decrypting if the frame is neither | ||
1099 | * addressed to us nor a multicast frame. | ||
1100 | */ | ||
1101 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1102 | return RX_CONTINUE; | ||
1103 | |||
1104 | /* start without a key */ | ||
1105 | rx->key = NULL; | ||
1106 | |||
1107 | if (rx->sta) | ||
1108 | sta_ptk = rcu_dereference(rx->sta->ptk); | ||
1109 | |||
1110 | fc = hdr->frame_control; | ||
1111 | |||
1112 | if (!ieee80211_has_protected(fc)) | ||
1113 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
1114 | |||
1115 | if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) { | ||
1116 | rx->key = sta_ptk; | ||
1117 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
1118 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
1119 | return RX_CONTINUE; | ||
1120 | /* Skip decryption if the frame is not protected. */ | ||
1121 | if (!ieee80211_has_protected(fc)) | ||
1122 | return RX_CONTINUE; | ||
1123 | } else if (mmie_keyidx >= 0) { | ||
1124 | /* Broadcast/multicast robust management frame / BIP */ | ||
1125 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
1126 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
1127 | return RX_CONTINUE; | ||
1128 | |||
1129 | if (mmie_keyidx < NUM_DEFAULT_KEYS || | ||
1130 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | ||
1131 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | ||
1132 | if (rx->sta) | ||
1133 | rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]); | ||
1134 | if (!rx->key) | ||
1135 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | ||
1136 | } else if (!ieee80211_has_protected(fc)) { | ||
1137 | /* | ||
1138 | * The frame was not protected, so skip decryption. However, we | ||
1139 | * need to set rx->key if there is a key that could have been | ||
1140 | * used so that the frame may be dropped if encryption would | ||
1141 | * have been expected. | ||
1142 | */ | ||
1143 | struct ieee80211_key *key = NULL; | ||
1144 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
1145 | int i; | ||
1146 | |||
1147 | if (ieee80211_is_mgmt(fc) && | ||
1148 | is_multicast_ether_addr(hdr->addr1) && | ||
1149 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) | ||
1150 | rx->key = key; | ||
1151 | else { | ||
1152 | if (rx->sta) { | ||
1153 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
1154 | key = rcu_dereference(rx->sta->gtk[i]); | ||
1155 | if (key) | ||
1156 | break; | ||
1157 | } | ||
1158 | } | ||
1159 | if (!key) { | ||
1160 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
1161 | key = rcu_dereference(sdata->keys[i]); | ||
1162 | if (key) | ||
1163 | break; | ||
1164 | } | ||
1165 | } | ||
1166 | if (key) | ||
1167 | rx->key = key; | ||
1168 | } | ||
1169 | return RX_CONTINUE; | ||
1170 | } else { | ||
1171 | u8 keyid; | ||
1172 | /* | ||
1173 | * The device doesn't give us the IV so we won't be | ||
1174 | * able to look up the key. That's ok though, we | ||
1175 | * don't need to decrypt the frame, we just won't | ||
1176 | * be able to keep statistics accurate. | ||
1177 | * Except for key threshold notifications, should | ||
1178 | * we somehow allow the driver to tell us which key | ||
1179 | * the hardware used if this flag is set? | ||
1180 | */ | ||
1181 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
1182 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
1183 | return RX_CONTINUE; | ||
1184 | |||
1185 | hdrlen = ieee80211_hdrlen(fc); | ||
1186 | |||
1187 | if (rx->skb->len < 8 + hdrlen) | ||
1188 | return RX_DROP_UNUSABLE; /* TODO: count this? */ | ||
1189 | |||
1190 | /* | ||
1191 | * no need to call ieee80211_wep_get_keyidx, | ||
1192 | * it verifies a bunch of things we've done already | ||
1193 | */ | ||
1194 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); | ||
1195 | keyidx = keyid >> 6; | ||
1196 | |||
1197 | /* check per-station GTK first, if multicast packet */ | ||
1198 | if (is_multicast_ether_addr(hdr->addr1) && rx->sta) | ||
1199 | rx->key = rcu_dereference(rx->sta->gtk[keyidx]); | ||
1200 | |||
1201 | /* if not found, try default key */ | ||
1202 | if (!rx->key) { | ||
1203 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); | ||
1204 | |||
1205 | /* | ||
1206 | * RSNA-protected unicast frames should always be | ||
1207 | * sent with pairwise or station-to-station keys, | ||
1208 | * but for WEP we allow using a key index as well. | ||
1209 | */ | ||
1210 | if (rx->key && | ||
1211 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && | ||
1212 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && | ||
1213 | !is_multicast_ether_addr(hdr->addr1)) | ||
1214 | rx->key = NULL; | ||
1215 | } | ||
1216 | } | ||
1217 | |||
1218 | if (rx->key) { | ||
1219 | if (unlikely(rx->key->flags & KEY_FLAG_TAINTED)) | ||
1220 | return RX_DROP_MONITOR; | ||
1221 | |||
1222 | rx->key->tx_rx_count++; | ||
1223 | /* TODO: add threshold stuff again */ | ||
1224 | } else { | ||
1225 | return RX_DROP_MONITOR; | ||
1226 | } | ||
1227 | |||
1228 | switch (rx->key->conf.cipher) { | ||
1229 | case WLAN_CIPHER_SUITE_WEP40: | ||
1230 | case WLAN_CIPHER_SUITE_WEP104: | ||
1231 | result = ieee80211_crypto_wep_decrypt(rx); | ||
1232 | break; | ||
1233 | case WLAN_CIPHER_SUITE_TKIP: | ||
1234 | result = ieee80211_crypto_tkip_decrypt(rx); | ||
1235 | break; | ||
1236 | case WLAN_CIPHER_SUITE_CCMP: | ||
1237 | result = ieee80211_crypto_ccmp_decrypt(rx); | ||
1238 | break; | ||
1239 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
1240 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | ||
1241 | break; | ||
1242 | default: | ||
1243 | /* | ||
1244 | * We can reach here only with HW-only algorithms | ||
1245 | * but why didn't it decrypt the frame?! | ||
1246 | */ | ||
1247 | return RX_DROP_UNUSABLE; | ||
1248 | } | ||
1249 | |||
1250 | /* the hdr variable is invalid after the decrypt handlers */ | ||
1251 | |||
1252 | /* either the frame has been decrypted or will be dropped */ | ||
1253 | status->flag |= RX_FLAG_DECRYPTED; | ||
1254 | |||
1255 | return result; | ||
1256 | } | ||
1257 | |||
1258 | static ieee80211_rx_result debug_noinline | ||
1259 | ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx) | 1058 | ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx) |
1260 | { | 1059 | { |
1261 | struct ieee80211_local *local; | 1060 | struct ieee80211_local *local; |
@@ -1556,6 +1355,207 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1556 | return RX_CONTINUE; | 1355 | return RX_CONTINUE; |
1557 | } /* ieee80211_rx_h_sta_process */ | 1356 | } /* ieee80211_rx_h_sta_process */ |
1558 | 1357 | ||
1358 | static ieee80211_rx_result debug_noinline | ||
1359 | ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | ||
1360 | { | ||
1361 | struct sk_buff *skb = rx->skb; | ||
1362 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
1363 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1364 | int keyidx; | ||
1365 | int hdrlen; | ||
1366 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | ||
1367 | struct ieee80211_key *sta_ptk = NULL; | ||
1368 | int mmie_keyidx = -1; | ||
1369 | __le16 fc; | ||
1370 | |||
1371 | /* | ||
1372 | * Key selection 101 | ||
1373 | * | ||
1374 | * There are four types of keys: | ||
1375 | * - GTK (group keys) | ||
1376 | * - IGTK (group keys for management frames) | ||
1377 | * - PTK (pairwise keys) | ||
1378 | * - STK (station-to-station pairwise keys) | ||
1379 | * | ||
1380 | * When selecting a key, we have to distinguish between multicast | ||
1381 | * (including broadcast) and unicast frames, the latter can only | ||
1382 | * use PTKs and STKs while the former always use GTKs and IGTKs. | ||
1383 | * Unless, of course, actual WEP keys ("pre-RSNA") are used, then | ||
1384 | * unicast frames can also use key indices like GTKs. Hence, if we | ||
1385 | * don't have a PTK/STK we check the key index for a WEP key. | ||
1386 | * | ||
1387 | * Note that in a regular BSS, multicast frames are sent by the | ||
1388 | * AP only, associated stations unicast the frame to the AP first | ||
1389 | * which then multicasts it on their behalf. | ||
1390 | * | ||
1391 | * There is also a slight problem in IBSS mode: GTKs are negotiated | ||
1392 | * with each station, that is something we don't currently handle. | ||
1393 | * The spec seems to expect that one negotiates the same key with | ||
1394 | * every station but there's no such requirement; VLANs could be | ||
1395 | * possible. | ||
1396 | */ | ||
1397 | |||
1398 | /* | ||
1399 | * No point in finding a key and decrypting if the frame is neither | ||
1400 | * addressed to us nor a multicast frame. | ||
1401 | */ | ||
1402 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1403 | return RX_CONTINUE; | ||
1404 | |||
1405 | /* start without a key */ | ||
1406 | rx->key = NULL; | ||
1407 | |||
1408 | if (rx->sta) | ||
1409 | sta_ptk = rcu_dereference(rx->sta->ptk); | ||
1410 | |||
1411 | fc = hdr->frame_control; | ||
1412 | |||
1413 | if (!ieee80211_has_protected(fc)) | ||
1414 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
1415 | |||
1416 | if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) { | ||
1417 | rx->key = sta_ptk; | ||
1418 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
1419 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
1420 | return RX_CONTINUE; | ||
1421 | /* Skip decryption if the frame is not protected. */ | ||
1422 | if (!ieee80211_has_protected(fc)) | ||
1423 | return RX_CONTINUE; | ||
1424 | } else if (mmie_keyidx >= 0) { | ||
1425 | /* Broadcast/multicast robust management frame / BIP */ | ||
1426 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
1427 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
1428 | return RX_CONTINUE; | ||
1429 | |||
1430 | if (mmie_keyidx < NUM_DEFAULT_KEYS || | ||
1431 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | ||
1432 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | ||
1433 | if (rx->sta) | ||
1434 | rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]); | ||
1435 | if (!rx->key) | ||
1436 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | ||
1437 | } else if (!ieee80211_has_protected(fc)) { | ||
1438 | /* | ||
1439 | * The frame was not protected, so skip decryption. However, we | ||
1440 | * need to set rx->key if there is a key that could have been | ||
1441 | * used so that the frame may be dropped if encryption would | ||
1442 | * have been expected. | ||
1443 | */ | ||
1444 | struct ieee80211_key *key = NULL; | ||
1445 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
1446 | int i; | ||
1447 | |||
1448 | if (ieee80211_is_mgmt(fc) && | ||
1449 | is_multicast_ether_addr(hdr->addr1) && | ||
1450 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) | ||
1451 | rx->key = key; | ||
1452 | else { | ||
1453 | if (rx->sta) { | ||
1454 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
1455 | key = rcu_dereference(rx->sta->gtk[i]); | ||
1456 | if (key) | ||
1457 | break; | ||
1458 | } | ||
1459 | } | ||
1460 | if (!key) { | ||
1461 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
1462 | key = rcu_dereference(sdata->keys[i]); | ||
1463 | if (key) | ||
1464 | break; | ||
1465 | } | ||
1466 | } | ||
1467 | if (key) | ||
1468 | rx->key = key; | ||
1469 | } | ||
1470 | return RX_CONTINUE; | ||
1471 | } else { | ||
1472 | u8 keyid; | ||
1473 | /* | ||
1474 | * The device doesn't give us the IV so we won't be | ||
1475 | * able to look up the key. That's ok though, we | ||
1476 | * don't need to decrypt the frame, we just won't | ||
1477 | * be able to keep statistics accurate. | ||
1478 | * Except for key threshold notifications, should | ||
1479 | * we somehow allow the driver to tell us which key | ||
1480 | * the hardware used if this flag is set? | ||
1481 | */ | ||
1482 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
1483 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
1484 | return RX_CONTINUE; | ||
1485 | |||
1486 | hdrlen = ieee80211_hdrlen(fc); | ||
1487 | |||
1488 | if (rx->skb->len < 8 + hdrlen) | ||
1489 | return RX_DROP_UNUSABLE; /* TODO: count this? */ | ||
1490 | |||
1491 | /* | ||
1492 | * no need to call ieee80211_wep_get_keyidx, | ||
1493 | * it verifies a bunch of things we've done already | ||
1494 | */ | ||
1495 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); | ||
1496 | keyidx = keyid >> 6; | ||
1497 | |||
1498 | /* check per-station GTK first, if multicast packet */ | ||
1499 | if (is_multicast_ether_addr(hdr->addr1) && rx->sta) | ||
1500 | rx->key = rcu_dereference(rx->sta->gtk[keyidx]); | ||
1501 | |||
1502 | /* if not found, try default key */ | ||
1503 | if (!rx->key) { | ||
1504 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); | ||
1505 | |||
1506 | /* | ||
1507 | * RSNA-protected unicast frames should always be | ||
1508 | * sent with pairwise or station-to-station keys, | ||
1509 | * but for WEP we allow using a key index as well. | ||
1510 | */ | ||
1511 | if (rx->key && | ||
1512 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && | ||
1513 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && | ||
1514 | !is_multicast_ether_addr(hdr->addr1)) | ||
1515 | rx->key = NULL; | ||
1516 | } | ||
1517 | } | ||
1518 | |||
1519 | if (rx->key) { | ||
1520 | if (unlikely(rx->key->flags & KEY_FLAG_TAINTED)) | ||
1521 | return RX_DROP_MONITOR; | ||
1522 | |||
1523 | rx->key->tx_rx_count++; | ||
1524 | /* TODO: add threshold stuff again */ | ||
1525 | } else { | ||
1526 | return RX_DROP_MONITOR; | ||
1527 | } | ||
1528 | |||
1529 | switch (rx->key->conf.cipher) { | ||
1530 | case WLAN_CIPHER_SUITE_WEP40: | ||
1531 | case WLAN_CIPHER_SUITE_WEP104: | ||
1532 | result = ieee80211_crypto_wep_decrypt(rx); | ||
1533 | break; | ||
1534 | case WLAN_CIPHER_SUITE_TKIP: | ||
1535 | result = ieee80211_crypto_tkip_decrypt(rx); | ||
1536 | break; | ||
1537 | case WLAN_CIPHER_SUITE_CCMP: | ||
1538 | result = ieee80211_crypto_ccmp_decrypt(rx); | ||
1539 | break; | ||
1540 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
1541 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | ||
1542 | break; | ||
1543 | default: | ||
1544 | /* | ||
1545 | * We can reach here only with HW-only algorithms | ||
1546 | * but why didn't it decrypt the frame?! | ||
1547 | */ | ||
1548 | return RX_DROP_UNUSABLE; | ||
1549 | } | ||
1550 | |||
1551 | /* the hdr variable is invalid after the decrypt handlers */ | ||
1552 | |||
1553 | /* either the frame has been decrypted or will be dropped */ | ||
1554 | status->flag |= RX_FLAG_DECRYPTED; | ||
1555 | |||
1556 | return result; | ||
1557 | } | ||
1558 | |||
1559 | static inline struct ieee80211_fragment_entry * | 1559 | static inline struct ieee80211_fragment_entry * |
1560 | ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, | 1560 | ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, |
1561 | unsigned int frag, unsigned int seq, int rx_queue, | 1561 | unsigned int frag, unsigned int seq, int rx_queue, |
@@ -2939,10 +2939,10 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, | |||
2939 | */ | 2939 | */ |
2940 | rx->skb = skb; | 2940 | rx->skb = skb; |
2941 | 2941 | ||
2942 | CALL_RXH(ieee80211_rx_h_decrypt) | ||
2943 | CALL_RXH(ieee80211_rx_h_check_more_data) | 2942 | CALL_RXH(ieee80211_rx_h_check_more_data) |
2944 | CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll) | 2943 | CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll) |
2945 | CALL_RXH(ieee80211_rx_h_sta_process) | 2944 | CALL_RXH(ieee80211_rx_h_sta_process) |
2945 | CALL_RXH(ieee80211_rx_h_decrypt) | ||
2946 | CALL_RXH(ieee80211_rx_h_defragment) | 2946 | CALL_RXH(ieee80211_rx_h_defragment) |
2947 | CALL_RXH(ieee80211_rx_h_michael_mic_verify) | 2947 | CALL_RXH(ieee80211_rx_h_michael_mic_verify) |
2948 | /* must be after MMIC verify so header is counted in MPDU mic */ | 2948 | /* must be after MMIC verify so header is counted in MPDU mic */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0e42322aa6b1..098ae854ad3c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -539,9 +539,11 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx) | |||
539 | { | 539 | { |
540 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 540 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
541 | 541 | ||
542 | if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol && | 542 | if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol)) { |
543 | tx->sdata->control_port_no_encrypt)) | 543 | if (tx->sdata->control_port_no_encrypt) |
544 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 544 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
545 | info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; | ||
546 | } | ||
545 | 547 | ||
546 | return TX_CONTINUE; | 548 | return TX_CONTINUE; |
547 | } | 549 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d23c5a705a68..e1b34a18b243 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1453,8 +1453,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1453 | local->resuming = true; | 1453 | local->resuming = true; |
1454 | 1454 | ||
1455 | if (local->wowlan) { | 1455 | if (local->wowlan) { |
1456 | local->wowlan = false; | ||
1457 | res = drv_resume(local); | 1456 | res = drv_resume(local); |
1457 | local->wowlan = false; | ||
1458 | if (res < 0) { | 1458 | if (res < 0) { |
1459 | local->resuming = false; | 1459 | local->resuming = false; |
1460 | return res; | 1460 | return res; |
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c index d11ac79246e4..cf5b145902e5 100644 --- a/net/rfkill/rfkill-regulator.c +++ b/net/rfkill/rfkill-regulator.c | |||
@@ -30,6 +30,7 @@ struct rfkill_regulator_data { | |||
30 | static int rfkill_regulator_set_block(void *data, bool blocked) | 30 | static int rfkill_regulator_set_block(void *data, bool blocked) |
31 | { | 31 | { |
32 | struct rfkill_regulator_data *rfkill_data = data; | 32 | struct rfkill_regulator_data *rfkill_data = data; |
33 | int ret = 0; | ||
33 | 34 | ||
34 | pr_debug("%s: blocked: %d\n", __func__, blocked); | 35 | pr_debug("%s: blocked: %d\n", __func__, blocked); |
35 | 36 | ||
@@ -40,15 +41,16 @@ static int rfkill_regulator_set_block(void *data, bool blocked) | |||
40 | } | 41 | } |
41 | } else { | 42 | } else { |
42 | if (!rfkill_data->reg_enabled) { | 43 | if (!rfkill_data->reg_enabled) { |
43 | regulator_enable(rfkill_data->vcc); | 44 | ret = regulator_enable(rfkill_data->vcc); |
44 | rfkill_data->reg_enabled = true; | 45 | if (!ret) |
46 | rfkill_data->reg_enabled = true; | ||
45 | } | 47 | } |
46 | } | 48 | } |
47 | 49 | ||
48 | pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__, | 50 | pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__, |
49 | regulator_is_enabled(rfkill_data->vcc)); | 51 | regulator_is_enabled(rfkill_data->vcc)); |
50 | 52 | ||
51 | return 0; | 53 | return ret; |
52 | } | 54 | } |
53 | 55 | ||
54 | static struct rfkill_ops rfkill_regulator_ops = { | 56 | static struct rfkill_ops rfkill_regulator_ops = { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index adf1e98f4c3e..c6164da1c133 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -6593,19 +6593,30 @@ static struct genl_multicast_group nl80211_testmode_mcgrp = { | |||
6593 | static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) | 6593 | static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) |
6594 | { | 6594 | { |
6595 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6595 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6596 | struct wireless_dev *wdev = | ||
6597 | __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs); | ||
6596 | int err; | 6598 | int err; |
6597 | 6599 | ||
6600 | if (!rdev->ops->testmode_cmd) | ||
6601 | return -EOPNOTSUPP; | ||
6602 | |||
6603 | if (IS_ERR(wdev)) { | ||
6604 | err = PTR_ERR(wdev); | ||
6605 | if (err != -EINVAL) | ||
6606 | return err; | ||
6607 | wdev = NULL; | ||
6608 | } else if (wdev->wiphy != &rdev->wiphy) { | ||
6609 | return -EINVAL; | ||
6610 | } | ||
6611 | |||
6598 | if (!info->attrs[NL80211_ATTR_TESTDATA]) | 6612 | if (!info->attrs[NL80211_ATTR_TESTDATA]) |
6599 | return -EINVAL; | 6613 | return -EINVAL; |
6600 | 6614 | ||
6601 | err = -EOPNOTSUPP; | 6615 | rdev->testmode_info = info; |
6602 | if (rdev->ops->testmode_cmd) { | 6616 | err = rdev_testmode_cmd(rdev, wdev, |
6603 | rdev->testmode_info = info; | ||
6604 | err = rdev_testmode_cmd(rdev, | ||
6605 | nla_data(info->attrs[NL80211_ATTR_TESTDATA]), | 6617 | nla_data(info->attrs[NL80211_ATTR_TESTDATA]), |
6606 | nla_len(info->attrs[NL80211_ATTR_TESTDATA])); | 6618 | nla_len(info->attrs[NL80211_ATTR_TESTDATA])); |
6607 | rdev->testmode_info = NULL; | 6619 | rdev->testmode_info = NULL; |
6608 | } | ||
6609 | 6620 | ||
6610 | return err; | 6621 | return err; |
6611 | } | 6622 | } |
@@ -7566,14 +7577,12 @@ static int nl80211_set_cqm_txe(struct genl_info *info, | |||
7566 | u32 rate, u32 pkts, u32 intvl) | 7577 | u32 rate, u32 pkts, u32 intvl) |
7567 | { | 7578 | { |
7568 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 7579 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
7569 | struct wireless_dev *wdev; | ||
7570 | struct net_device *dev = info->user_ptr[1]; | 7580 | struct net_device *dev = info->user_ptr[1]; |
7581 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
7571 | 7582 | ||
7572 | if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL) | 7583 | if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL) |
7573 | return -EINVAL; | 7584 | return -EINVAL; |
7574 | 7585 | ||
7575 | wdev = dev->ieee80211_ptr; | ||
7576 | |||
7577 | if (!rdev->ops->set_cqm_txe_config) | 7586 | if (!rdev->ops->set_cqm_txe_config) |
7578 | return -EOPNOTSUPP; | 7587 | return -EOPNOTSUPP; |
7579 | 7588 | ||
@@ -7588,13 +7597,15 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, | |||
7588 | s32 threshold, u32 hysteresis) | 7597 | s32 threshold, u32 hysteresis) |
7589 | { | 7598 | { |
7590 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 7599 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
7591 | struct wireless_dev *wdev; | ||
7592 | struct net_device *dev = info->user_ptr[1]; | 7600 | struct net_device *dev = info->user_ptr[1]; |
7601 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
7593 | 7602 | ||
7594 | if (threshold > 0) | 7603 | if (threshold > 0) |
7595 | return -EINVAL; | 7604 | return -EINVAL; |
7596 | 7605 | ||
7597 | wdev = dev->ieee80211_ptr; | 7606 | /* disabling - hysteresis should also be zero then */ |
7607 | if (threshold == 0) | ||
7608 | hysteresis = 0; | ||
7598 | 7609 | ||
7599 | if (!rdev->ops->set_cqm_rssi_config) | 7610 | if (!rdev->ops->set_cqm_rssi_config) |
7600 | return -EOPNOTSUPP; | 7611 | return -EOPNOTSUPP; |
@@ -7613,36 +7624,33 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) | |||
7613 | int err; | 7624 | int err; |
7614 | 7625 | ||
7615 | cqm = info->attrs[NL80211_ATTR_CQM]; | 7626 | cqm = info->attrs[NL80211_ATTR_CQM]; |
7616 | if (!cqm) { | 7627 | if (!cqm) |
7617 | err = -EINVAL; | 7628 | return -EINVAL; |
7618 | goto out; | ||
7619 | } | ||
7620 | 7629 | ||
7621 | err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm, | 7630 | err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm, |
7622 | nl80211_attr_cqm_policy); | 7631 | nl80211_attr_cqm_policy); |
7623 | if (err) | 7632 | if (err) |
7624 | goto out; | 7633 | return err; |
7625 | 7634 | ||
7626 | if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] && | 7635 | if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] && |
7627 | attrs[NL80211_ATTR_CQM_RSSI_HYST]) { | 7636 | attrs[NL80211_ATTR_CQM_RSSI_HYST]) { |
7628 | s32 threshold; | 7637 | s32 threshold = nla_get_s32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); |
7629 | u32 hysteresis; | 7638 | u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); |
7630 | threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); | ||
7631 | hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); | ||
7632 | err = nl80211_set_cqm_rssi(info, threshold, hysteresis); | ||
7633 | } else if (attrs[NL80211_ATTR_CQM_TXE_RATE] && | ||
7634 | attrs[NL80211_ATTR_CQM_TXE_PKTS] && | ||
7635 | attrs[NL80211_ATTR_CQM_TXE_INTVL]) { | ||
7636 | u32 rate, pkts, intvl; | ||
7637 | rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]); | ||
7638 | pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]); | ||
7639 | intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]); | ||
7640 | err = nl80211_set_cqm_txe(info, rate, pkts, intvl); | ||
7641 | } else | ||
7642 | err = -EINVAL; | ||
7643 | 7639 | ||
7644 | out: | 7640 | return nl80211_set_cqm_rssi(info, threshold, hysteresis); |
7645 | return err; | 7641 | } |
7642 | |||
7643 | if (attrs[NL80211_ATTR_CQM_TXE_RATE] && | ||
7644 | attrs[NL80211_ATTR_CQM_TXE_PKTS] && | ||
7645 | attrs[NL80211_ATTR_CQM_TXE_INTVL]) { | ||
7646 | u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]); | ||
7647 | u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]); | ||
7648 | u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]); | ||
7649 | |||
7650 | return nl80211_set_cqm_txe(info, rate, pkts, intvl); | ||
7651 | } | ||
7652 | |||
7653 | return -EINVAL; | ||
7646 | } | 7654 | } |
7647 | 7655 | ||
7648 | static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | 7656 | static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) |
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index de870d4d0bcc..37ce9fdfe934 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -516,11 +516,12 @@ static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev) | |||
516 | 516 | ||
517 | #ifdef CONFIG_NL80211_TESTMODE | 517 | #ifdef CONFIG_NL80211_TESTMODE |
518 | static inline int rdev_testmode_cmd(struct cfg80211_registered_device *rdev, | 518 | static inline int rdev_testmode_cmd(struct cfg80211_registered_device *rdev, |
519 | struct wireless_dev *wdev, | ||
519 | void *data, int len) | 520 | void *data, int len) |
520 | { | 521 | { |
521 | int ret; | 522 | int ret; |
522 | trace_rdev_testmode_cmd(&rdev->wiphy); | 523 | trace_rdev_testmode_cmd(&rdev->wiphy, wdev); |
523 | ret = rdev->ops->testmode_cmd(&rdev->wiphy, data, len); | 524 | ret = rdev->ops->testmode_cmd(&rdev->wiphy, wdev, data, len); |
524 | trace_rdev_return_int(&rdev->wiphy, ret); | 525 | trace_rdev_return_int(&rdev->wiphy, ret); |
525 | return ret; | 526 | return ret; |
526 | } | 527 | } |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index f0ebdcd394ef..ba5f0d6614d5 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -1293,15 +1293,17 @@ TRACE_EVENT(rdev_return_int_int, | |||
1293 | 1293 | ||
1294 | #ifdef CONFIG_NL80211_TESTMODE | 1294 | #ifdef CONFIG_NL80211_TESTMODE |
1295 | TRACE_EVENT(rdev_testmode_cmd, | 1295 | TRACE_EVENT(rdev_testmode_cmd, |
1296 | TP_PROTO(struct wiphy *wiphy), | 1296 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), |
1297 | TP_ARGS(wiphy), | 1297 | TP_ARGS(wiphy, wdev), |
1298 | TP_STRUCT__entry( | 1298 | TP_STRUCT__entry( |
1299 | WIPHY_ENTRY | 1299 | WIPHY_ENTRY |
1300 | WDEV_ENTRY | ||
1300 | ), | 1301 | ), |
1301 | TP_fast_assign( | 1302 | TP_fast_assign( |
1302 | WIPHY_ASSIGN; | 1303 | WIPHY_ASSIGN; |
1304 | WDEV_ASSIGN; | ||
1303 | ), | 1305 | ), |
1304 | TP_printk(WIPHY_PR_FMT, WIPHY_PR_ARG) | 1306 | TP_printk(WIPHY_PR_FMT WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) |
1305 | ); | 1307 | ); |
1306 | 1308 | ||
1307 | TRACE_EVENT(rdev_testmode_dump, | 1309 | TRACE_EVENT(rdev_testmode_dump, |