diff options
author | David S. Miller <davem@davemloft.net> | 2010-12-23 13:13:30 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-23 13:13:30 -0500 |
commit | a130883d9528eefb66285728ba6a232d8fff9465 (patch) | |
tree | 304b63e59d910be2ee2798404fe4a940bdfdd2af /net | |
parent | d9f4fbaf7053af43e6c72909c2aff18654717aed (diff) | |
parent | 65a6538a56d4c7ae8465f2a8420ddc65877b6779 (diff) |
Merge branch 'for-davem' of ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
31 files changed, 769 insertions, 218 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index d4679b265ba8..9cc472c6a6a5 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -342,10 +342,11 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
342 | /* send AddBA request */ | 342 | /* send AddBA request */ |
343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, | 343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, |
344 | tid_tx->dialog_token, start_seq_num, | 344 | tid_tx->dialog_token, start_seq_num, |
345 | 0x40, 5000); | 345 | 0x40, tid_tx->timeout); |
346 | } | 346 | } |
347 | 347 | ||
348 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | 348 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, |
349 | u16 timeout) | ||
349 | { | 350 | { |
350 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 351 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
351 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 352 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -420,6 +421,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
420 | skb_queue_head_init(&tid_tx->pending); | 421 | skb_queue_head_init(&tid_tx->pending); |
421 | __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); | 422 | __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); |
422 | 423 | ||
424 | tid_tx->timeout = timeout; | ||
425 | |||
423 | /* Tx timer */ | 426 | /* Tx timer */ |
424 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; | 427 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; |
425 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 428 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c30b8b72eedb..5892b0302454 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -295,11 +295,12 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
295 | 295 | ||
296 | static int ieee80211_config_default_key(struct wiphy *wiphy, | 296 | static int ieee80211_config_default_key(struct wiphy *wiphy, |
297 | struct net_device *dev, | 297 | struct net_device *dev, |
298 | u8 key_idx) | 298 | u8 key_idx, bool uni, |
299 | bool multi) | ||
299 | { | 300 | { |
300 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 301 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
301 | 302 | ||
302 | ieee80211_set_default_key(sdata, key_idx); | 303 | ieee80211_set_default_key(sdata, key_idx, uni, multi); |
303 | 304 | ||
304 | return 0; | 305 | return 0; |
305 | } | 306 | } |
@@ -983,7 +984,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
983 | return 0; | 984 | return 0; |
984 | } | 985 | } |
985 | 986 | ||
986 | static int ieee80211_get_mesh_params(struct wiphy *wiphy, | 987 | static int ieee80211_get_mesh_config(struct wiphy *wiphy, |
987 | struct net_device *dev, | 988 | struct net_device *dev, |
988 | struct mesh_config *conf) | 989 | struct mesh_config *conf) |
989 | { | 990 | { |
@@ -999,7 +1000,37 @@ static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask) | |||
999 | return (mask >> (parm-1)) & 0x1; | 1000 | return (mask >> (parm-1)) & 0x1; |
1000 | } | 1001 | } |
1001 | 1002 | ||
1002 | static int ieee80211_update_mesh_params(struct wiphy *wiphy, | 1003 | static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, |
1004 | const struct mesh_setup *setup) | ||
1005 | { | ||
1006 | u8 *new_ie; | ||
1007 | const u8 *old_ie; | ||
1008 | |||
1009 | /* first allocate the new vendor information element */ | ||
1010 | new_ie = NULL; | ||
1011 | old_ie = ifmsh->vendor_ie; | ||
1012 | |||
1013 | ifmsh->vendor_ie_len = setup->vendor_ie_len; | ||
1014 | if (setup->vendor_ie_len) { | ||
1015 | new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len, | ||
1016 | GFP_KERNEL); | ||
1017 | if (!new_ie) | ||
1018 | return -ENOMEM; | ||
1019 | } | ||
1020 | |||
1021 | /* now copy the rest of the setup parameters */ | ||
1022 | ifmsh->mesh_id_len = setup->mesh_id_len; | ||
1023 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | ||
1024 | ifmsh->mesh_pp_id = setup->path_sel_proto; | ||
1025 | ifmsh->mesh_pm_id = setup->path_metric; | ||
1026 | ifmsh->vendor_ie = new_ie; | ||
1027 | |||
1028 | kfree(old_ie); | ||
1029 | |||
1030 | return 0; | ||
1031 | } | ||
1032 | |||
1033 | static int ieee80211_update_mesh_config(struct wiphy *wiphy, | ||
1003 | struct net_device *dev, u32 mask, | 1034 | struct net_device *dev, u32 mask, |
1004 | const struct mesh_config *nconf) | 1035 | const struct mesh_config *nconf) |
1005 | { | 1036 | { |
@@ -1058,11 +1089,12 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
1058 | { | 1089 | { |
1059 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1090 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1060 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1091 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1092 | int err; | ||
1061 | 1093 | ||
1062 | memcpy(&sdata->u.mesh.mshcfg, conf, sizeof(struct mesh_config)); | 1094 | memcpy(&ifmsh->mshcfg, conf, sizeof(struct mesh_config)); |
1063 | ifmsh->mesh_id_len = setup->mesh_id_len; | 1095 | err = copy_mesh_setup(ifmsh, setup); |
1064 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | 1096 | if (err) |
1065 | 1097 | return err; | |
1066 | ieee80211_start_mesh(sdata); | 1098 | ieee80211_start_mesh(sdata); |
1067 | 1099 | ||
1068 | return 0; | 1100 | return 0; |
@@ -1638,6 +1670,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1638 | case NL80211_IFTYPE_AP: | 1670 | case NL80211_IFTYPE_AP: |
1639 | case NL80211_IFTYPE_AP_VLAN: | 1671 | case NL80211_IFTYPE_AP_VLAN: |
1640 | case NL80211_IFTYPE_P2P_GO: | 1672 | case NL80211_IFTYPE_P2P_GO: |
1673 | case NL80211_IFTYPE_MESH_POINT: | ||
1641 | if (!ieee80211_is_action(mgmt->frame_control) || | 1674 | if (!ieee80211_is_action(mgmt->frame_control) || |
1642 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | 1675 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) |
1643 | break; | 1676 | break; |
@@ -1786,8 +1819,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1786 | .change_mpath = ieee80211_change_mpath, | 1819 | .change_mpath = ieee80211_change_mpath, |
1787 | .get_mpath = ieee80211_get_mpath, | 1820 | .get_mpath = ieee80211_get_mpath, |
1788 | .dump_mpath = ieee80211_dump_mpath, | 1821 | .dump_mpath = ieee80211_dump_mpath, |
1789 | .update_mesh_params = ieee80211_update_mesh_params, | 1822 | .update_mesh_config = ieee80211_update_mesh_config, |
1790 | .get_mesh_params = ieee80211_get_mesh_params, | 1823 | .get_mesh_config = ieee80211_get_mesh_config, |
1791 | .join_mesh = ieee80211_join_mesh, | 1824 | .join_mesh = ieee80211_join_mesh, |
1792 | .leave_mesh = ieee80211_leave_mesh, | 1825 | .leave_mesh = ieee80211_leave_mesh, |
1793 | #endif | 1826 | #endif |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 5822a6ce7671..f7ef3477c24a 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -274,7 +274,8 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key) | |||
274 | debugfs_remove_recursive(key->debugfs.dir); | 274 | debugfs_remove_recursive(key->debugfs.dir); |
275 | key->debugfs.dir = NULL; | 275 | key->debugfs.dir = NULL; |
276 | } | 276 | } |
277 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) | 277 | |
278 | void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | ||
278 | { | 279 | { |
279 | char buf[50]; | 280 | char buf[50]; |
280 | struct ieee80211_key *key; | 281 | struct ieee80211_key *key; |
@@ -282,25 +283,29 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) | |||
282 | if (!sdata->debugfs.dir) | 283 | if (!sdata->debugfs.dir) |
283 | return; | 284 | return; |
284 | 285 | ||
285 | /* this is running under the key lock */ | 286 | lockdep_assert_held(&sdata->local->key_mtx); |
286 | 287 | ||
287 | key = sdata->default_key; | 288 | if (sdata->default_unicast_key) { |
288 | if (key) { | 289 | key = sdata->default_unicast_key; |
289 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 290 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
290 | sdata->debugfs.default_key = | 291 | sdata->debugfs.default_unicast_key = |
291 | debugfs_create_symlink("default_key", | 292 | debugfs_create_symlink("default_unicast_key", |
292 | sdata->debugfs.dir, buf); | 293 | sdata->debugfs.dir, buf); |
293 | } else | 294 | } else { |
294 | ieee80211_debugfs_key_remove_default(sdata); | 295 | debugfs_remove(sdata->debugfs.default_unicast_key); |
295 | } | 296 | sdata->debugfs.default_unicast_key = NULL; |
296 | 297 | } | |
297 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) | ||
298 | { | ||
299 | if (!sdata) | ||
300 | return; | ||
301 | 298 | ||
302 | debugfs_remove(sdata->debugfs.default_key); | 299 | if (sdata->default_multicast_key) { |
303 | sdata->debugfs.default_key = NULL; | 300 | key = sdata->default_multicast_key; |
301 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | ||
302 | sdata->debugfs.default_multicast_key = | ||
303 | debugfs_create_symlink("default_multicast_key", | ||
304 | sdata->debugfs.dir, buf); | ||
305 | } else { | ||
306 | debugfs_remove(sdata->debugfs.default_multicast_key); | ||
307 | sdata->debugfs.default_multicast_key = NULL; | ||
308 | } | ||
304 | } | 309 | } |
305 | 310 | ||
306 | void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | 311 | void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h index 54717b4e1371..32adc77e9c77 100644 --- a/net/mac80211/debugfs_key.h +++ b/net/mac80211/debugfs_key.h | |||
@@ -4,8 +4,7 @@ | |||
4 | #ifdef CONFIG_MAC80211_DEBUGFS | 4 | #ifdef CONFIG_MAC80211_DEBUGFS |
5 | void ieee80211_debugfs_key_add(struct ieee80211_key *key); | 5 | void ieee80211_debugfs_key_add(struct ieee80211_key *key); |
6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); | 6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); |
7 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); | 7 | void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata); |
8 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); | ||
9 | void ieee80211_debugfs_key_add_mgmt_default( | 8 | void ieee80211_debugfs_key_add_mgmt_default( |
10 | struct ieee80211_sub_if_data *sdata); | 9 | struct ieee80211_sub_if_data *sdata); |
11 | void ieee80211_debugfs_key_remove_mgmt_default( | 10 | void ieee80211_debugfs_key_remove_mgmt_default( |
@@ -17,10 +16,7 @@ static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key) | |||
17 | {} | 16 | {} |
18 | static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) | 17 | static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) |
19 | {} | 18 | {} |
20 | static inline void ieee80211_debugfs_key_add_default( | 19 | static inline void ieee80211_debugfs_key_update_default( |
21 | struct ieee80211_sub_if_data *sdata) | ||
22 | {} | ||
23 | static inline void ieee80211_debugfs_key_remove_default( | ||
24 | struct ieee80211_sub_if_data *sdata) | 20 | struct ieee80211_sub_if_data *sdata) |
25 | {} | 21 | {} |
26 | static inline void ieee80211_debugfs_key_add_mgmt_default( | 22 | static inline void ieee80211_debugfs_key_add_mgmt_default( |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 8bb5af85f469..c04a1396cf8d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -189,7 +189,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu | |||
189 | 189 | ||
190 | if (tx) { | 190 | if (tx) { |
191 | if (start) | 191 | if (start) |
192 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid); | 192 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid, 5000); |
193 | else | 193 | else |
194 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); | 194 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); |
195 | } else { | 195 | } else { |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 4244554d218a..af0c4398cceb 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -367,7 +367,7 @@ static inline void drv_reset_tsf(struct ieee80211_local *local) | |||
367 | 367 | ||
368 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 368 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) |
369 | { | 369 | { |
370 | int ret = 1; | 370 | int ret = 0; /* default unsuported op for less congestion */ |
371 | 371 | ||
372 | might_sleep(); | 372 | might_sleep(); |
373 | 373 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 72499fe5fc36..a05893a238b7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <linux/leds.h> | ||
26 | #include <net/ieee80211_radiotap.h> | 27 | #include <net/ieee80211_radiotap.h> |
27 | #include <net/cfg80211.h> | 28 | #include <net/cfg80211.h> |
28 | #include <net/mac80211.h> | 29 | #include <net/mac80211.h> |
@@ -484,6 +485,8 @@ struct ieee80211_if_mesh { | |||
484 | struct mesh_config mshcfg; | 485 | struct mesh_config mshcfg; |
485 | u32 mesh_seqnum; | 486 | u32 mesh_seqnum; |
486 | bool accepting_plinks; | 487 | bool accepting_plinks; |
488 | const u8 *vendor_ie; | ||
489 | u8 vendor_ie_len; | ||
487 | }; | 490 | }; |
488 | 491 | ||
489 | #ifdef CONFIG_MAC80211_MESH | 492 | #ifdef CONFIG_MAC80211_MESH |
@@ -557,7 +560,7 @@ struct ieee80211_sub_if_data { | |||
557 | unsigned int fragment_next; | 560 | unsigned int fragment_next; |
558 | 561 | ||
559 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 562 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
560 | struct ieee80211_key *default_key; | 563 | struct ieee80211_key *default_unicast_key, *default_multicast_key; |
561 | struct ieee80211_key *default_mgmt_key; | 564 | struct ieee80211_key *default_mgmt_key; |
562 | 565 | ||
563 | u16 sequence_number; | 566 | u16 sequence_number; |
@@ -585,9 +588,7 @@ struct ieee80211_sub_if_data { | |||
585 | struct ieee80211_if_vlan vlan; | 588 | struct ieee80211_if_vlan vlan; |
586 | struct ieee80211_if_managed mgd; | 589 | struct ieee80211_if_managed mgd; |
587 | struct ieee80211_if_ibss ibss; | 590 | struct ieee80211_if_ibss ibss; |
588 | #ifdef CONFIG_MAC80211_MESH | ||
589 | struct ieee80211_if_mesh mesh; | 591 | struct ieee80211_if_mesh mesh; |
590 | #endif | ||
591 | u32 mntr_flags; | 592 | u32 mntr_flags; |
592 | } u; | 593 | } u; |
593 | 594 | ||
@@ -595,7 +596,8 @@ struct ieee80211_sub_if_data { | |||
595 | struct { | 596 | struct { |
596 | struct dentry *dir; | 597 | struct dentry *dir; |
597 | struct dentry *subdir_stations; | 598 | struct dentry *subdir_stations; |
598 | struct dentry *default_key; | 599 | struct dentry *default_unicast_key; |
600 | struct dentry *default_multicast_key; | ||
599 | struct dentry *default_mgmt_key; | 601 | struct dentry *default_mgmt_key; |
600 | } debugfs; | 602 | } debugfs; |
601 | #endif | 603 | #endif |
@@ -629,6 +631,20 @@ enum queue_stop_reason { | |||
629 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 631 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
630 | }; | 632 | }; |
631 | 633 | ||
634 | #ifdef CONFIG_MAC80211_LEDS | ||
635 | struct tpt_led_trigger { | ||
636 | struct led_trigger trig; | ||
637 | char name[32]; | ||
638 | const struct ieee80211_tpt_blink *blink_table; | ||
639 | unsigned int blink_table_len; | ||
640 | struct timer_list timer; | ||
641 | unsigned long prev_traffic; | ||
642 | unsigned long tx_bytes, rx_bytes; | ||
643 | unsigned int active, want; | ||
644 | bool running; | ||
645 | }; | ||
646 | #endif | ||
647 | |||
632 | /** | 648 | /** |
633 | * mac80211 scan flags - currently active scan mode | 649 | * mac80211 scan flags - currently active scan mode |
634 | * | 650 | * |
@@ -837,6 +853,7 @@ struct ieee80211_local { | |||
837 | #ifdef CONFIG_MAC80211_LEDS | 853 | #ifdef CONFIG_MAC80211_LEDS |
838 | int tx_led_counter, rx_led_counter; | 854 | int tx_led_counter, rx_led_counter; |
839 | struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; | 855 | struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; |
856 | struct tpt_led_trigger *tpt_led_trigger; | ||
840 | char tx_led_name[32], rx_led_name[32], | 857 | char tx_led_name[32], rx_led_name[32], |
841 | assoc_led_name[32], radio_led_name[32]; | 858 | assoc_led_name[32], radio_led_name[32]; |
842 | #endif | 859 | #endif |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index f0f11bb794af..b6db237672ff 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -220,6 +220,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
220 | /* we're brought up, everything changes */ | 220 | /* we're brought up, everything changes */ |
221 | hw_reconf_flags = ~0; | 221 | hw_reconf_flags = ~0; |
222 | ieee80211_led_radio(local, true); | 222 | ieee80211_led_radio(local, true); |
223 | ieee80211_mod_tpt_led_trig(local, | ||
224 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | ||
223 | } | 225 | } |
224 | 226 | ||
225 | /* | 227 | /* |
@@ -1264,6 +1266,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1264 | int count = 0; | 1266 | int count = 0; |
1265 | bool working = false, scanning = false; | 1267 | bool working = false, scanning = false; |
1266 | struct ieee80211_work *wk; | 1268 | struct ieee80211_work *wk; |
1269 | unsigned int led_trig_start = 0, led_trig_stop = 0; | ||
1267 | 1270 | ||
1268 | #ifdef CONFIG_PROVE_LOCKING | 1271 | #ifdef CONFIG_PROVE_LOCKING |
1269 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | 1272 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && |
@@ -1313,6 +1316,18 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1313 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | 1316 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); |
1314 | } | 1317 | } |
1315 | 1318 | ||
1319 | if (working || scanning) | ||
1320 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
1321 | else | ||
1322 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | ||
1323 | |||
1324 | if (count) | ||
1325 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
1326 | else | ||
1327 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | ||
1328 | |||
1329 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | ||
1330 | |||
1316 | if (working) | 1331 | if (working) |
1317 | return ieee80211_idle_off(local, "working"); | 1332 | return ieee80211_idle_off(local, "working"); |
1318 | if (scanning) | 1333 | if (scanning) |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 72df1ca7299b..84cf9196820f 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -178,7 +178,7 @@ void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) | |||
178 | EXPORT_SYMBOL_GPL(ieee80211_key_removed); | 178 | EXPORT_SYMBOL_GPL(ieee80211_key_removed); |
179 | 179 | ||
180 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | 180 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
181 | int idx) | 181 | int idx, bool uni, bool multi) |
182 | { | 182 | { |
183 | struct ieee80211_key *key = NULL; | 183 | struct ieee80211_key *key = NULL; |
184 | 184 | ||
@@ -187,18 +187,19 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | |||
187 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) | 187 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) |
188 | key = sdata->keys[idx]; | 188 | key = sdata->keys[idx]; |
189 | 189 | ||
190 | rcu_assign_pointer(sdata->default_key, key); | 190 | if (uni) |
191 | rcu_assign_pointer(sdata->default_unicast_key, key); | ||
192 | if (multi) | ||
193 | rcu_assign_pointer(sdata->default_multicast_key, key); | ||
191 | 194 | ||
192 | if (key) { | 195 | ieee80211_debugfs_key_update_default(sdata); |
193 | ieee80211_debugfs_key_remove_default(key->sdata); | ||
194 | ieee80211_debugfs_key_add_default(key->sdata); | ||
195 | } | ||
196 | } | 196 | } |
197 | 197 | ||
198 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) | 198 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
199 | bool uni, bool multi) | ||
199 | { | 200 | { |
200 | mutex_lock(&sdata->local->key_mtx); | 201 | mutex_lock(&sdata->local->key_mtx); |
201 | __ieee80211_set_default_key(sdata, idx); | 202 | __ieee80211_set_default_key(sdata, idx, uni, multi); |
202 | mutex_unlock(&sdata->local->key_mtx); | 203 | mutex_unlock(&sdata->local->key_mtx); |
203 | } | 204 | } |
204 | 205 | ||
@@ -215,10 +216,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) | |||
215 | 216 | ||
216 | rcu_assign_pointer(sdata->default_mgmt_key, key); | 217 | rcu_assign_pointer(sdata->default_mgmt_key, key); |
217 | 218 | ||
218 | if (key) { | 219 | ieee80211_debugfs_key_update_default(sdata); |
219 | ieee80211_debugfs_key_remove_mgmt_default(key->sdata); | ||
220 | ieee80211_debugfs_key_add_mgmt_default(key->sdata); | ||
221 | } | ||
222 | } | 220 | } |
223 | 221 | ||
224 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | 222 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, |
@@ -236,7 +234,8 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
236 | struct ieee80211_key *old, | 234 | struct ieee80211_key *old, |
237 | struct ieee80211_key *new) | 235 | struct ieee80211_key *new) |
238 | { | 236 | { |
239 | int idx, defkey, defmgmtkey; | 237 | int idx; |
238 | bool defunikey, defmultikey, defmgmtkey; | ||
240 | 239 | ||
241 | if (new) | 240 | if (new) |
242 | list_add(&new->list, &sdata->key_list); | 241 | list_add(&new->list, &sdata->key_list); |
@@ -257,17 +256,24 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
257 | else | 256 | else |
258 | idx = new->conf.keyidx; | 257 | idx = new->conf.keyidx; |
259 | 258 | ||
260 | defkey = old && sdata->default_key == old; | 259 | defunikey = old && sdata->default_unicast_key == old; |
260 | defmultikey = old && sdata->default_multicast_key == old; | ||
261 | defmgmtkey = old && sdata->default_mgmt_key == old; | 261 | defmgmtkey = old && sdata->default_mgmt_key == old; |
262 | 262 | ||
263 | if (defkey && !new) | 263 | if (defunikey && !new) |
264 | __ieee80211_set_default_key(sdata, -1); | 264 | __ieee80211_set_default_key(sdata, -1, true, false); |
265 | if (defmultikey && !new) | ||
266 | __ieee80211_set_default_key(sdata, -1, false, true); | ||
265 | if (defmgmtkey && !new) | 267 | if (defmgmtkey && !new) |
266 | __ieee80211_set_default_mgmt_key(sdata, -1); | 268 | __ieee80211_set_default_mgmt_key(sdata, -1); |
267 | 269 | ||
268 | rcu_assign_pointer(sdata->keys[idx], new); | 270 | rcu_assign_pointer(sdata->keys[idx], new); |
269 | if (defkey && new) | 271 | if (defunikey && new) |
270 | __ieee80211_set_default_key(sdata, new->conf.keyidx); | 272 | __ieee80211_set_default_key(sdata, new->conf.keyidx, |
273 | true, false); | ||
274 | if (defmultikey && new) | ||
275 | __ieee80211_set_default_key(sdata, new->conf.keyidx, | ||
276 | false, true); | ||
271 | if (defmgmtkey && new) | 277 | if (defmgmtkey && new) |
272 | __ieee80211_set_default_mgmt_key(sdata, | 278 | __ieee80211_set_default_mgmt_key(sdata, |
273 | new->conf.keyidx); | 279 | new->conf.keyidx); |
@@ -509,11 +515,12 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | |||
509 | 515 | ||
510 | mutex_lock(&sdata->local->key_mtx); | 516 | mutex_lock(&sdata->local->key_mtx); |
511 | 517 | ||
512 | ieee80211_debugfs_key_remove_default(sdata); | ||
513 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 518 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
514 | 519 | ||
515 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 520 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
516 | __ieee80211_key_free(key); | 521 | __ieee80211_key_free(key); |
517 | 522 | ||
523 | ieee80211_debugfs_key_update_default(sdata); | ||
524 | |||
518 | mutex_unlock(&sdata->local->key_mtx); | 525 | mutex_unlock(&sdata->local->key_mtx); |
519 | } | 526 | } |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 0db1c0f5f697..8106aa1b7466 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -138,7 +138,8 @@ int __must_check ieee80211_key_link(struct ieee80211_key *key, | |||
138 | struct sta_info *sta); | 138 | struct sta_info *sta); |
139 | void ieee80211_key_free(struct ieee80211_local *local, | 139 | void ieee80211_key_free(struct ieee80211_local *local, |
140 | struct ieee80211_key *key); | 140 | struct ieee80211_key *key); |
141 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); | 141 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
142 | bool uni, bool multi); | ||
142 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | 143 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, |
143 | int idx); | 144 | int idx); |
144 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 145 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/led.c b/net/mac80211/led.c index 063aad944246..4905eb8af572 100644 --- a/net/mac80211/led.c +++ b/net/mac80211/led.c | |||
@@ -54,12 +54,22 @@ void ieee80211_led_radio(struct ieee80211_local *local, bool enabled) | |||
54 | led_trigger_event(local->radio_led, LED_OFF); | 54 | led_trigger_event(local->radio_led, LED_OFF); |
55 | } | 55 | } |
56 | 56 | ||
57 | void ieee80211_led_names(struct ieee80211_local *local) | ||
58 | { | ||
59 | snprintf(local->rx_led_name, sizeof(local->rx_led_name), | ||
60 | "%srx", wiphy_name(local->hw.wiphy)); | ||
61 | snprintf(local->tx_led_name, sizeof(local->tx_led_name), | ||
62 | "%stx", wiphy_name(local->hw.wiphy)); | ||
63 | snprintf(local->assoc_led_name, sizeof(local->assoc_led_name), | ||
64 | "%sassoc", wiphy_name(local->hw.wiphy)); | ||
65 | snprintf(local->radio_led_name, sizeof(local->radio_led_name), | ||
66 | "%sradio", wiphy_name(local->hw.wiphy)); | ||
67 | } | ||
68 | |||
57 | void ieee80211_led_init(struct ieee80211_local *local) | 69 | void ieee80211_led_init(struct ieee80211_local *local) |
58 | { | 70 | { |
59 | local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 71 | local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); |
60 | if (local->rx_led) { | 72 | if (local->rx_led) { |
61 | snprintf(local->rx_led_name, sizeof(local->rx_led_name), | ||
62 | "%srx", wiphy_name(local->hw.wiphy)); | ||
63 | local->rx_led->name = local->rx_led_name; | 73 | local->rx_led->name = local->rx_led_name; |
64 | if (led_trigger_register(local->rx_led)) { | 74 | if (led_trigger_register(local->rx_led)) { |
65 | kfree(local->rx_led); | 75 | kfree(local->rx_led); |
@@ -69,8 +79,6 @@ void ieee80211_led_init(struct ieee80211_local *local) | |||
69 | 79 | ||
70 | local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 80 | local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); |
71 | if (local->tx_led) { | 81 | if (local->tx_led) { |
72 | snprintf(local->tx_led_name, sizeof(local->tx_led_name), | ||
73 | "%stx", wiphy_name(local->hw.wiphy)); | ||
74 | local->tx_led->name = local->tx_led_name; | 82 | local->tx_led->name = local->tx_led_name; |
75 | if (led_trigger_register(local->tx_led)) { | 83 | if (led_trigger_register(local->tx_led)) { |
76 | kfree(local->tx_led); | 84 | kfree(local->tx_led); |
@@ -80,8 +88,6 @@ void ieee80211_led_init(struct ieee80211_local *local) | |||
80 | 88 | ||
81 | local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 89 | local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); |
82 | if (local->assoc_led) { | 90 | if (local->assoc_led) { |
83 | snprintf(local->assoc_led_name, sizeof(local->assoc_led_name), | ||
84 | "%sassoc", wiphy_name(local->hw.wiphy)); | ||
85 | local->assoc_led->name = local->assoc_led_name; | 91 | local->assoc_led->name = local->assoc_led_name; |
86 | if (led_trigger_register(local->assoc_led)) { | 92 | if (led_trigger_register(local->assoc_led)) { |
87 | kfree(local->assoc_led); | 93 | kfree(local->assoc_led); |
@@ -91,14 +97,19 @@ void ieee80211_led_init(struct ieee80211_local *local) | |||
91 | 97 | ||
92 | local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); | 98 | local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); |
93 | if (local->radio_led) { | 99 | if (local->radio_led) { |
94 | snprintf(local->radio_led_name, sizeof(local->radio_led_name), | ||
95 | "%sradio", wiphy_name(local->hw.wiphy)); | ||
96 | local->radio_led->name = local->radio_led_name; | 100 | local->radio_led->name = local->radio_led_name; |
97 | if (led_trigger_register(local->radio_led)) { | 101 | if (led_trigger_register(local->radio_led)) { |
98 | kfree(local->radio_led); | 102 | kfree(local->radio_led); |
99 | local->radio_led = NULL; | 103 | local->radio_led = NULL; |
100 | } | 104 | } |
101 | } | 105 | } |
106 | |||
107 | if (local->tpt_led_trigger) { | ||
108 | if (led_trigger_register(&local->tpt_led_trigger->trig)) { | ||
109 | kfree(local->tpt_led_trigger); | ||
110 | local->tpt_led_trigger = NULL; | ||
111 | } | ||
112 | } | ||
102 | } | 113 | } |
103 | 114 | ||
104 | void ieee80211_led_exit(struct ieee80211_local *local) | 115 | void ieee80211_led_exit(struct ieee80211_local *local) |
@@ -119,15 +130,18 @@ void ieee80211_led_exit(struct ieee80211_local *local) | |||
119 | led_trigger_unregister(local->rx_led); | 130 | led_trigger_unregister(local->rx_led); |
120 | kfree(local->rx_led); | 131 | kfree(local->rx_led); |
121 | } | 132 | } |
133 | |||
134 | if (local->tpt_led_trigger) { | ||
135 | led_trigger_unregister(&local->tpt_led_trigger->trig); | ||
136 | kfree(local->tpt_led_trigger); | ||
137 | } | ||
122 | } | 138 | } |
123 | 139 | ||
124 | char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw) | 140 | char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw) |
125 | { | 141 | { |
126 | struct ieee80211_local *local = hw_to_local(hw); | 142 | struct ieee80211_local *local = hw_to_local(hw); |
127 | 143 | ||
128 | if (local->radio_led) | 144 | return local->radio_led_name; |
129 | return local->radio_led_name; | ||
130 | return NULL; | ||
131 | } | 145 | } |
132 | EXPORT_SYMBOL(__ieee80211_get_radio_led_name); | 146 | EXPORT_SYMBOL(__ieee80211_get_radio_led_name); |
133 | 147 | ||
@@ -135,9 +149,7 @@ char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) | |||
135 | { | 149 | { |
136 | struct ieee80211_local *local = hw_to_local(hw); | 150 | struct ieee80211_local *local = hw_to_local(hw); |
137 | 151 | ||
138 | if (local->assoc_led) | 152 | return local->assoc_led_name; |
139 | return local->assoc_led_name; | ||
140 | return NULL; | ||
141 | } | 153 | } |
142 | EXPORT_SYMBOL(__ieee80211_get_assoc_led_name); | 154 | EXPORT_SYMBOL(__ieee80211_get_assoc_led_name); |
143 | 155 | ||
@@ -145,9 +157,7 @@ char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw) | |||
145 | { | 157 | { |
146 | struct ieee80211_local *local = hw_to_local(hw); | 158 | struct ieee80211_local *local = hw_to_local(hw); |
147 | 159 | ||
148 | if (local->tx_led) | 160 | return local->tx_led_name; |
149 | return local->tx_led_name; | ||
150 | return NULL; | ||
151 | } | 161 | } |
152 | EXPORT_SYMBOL(__ieee80211_get_tx_led_name); | 162 | EXPORT_SYMBOL(__ieee80211_get_tx_led_name); |
153 | 163 | ||
@@ -155,8 +165,144 @@ char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw) | |||
155 | { | 165 | { |
156 | struct ieee80211_local *local = hw_to_local(hw); | 166 | struct ieee80211_local *local = hw_to_local(hw); |
157 | 167 | ||
158 | if (local->rx_led) | 168 | return local->rx_led_name; |
159 | return local->rx_led_name; | ||
160 | return NULL; | ||
161 | } | 169 | } |
162 | EXPORT_SYMBOL(__ieee80211_get_rx_led_name); | 170 | EXPORT_SYMBOL(__ieee80211_get_rx_led_name); |
171 | |||
172 | static unsigned long tpt_trig_traffic(struct ieee80211_local *local, | ||
173 | struct tpt_led_trigger *tpt_trig) | ||
174 | { | ||
175 | unsigned long traffic, delta; | ||
176 | |||
177 | traffic = tpt_trig->tx_bytes + tpt_trig->rx_bytes; | ||
178 | |||
179 | delta = traffic - tpt_trig->prev_traffic; | ||
180 | tpt_trig->prev_traffic = traffic; | ||
181 | return DIV_ROUND_UP(delta, 1024 / 8); | ||
182 | } | ||
183 | |||
184 | static void tpt_trig_timer(unsigned long data) | ||
185 | { | ||
186 | struct ieee80211_local *local = (void *)data; | ||
187 | struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; | ||
188 | struct led_classdev *led_cdev; | ||
189 | unsigned long on, off, tpt; | ||
190 | int i; | ||
191 | |||
192 | if (!tpt_trig->running) | ||
193 | return; | ||
194 | |||
195 | mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ)); | ||
196 | |||
197 | tpt = tpt_trig_traffic(local, tpt_trig); | ||
198 | |||
199 | /* default to just solid on */ | ||
200 | on = 1; | ||
201 | off = 0; | ||
202 | |||
203 | for (i = tpt_trig->blink_table_len - 1; i >= 0; i--) { | ||
204 | if (tpt_trig->blink_table[i].throughput < 0 || | ||
205 | tpt > tpt_trig->blink_table[i].throughput) { | ||
206 | off = tpt_trig->blink_table[i].blink_time / 2; | ||
207 | on = tpt_trig->blink_table[i].blink_time - off; | ||
208 | break; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | read_lock(&tpt_trig->trig.leddev_list_lock); | ||
213 | list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list) | ||
214 | led_blink_set(led_cdev, &on, &off); | ||
215 | read_unlock(&tpt_trig->trig.leddev_list_lock); | ||
216 | } | ||
217 | |||
218 | extern char *__ieee80211_create_tpt_led_trigger( | ||
219 | struct ieee80211_hw *hw, unsigned int flags, | ||
220 | const struct ieee80211_tpt_blink *blink_table, | ||
221 | unsigned int blink_table_len) | ||
222 | { | ||
223 | struct ieee80211_local *local = hw_to_local(hw); | ||
224 | struct tpt_led_trigger *tpt_trig; | ||
225 | |||
226 | if (WARN_ON(local->tpt_led_trigger)) | ||
227 | return NULL; | ||
228 | |||
229 | tpt_trig = kzalloc(sizeof(struct tpt_led_trigger), GFP_KERNEL); | ||
230 | if (!tpt_trig) | ||
231 | return NULL; | ||
232 | |||
233 | snprintf(tpt_trig->name, sizeof(tpt_trig->name), | ||
234 | "%stpt", wiphy_name(local->hw.wiphy)); | ||
235 | |||
236 | tpt_trig->trig.name = tpt_trig->name; | ||
237 | |||
238 | tpt_trig->blink_table = blink_table; | ||
239 | tpt_trig->blink_table_len = blink_table_len; | ||
240 | tpt_trig->want = flags; | ||
241 | |||
242 | setup_timer(&tpt_trig->timer, tpt_trig_timer, (unsigned long)local); | ||
243 | |||
244 | local->tpt_led_trigger = tpt_trig; | ||
245 | |||
246 | return tpt_trig->name; | ||
247 | } | ||
248 | EXPORT_SYMBOL(__ieee80211_create_tpt_led_trigger); | ||
249 | |||
250 | static void ieee80211_start_tpt_led_trig(struct ieee80211_local *local) | ||
251 | { | ||
252 | struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; | ||
253 | |||
254 | if (tpt_trig->running) | ||
255 | return; | ||
256 | |||
257 | /* reset traffic */ | ||
258 | tpt_trig_traffic(local, tpt_trig); | ||
259 | tpt_trig->running = true; | ||
260 | |||
261 | tpt_trig_timer((unsigned long)local); | ||
262 | mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ)); | ||
263 | } | ||
264 | |||
265 | static void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local) | ||
266 | { | ||
267 | struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; | ||
268 | struct led_classdev *led_cdev; | ||
269 | |||
270 | if (!tpt_trig->running) | ||
271 | return; | ||
272 | |||
273 | tpt_trig->running = false; | ||
274 | del_timer_sync(&tpt_trig->timer); | ||
275 | |||
276 | read_lock(&tpt_trig->trig.leddev_list_lock); | ||
277 | list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list) | ||
278 | led_brightness_set(led_cdev, LED_OFF); | ||
279 | read_unlock(&tpt_trig->trig.leddev_list_lock); | ||
280 | } | ||
281 | |||
282 | void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, | ||
283 | unsigned int types_on, unsigned int types_off) | ||
284 | { | ||
285 | struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; | ||
286 | bool allowed; | ||
287 | |||
288 | WARN_ON(types_on & types_off); | ||
289 | |||
290 | if (!tpt_trig) | ||
291 | return; | ||
292 | |||
293 | tpt_trig->active &= ~types_off; | ||
294 | tpt_trig->active |= types_on; | ||
295 | |||
296 | /* | ||
297 | * Regardless of wanted state, we shouldn't blink when | ||
298 | * the radio is disabled -- this can happen due to some | ||
299 | * code ordering issues with __ieee80211_recalc_idle() | ||
300 | * being called before the radio is started. | ||
301 | */ | ||
302 | allowed = tpt_trig->active & IEEE80211_TPT_LEDTRIG_FL_RADIO; | ||
303 | |||
304 | if (!allowed || !(tpt_trig->active & tpt_trig->want)) | ||
305 | ieee80211_stop_tpt_led_trig(local); | ||
306 | else | ||
307 | ieee80211_start_tpt_led_trig(local); | ||
308 | } | ||
diff --git a/net/mac80211/led.h b/net/mac80211/led.h index 77b1e1ba6039..e0275d9befa8 100644 --- a/net/mac80211/led.h +++ b/net/mac80211/led.h | |||
@@ -12,14 +12,17 @@ | |||
12 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
13 | 13 | ||
14 | #ifdef CONFIG_MAC80211_LEDS | 14 | #ifdef CONFIG_MAC80211_LEDS |
15 | extern void ieee80211_led_rx(struct ieee80211_local *local); | 15 | void ieee80211_led_rx(struct ieee80211_local *local); |
16 | extern void ieee80211_led_tx(struct ieee80211_local *local, int q); | 16 | void ieee80211_led_tx(struct ieee80211_local *local, int q); |
17 | extern void ieee80211_led_assoc(struct ieee80211_local *local, | 17 | void ieee80211_led_assoc(struct ieee80211_local *local, |
18 | bool associated); | 18 | bool associated); |
19 | extern void ieee80211_led_radio(struct ieee80211_local *local, | 19 | void ieee80211_led_radio(struct ieee80211_local *local, |
20 | bool enabled); | 20 | bool enabled); |
21 | extern void ieee80211_led_init(struct ieee80211_local *local); | 21 | void ieee80211_led_names(struct ieee80211_local *local); |
22 | extern void ieee80211_led_exit(struct ieee80211_local *local); | 22 | void ieee80211_led_init(struct ieee80211_local *local); |
23 | void ieee80211_led_exit(struct ieee80211_local *local); | ||
24 | void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, | ||
25 | unsigned int types_on, unsigned int types_off); | ||
23 | #else | 26 | #else |
24 | static inline void ieee80211_led_rx(struct ieee80211_local *local) | 27 | static inline void ieee80211_led_rx(struct ieee80211_local *local) |
25 | { | 28 | { |
@@ -35,10 +38,36 @@ static inline void ieee80211_led_radio(struct ieee80211_local *local, | |||
35 | bool enabled) | 38 | bool enabled) |
36 | { | 39 | { |
37 | } | 40 | } |
41 | static inline void ieee80211_led_names(struct ieee80211_local *local) | ||
42 | { | ||
43 | } | ||
38 | static inline void ieee80211_led_init(struct ieee80211_local *local) | 44 | static inline void ieee80211_led_init(struct ieee80211_local *local) |
39 | { | 45 | { |
40 | } | 46 | } |
41 | static inline void ieee80211_led_exit(struct ieee80211_local *local) | 47 | static inline void ieee80211_led_exit(struct ieee80211_local *local) |
42 | { | 48 | { |
43 | } | 49 | } |
50 | static inline void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, | ||
51 | unsigned int types_on, | ||
52 | unsigned int types_off) | ||
53 | { | ||
54 | } | ||
55 | #endif | ||
56 | |||
57 | static inline void | ||
58 | ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes) | ||
59 | { | ||
60 | #ifdef CONFIG_MAC80211_LEDS | ||
61 | if (local->tpt_led_trigger && ieee80211_is_data(fc)) | ||
62 | local->tpt_led_trigger->tx_bytes += bytes; | ||
63 | #endif | ||
64 | } | ||
65 | |||
66 | static inline void | ||
67 | ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes) | ||
68 | { | ||
69 | #ifdef CONFIG_MAC80211_LEDS | ||
70 | if (local->tpt_led_trigger && ieee80211_is_data(fc)) | ||
71 | local->tpt_led_trigger->rx_bytes += bytes; | ||
44 | #endif | 72 | #endif |
73 | } | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 973fee9f7d69..bbe8e0ac6e52 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -484,6 +484,10 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
484 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | 484 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | |
485 | BIT(IEEE80211_STYPE_ACTION >> 4), | 485 | BIT(IEEE80211_STYPE_ACTION >> 4), |
486 | }, | 486 | }, |
487 | [NL80211_IFTYPE_MESH_POINT] = { | ||
488 | .tx = 0xffff, | ||
489 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4), | ||
490 | }, | ||
487 | }; | 491 | }; |
488 | 492 | ||
489 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 493 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
@@ -517,10 +521,15 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
517 | 521 | ||
518 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; | 522 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; |
519 | 523 | ||
524 | wiphy->privid = mac80211_wiphy_privid; | ||
525 | |||
520 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 526 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
521 | WIPHY_FLAG_4ADDR_AP | | 527 | WIPHY_FLAG_4ADDR_AP | |
522 | WIPHY_FLAG_4ADDR_STATION; | 528 | WIPHY_FLAG_4ADDR_STATION | |
523 | wiphy->privid = mac80211_wiphy_privid; | 529 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS; |
530 | |||
531 | if (!ops->set_key) | ||
532 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
524 | 533 | ||
525 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss); | 534 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss); |
526 | 535 | ||
@@ -596,6 +605,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
596 | /* init dummy netdev for use w/ NAPI */ | 605 | /* init dummy netdev for use w/ NAPI */ |
597 | init_dummy_netdev(&local->napi_dev); | 606 | init_dummy_netdev(&local->napi_dev); |
598 | 607 | ||
608 | ieee80211_led_names(local); | ||
609 | |||
599 | return local_to_hw(local); | 610 | return local_to_hw(local); |
600 | } | 611 | } |
601 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 612 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
@@ -740,6 +751,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
740 | } | 751 | } |
741 | } | 752 | } |
742 | 753 | ||
754 | local->hw.wiphy->max_remain_on_channel_duration = 5000; | ||
755 | |||
743 | result = wiphy_register(local->hw.wiphy); | 756 | result = wiphy_register(local->hw.wiphy); |
744 | if (result < 0) | 757 | if (result < 0) |
745 | goto fail_wiphy_register; | 758 | goto fail_wiphy_register; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 63e1188d5062..ca3af4685b0a 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -124,15 +124,6 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
124 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); | 124 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); |
125 | } | 125 | } |
126 | 126 | ||
127 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) | ||
128 | { | ||
129 | sta->mesh_pp_id = 0; /* HWMP */ | ||
130 | sta->mesh_pm_id = 0; /* Airtime */ | ||
131 | sta->mesh_cc_id = 0; /* Disabled */ | ||
132 | sta->mesh_sp_id = 0; /* Neighbor Offset */ | ||
133 | sta->mesh_auth_id = 0; /* Disabled */ | ||
134 | } | ||
135 | |||
136 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 127 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
137 | { | 128 | { |
138 | int i; | 129 | int i; |
@@ -287,6 +278,13 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
287 | *pos++ |= sdata->u.mesh.accepting_plinks ? | 278 | *pos++ |= sdata->u.mesh.accepting_plinks ? |
288 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 279 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
289 | *pos++ = 0x00; | 280 | *pos++ = 0x00; |
281 | |||
282 | if (sdata->u.mesh.vendor_ie) { | ||
283 | int len = sdata->u.mesh.vendor_ie_len; | ||
284 | const u8 *data = sdata->u.mesh.vendor_ie; | ||
285 | if (skb_tailroom(skb) > len) | ||
286 | memcpy(skb_put(skb, len), data, len); | ||
287 | } | ||
290 | } | 288 | } |
291 | 289 | ||
292 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) | 290 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) |
@@ -412,39 +410,33 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | |||
412 | * ieee80211_new_mesh_header - create a new mesh header | 410 | * ieee80211_new_mesh_header - create a new mesh header |
413 | * @meshhdr: uninitialized mesh header | 411 | * @meshhdr: uninitialized mesh header |
414 | * @sdata: mesh interface to be used | 412 | * @sdata: mesh interface to be used |
415 | * @addr4: addr4 of the mesh frame (1st in ae header) | 413 | * @addr4or5: 1st address in the ae header, which may correspond to address 4 |
416 | * may be NULL | 414 | * (if addr6 is NULL) or address 5 (if addr6 is present). It may |
417 | * @addr5: addr5 of the mesh frame (1st or 2nd in ae header) | 415 | * be NULL. |
418 | * may be NULL unless addr6 is present | 416 | * @addr6: 2nd address in the ae header, which corresponds to addr6 of the |
419 | * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header) | 417 | * mesh frame |
420 | * may be NULL unless addr5 is present | ||
421 | * | 418 | * |
422 | * Return the header length. | 419 | * Return the header length. |
423 | */ | 420 | */ |
424 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 421 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
425 | struct ieee80211_sub_if_data *sdata, char *addr4, | 422 | struct ieee80211_sub_if_data *sdata, char *addr4or5, |
426 | char *addr5, char *addr6) | 423 | char *addr6) |
427 | { | 424 | { |
428 | int aelen = 0; | 425 | int aelen = 0; |
426 | BUG_ON(!addr4or5 && addr6); | ||
429 | memset(meshhdr, 0, sizeof(*meshhdr)); | 427 | memset(meshhdr, 0, sizeof(*meshhdr)); |
430 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 428 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
431 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); | 429 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); |
432 | sdata->u.mesh.mesh_seqnum++; | 430 | sdata->u.mesh.mesh_seqnum++; |
433 | if (addr4) { | 431 | if (addr4or5 && !addr6) { |
434 | meshhdr->flags |= MESH_FLAGS_AE_A4; | 432 | meshhdr->flags |= MESH_FLAGS_AE_A4; |
435 | aelen += ETH_ALEN; | 433 | aelen += ETH_ALEN; |
436 | memcpy(meshhdr->eaddr1, addr4, ETH_ALEN); | 434 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
437 | } | 435 | } else if (addr4or5 && addr6) { |
438 | if (addr5 && addr6) { | ||
439 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; | 436 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; |
440 | aelen += 2 * ETH_ALEN; | 437 | aelen += 2 * ETH_ALEN; |
441 | if (!addr4) { | 438 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
442 | memcpy(meshhdr->eaddr1, addr5, ETH_ALEN); | 439 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); |
443 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); | ||
444 | } else { | ||
445 | memcpy(meshhdr->eaddr2, addr5, ETH_ALEN); | ||
446 | memcpy(meshhdr->eaddr3, addr6, ETH_ALEN); | ||
447 | } | ||
448 | } | 440 | } |
449 | return 6 + aelen; | 441 | return 6 + aelen; |
450 | } | 442 | } |
@@ -518,6 +510,9 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
518 | atomic_inc(&local->iff_allmultis); | 510 | atomic_inc(&local->iff_allmultis); |
519 | ieee80211_configure_filter(local); | 511 | ieee80211_configure_filter(local); |
520 | 512 | ||
513 | ifmsh->mesh_cc_id = 0; /* Disabled */ | ||
514 | ifmsh->mesh_sp_id = 0; /* Neighbor Offset */ | ||
515 | ifmsh->mesh_auth_id = 0; /* Disabled */ | ||
521 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 516 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
522 | ieee80211_mesh_root_setup(ifmsh); | 517 | ieee80211_mesh_root_setup(ifmsh); |
523 | ieee80211_queue_work(&local->hw, &sdata->work); | 518 | ieee80211_queue_work(&local->hw, &sdata->work); |
@@ -688,7 +683,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
688 | /* Allocate all mesh structures when creating the first mesh interface. */ | 683 | /* Allocate all mesh structures when creating the first mesh interface. */ |
689 | if (!mesh_allocated) | 684 | if (!mesh_allocated) |
690 | ieee80211s_init(); | 685 | ieee80211s_init(); |
691 | mesh_ids_set_default(ifmsh); | ||
692 | setup_timer(&ifmsh->mesh_path_timer, | 686 | setup_timer(&ifmsh->mesh_path_timer, |
693 | ieee80211_mesh_path_timer, | 687 | ieee80211_mesh_path_timer, |
694 | (unsigned long) sdata); | 688 | (unsigned long) sdata); |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 039d7fa0af74..b99e230fe31c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -164,17 +164,6 @@ struct mesh_rmc { | |||
164 | }; | 164 | }; |
165 | 165 | ||
166 | 166 | ||
167 | /* | ||
168 | * MESH_CFG_COMP_LEN Includes: | ||
169 | * - Active path selection protocol ID. | ||
170 | * - Active path selection metric ID. | ||
171 | * - Congestion control mode identifier. | ||
172 | * - Channel precedence. | ||
173 | * Does not include mesh capabilities, which may vary across nodes in the same | ||
174 | * mesh | ||
175 | */ | ||
176 | #define MESH_CFG_CMP_LEN (IEEE80211_MESH_CONFIG_LEN - 2) | ||
177 | |||
178 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ | 167 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ |
179 | 168 | ||
180 | #define MESH_PATH_EXPIRE (600 * HZ) | 169 | #define MESH_PATH_EXPIRE (600 * HZ) |
@@ -198,8 +187,8 @@ struct mesh_rmc { | |||
198 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 187 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
199 | const u8 *da, const u8 *sa); | 188 | const u8 *da, const u8 *sa); |
200 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 189 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
201 | struct ieee80211_sub_if_data *sdata, char *addr4, | 190 | struct ieee80211_sub_if_data *sdata, char *addr4or5, |
202 | char *addr5, char *addr6); | 191 | char *addr6); |
203 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | 192 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, |
204 | struct ieee80211_sub_if_data *sdata); | 193 | struct ieee80211_sub_if_data *sdata); |
205 | bool mesh_matches_local(struct ieee802_11_elems *ie, | 194 | bool mesh_matches_local(struct ieee802_11_elems *ie, |
@@ -295,6 +284,11 @@ static inline void mesh_path_activate(struct mesh_path *mpath) | |||
295 | mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED; | 284 | mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED; |
296 | } | 285 | } |
297 | 286 | ||
287 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | ||
288 | { | ||
289 | return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP; | ||
290 | } | ||
291 | |||
298 | #define for_each_mesh_entry(x, p, node, i) \ | 292 | #define for_each_mesh_entry(x, p, node, i) \ |
299 | for (i = 0; i <= x->hash_mask; i++) \ | 293 | for (i = 0; i <= x->hash_mask; i++) \ |
300 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) | 294 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) |
@@ -315,6 +309,8 @@ static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | |||
315 | {} | 309 | {} |
316 | static inline void mesh_plink_quiesce(struct sta_info *sta) {} | 310 | static inline void mesh_plink_quiesce(struct sta_info *sta) {} |
317 | static inline void mesh_plink_restart(struct sta_info *sta) {} | 311 | static inline void mesh_plink_restart(struct sta_info *sta) {} |
312 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | ||
313 | { return false; } | ||
318 | #endif | 314 | #endif |
319 | 315 | ||
320 | #endif /* IEEE80211S_H */ | 316 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 1c91f0f3c307..44b53931ba5e 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -160,7 +160,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
160 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, | 160 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, |
161 | __le16 reason) { | 161 | __le16 reason) { |
162 | struct ieee80211_local *local = sdata->local; | 162 | struct ieee80211_local *local = sdata->local; |
163 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 163 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + |
164 | sdata->u.mesh.vendor_ie_len); | ||
164 | struct ieee80211_mgmt *mgmt; | 165 | struct ieee80211_mgmt *mgmt; |
165 | bool include_plid = false; | 166 | bool include_plid = false; |
166 | static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; | 167 | static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 4ad7a362fcc1..165a4518bb48 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -374,7 +374,7 @@ minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, stru | |||
374 | if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) | 374 | if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) |
375 | return; | 375 | return; |
376 | 376 | ||
377 | ieee80211_start_tx_ba_session(pubsta, tid); | 377 | ieee80211_start_tx_ba_session(pubsta, tid, 5000); |
378 | } | 378 | } |
379 | 379 | ||
380 | static void | 380 | static void |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2fe8f5f86499..01a3f2630eaf 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -955,12 +955,31 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
955 | * have been expected. | 955 | * have been expected. |
956 | */ | 956 | */ |
957 | struct ieee80211_key *key = NULL; | 957 | struct ieee80211_key *key = NULL; |
958 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
959 | int i; | ||
960 | |||
958 | if (ieee80211_is_mgmt(fc) && | 961 | if (ieee80211_is_mgmt(fc) && |
959 | is_multicast_ether_addr(hdr->addr1) && | 962 | is_multicast_ether_addr(hdr->addr1) && |
960 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) | 963 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) |
961 | rx->key = key; | 964 | rx->key = key; |
962 | else if ((key = rcu_dereference(rx->sdata->default_key))) | 965 | else { |
963 | rx->key = key; | 966 | if (rx->sta) { |
967 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
968 | key = rcu_dereference(rx->sta->gtk[i]); | ||
969 | if (key) | ||
970 | break; | ||
971 | } | ||
972 | } | ||
973 | if (!key) { | ||
974 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
975 | key = rcu_dereference(sdata->keys[i]); | ||
976 | if (key) | ||
977 | break; | ||
978 | } | ||
979 | } | ||
980 | if (key) | ||
981 | rx->key = key; | ||
982 | } | ||
964 | return RX_CONTINUE; | 983 | return RX_CONTINUE; |
965 | } else { | 984 | } else { |
966 | u8 keyid; | 985 | u8 keyid; |
@@ -1521,12 +1540,30 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | |||
1521 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1540 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1522 | if (unlikely(!ieee80211_has_protected(fc) && | 1541 | if (unlikely(!ieee80211_has_protected(fc) && |
1523 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1542 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && |
1524 | rx->key)) | 1543 | rx->key)) { |
1544 | if (ieee80211_is_deauth(fc)) | ||
1545 | cfg80211_send_unprot_deauth(rx->sdata->dev, | ||
1546 | rx->skb->data, | ||
1547 | rx->skb->len); | ||
1548 | else if (ieee80211_is_disassoc(fc)) | ||
1549 | cfg80211_send_unprot_disassoc(rx->sdata->dev, | ||
1550 | rx->skb->data, | ||
1551 | rx->skb->len); | ||
1525 | return -EACCES; | 1552 | return -EACCES; |
1553 | } | ||
1526 | /* BIP does not use Protected field, so need to check MMIE */ | 1554 | /* BIP does not use Protected field, so need to check MMIE */ |
1527 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | 1555 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && |
1528 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) | 1556 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) { |
1557 | if (ieee80211_is_deauth(fc)) | ||
1558 | cfg80211_send_unprot_deauth(rx->sdata->dev, | ||
1559 | rx->skb->data, | ||
1560 | rx->skb->len); | ||
1561 | else if (ieee80211_is_disassoc(fc)) | ||
1562 | cfg80211_send_unprot_disassoc(rx->sdata->dev, | ||
1563 | rx->skb->data, | ||
1564 | rx->skb->len); | ||
1529 | return -EACCES; | 1565 | return -EACCES; |
1566 | } | ||
1530 | /* | 1567 | /* |
1531 | * When using MFP, Action frames are not allowed prior to | 1568 | * When using MFP, Action frames are not allowed prior to |
1532 | * having configured keys. | 1569 | * having configured keys. |
@@ -2124,10 +2161,13 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2124 | } | 2161 | } |
2125 | break; | 2162 | break; |
2126 | case WLAN_CATEGORY_MESH_PLINK: | 2163 | case WLAN_CATEGORY_MESH_PLINK: |
2127 | case WLAN_CATEGORY_MESH_PATH_SEL: | ||
2128 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2164 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2129 | break; | 2165 | break; |
2130 | goto queue; | 2166 | goto queue; |
2167 | case WLAN_CATEGORY_MESH_PATH_SEL: | ||
2168 | if (!mesh_path_sel_is_hwmp(sdata)) | ||
2169 | break; | ||
2170 | goto queue; | ||
2131 | } | 2171 | } |
2132 | 2172 | ||
2133 | return RX_CONTINUE; | 2173 | return RX_CONTINUE; |
@@ -2888,6 +2928,9 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2888 | return; | 2928 | return; |
2889 | } | 2929 | } |
2890 | 2930 | ||
2931 | ieee80211_tpt_led_trig_rx(local, | ||
2932 | ((struct ieee80211_hdr *)skb->data)->frame_control, | ||
2933 | skb->len); | ||
2891 | __ieee80211_rx_handle_packet(hw, skb); | 2934 | __ieee80211_rx_handle_packet(hw, skb); |
2892 | 2935 | ||
2893 | rcu_read_unlock(); | 2936 | rcu_read_unlock(); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index fdca52cf88de..bbdd2a86a94b 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -78,6 +78,7 @@ enum ieee80211_sta_info_flags { | |||
78 | * @addba_resp_timer: timer for peer's response to addba request | 78 | * @addba_resp_timer: timer for peer's response to addba request |
79 | * @pending: pending frames queue -- use sta's spinlock to protect | 79 | * @pending: pending frames queue -- use sta's spinlock to protect |
80 | * @dialog_token: dialog token for aggregation session | 80 | * @dialog_token: dialog token for aggregation session |
81 | * @timeout: session timeout value to be filled in ADDBA requests | ||
81 | * @state: session state (see above) | 82 | * @state: session state (see above) |
82 | * @stop_initiator: initiator of a session stop | 83 | * @stop_initiator: initiator of a session stop |
83 | * @tx_stop: TX DelBA frame when stopping | 84 | * @tx_stop: TX DelBA frame when stopping |
@@ -96,6 +97,7 @@ struct tid_ampdu_tx { | |||
96 | struct timer_list addba_resp_timer; | 97 | struct timer_list addba_resp_timer; |
97 | struct sk_buff_head pending; | 98 | struct sk_buff_head pending; |
98 | unsigned long state; | 99 | unsigned long state; |
100 | u16 timeout; | ||
99 | u8 dialog_token; | 101 | u8 dialog_token; |
100 | u8 stop_initiator; | 102 | u8 stop_initiator; |
101 | bool tx_stop; | 103 | bool tx_stop; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0ee56bb0ea7e..68c2fbd16ebb 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -539,7 +539,11 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
539 | ieee80211_is_robust_mgmt_frame(hdr) && | 539 | ieee80211_is_robust_mgmt_frame(hdr) && |
540 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | 540 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) |
541 | tx->key = key; | 541 | tx->key = key; |
542 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 542 | else if (is_multicast_ether_addr(hdr->addr1) && |
543 | (key = rcu_dereference(tx->sdata->default_multicast_key))) | ||
544 | tx->key = key; | ||
545 | else if (!is_multicast_ether_addr(hdr->addr1) && | ||
546 | (key = rcu_dereference(tx->sdata->default_unicast_key))) | ||
543 | tx->key = key; | 547 | tx->key = key; |
544 | else if (tx->sdata->drop_unencrypted && | 548 | else if (tx->sdata->drop_unencrypted && |
545 | (tx->skb->protocol != tx->sdata->control_port_protocol) && | 549 | (tx->skb->protocol != tx->sdata->control_port_protocol) && |
@@ -1293,6 +1297,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1293 | 1297 | ||
1294 | while (skb) { | 1298 | while (skb) { |
1295 | int q = skb_get_queue_mapping(skb); | 1299 | int q = skb_get_queue_mapping(skb); |
1300 | __le16 fc; | ||
1296 | 1301 | ||
1297 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 1302 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
1298 | ret = IEEE80211_TX_OK; | 1303 | ret = IEEE80211_TX_OK; |
@@ -1335,6 +1340,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1335 | else | 1340 | else |
1336 | info->control.sta = NULL; | 1341 | info->control.sta = NULL; |
1337 | 1342 | ||
1343 | fc = ((struct ieee80211_hdr *)skb->data)->frame_control; | ||
1338 | ret = drv_tx(local, skb); | 1344 | ret = drv_tx(local, skb); |
1339 | if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { | 1345 | if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { |
1340 | dev_kfree_skb(skb); | 1346 | dev_kfree_skb(skb); |
@@ -1345,6 +1351,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1345 | return IEEE80211_TX_AGAIN; | 1351 | return IEEE80211_TX_AGAIN; |
1346 | } | 1352 | } |
1347 | 1353 | ||
1354 | ieee80211_tpt_led_trig_tx(local, fc, len); | ||
1348 | *skbp = skb = next; | 1355 | *skbp = skb = next; |
1349 | ieee80211_led_tx(local, 1); | 1356 | ieee80211_led_tx(local, 1); |
1350 | fragm = true; | 1357 | fragm = true; |
@@ -1542,8 +1549,10 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1542 | 1549 | ||
1543 | if (skb_header_cloned(skb)) | 1550 | if (skb_header_cloned(skb)) |
1544 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | 1551 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); |
1545 | else | 1552 | else if (head_need || tail_need) |
1546 | I802_DEBUG_INC(local->tx_expand_skb_head); | 1553 | I802_DEBUG_INC(local->tx_expand_skb_head); |
1554 | else | ||
1555 | return 0; | ||
1547 | 1556 | ||
1548 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { | 1557 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { |
1549 | wiphy_debug(local->hw.wiphy, | 1558 | wiphy_debug(local->hw.wiphy, |
@@ -1735,7 +1744,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1735 | { | 1744 | { |
1736 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1745 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1737 | struct ieee80211_local *local = sdata->local; | 1746 | struct ieee80211_local *local = sdata->local; |
1738 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1747 | struct ieee80211_tx_info *info; |
1739 | int ret = NETDEV_TX_BUSY, head_need; | 1748 | int ret = NETDEV_TX_BUSY, head_need; |
1740 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1749 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1741 | __le16 fc; | 1750 | __le16 fc; |
@@ -1807,7 +1816,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1807 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1816 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1808 | skb->data, skb->data + ETH_ALEN); | 1817 | skb->data, skb->data + ETH_ALEN); |
1809 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1818 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1810 | sdata, NULL, NULL, NULL); | 1819 | sdata, NULL, NULL); |
1811 | } else { | 1820 | } else { |
1812 | /* packet from other interface */ | 1821 | /* packet from other interface */ |
1813 | struct mesh_path *mppath; | 1822 | struct mesh_path *mppath; |
@@ -1840,13 +1849,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1840 | ieee80211_new_mesh_header(&mesh_hdr, | 1849 | ieee80211_new_mesh_header(&mesh_hdr, |
1841 | sdata, | 1850 | sdata, |
1842 | skb->data + ETH_ALEN, | 1851 | skb->data + ETH_ALEN, |
1843 | NULL, | ||
1844 | NULL); | 1852 | NULL); |
1845 | else | 1853 | else |
1846 | meshhdrlen = | 1854 | meshhdrlen = |
1847 | ieee80211_new_mesh_header(&mesh_hdr, | 1855 | ieee80211_new_mesh_header(&mesh_hdr, |
1848 | sdata, | 1856 | sdata, |
1849 | NULL, | ||
1850 | skb->data, | 1857 | skb->data, |
1851 | skb->data + ETH_ALEN); | 1858 | skb->data + ETH_ALEN); |
1852 | 1859 | ||
@@ -1930,7 +1937,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1930 | */ | 1937 | */ |
1931 | if (skb_shared(skb)) { | 1938 | if (skb_shared(skb)) { |
1932 | tmp_skb = skb; | 1939 | tmp_skb = skb; |
1933 | skb = skb_copy(skb, GFP_ATOMIC); | 1940 | skb = skb_clone(skb, GFP_ATOMIC); |
1934 | kfree_skb(tmp_skb); | 1941 | kfree_skb(tmp_skb); |
1935 | 1942 | ||
1936 | if (!skb) { | 1943 | if (!skb) { |
@@ -2026,6 +2033,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2026 | skb_set_network_header(skb, nh_pos); | 2033 | skb_set_network_header(skb, nh_pos); |
2027 | skb_set_transport_header(skb, h_pos); | 2034 | skb_set_transport_header(skb, h_pos); |
2028 | 2035 | ||
2036 | info = IEEE80211_SKB_CB(skb); | ||
2029 | memset(info, 0, sizeof(*info)); | 2037 | memset(info, 0, sizeof(*info)); |
2030 | 2038 | ||
2031 | dev->trans_start = jiffies; | 2039 | dev->trans_start = jiffies; |
@@ -2286,7 +2294,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2286 | u8 *pos; | 2294 | u8 *pos; |
2287 | 2295 | ||
2288 | /* headroom, head length, tail length and maximum TIM length */ | 2296 | /* headroom, head length, tail length and maximum TIM length */ |
2289 | skb = dev_alloc_skb(local->tx_headroom + 400); | 2297 | skb = dev_alloc_skb(local->tx_headroom + 400 + |
2298 | sdata->u.mesh.vendor_ie_len); | ||
2290 | if (!skb) | 2299 | if (!skb) |
2291 | goto out; | 2300 | goto out; |
2292 | 2301 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e497476174ce..cf68700abffa 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1116,6 +1116,7 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
1116 | void ieee80211_stop_device(struct ieee80211_local *local) | 1116 | void ieee80211_stop_device(struct ieee80211_local *local) |
1117 | { | 1117 | { |
1118 | ieee80211_led_radio(local, false); | 1118 | ieee80211_led_radio(local, false); |
1119 | ieee80211_mod_tpt_led_trig(local, 0, IEEE80211_TPT_LEDTRIG_FL_RADIO); | ||
1119 | 1120 | ||
1120 | cancel_work_sync(&local->reconfig_filter); | 1121 | cancel_work_sync(&local->reconfig_filter); |
1121 | 1122 | ||
@@ -1150,6 +1151,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1150 | } | 1151 | } |
1151 | 1152 | ||
1152 | ieee80211_led_radio(local, true); | 1153 | ieee80211_led_radio(local, true); |
1154 | ieee80211_mod_tpt_led_trig(local, | ||
1155 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | ||
1153 | } | 1156 | } |
1154 | 1157 | ||
1155 | /* add interfaces */ | 1158 | /* add interfaces */ |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 79772fcc37bc..e9a5f8ca4c27 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -789,13 +789,23 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
789 | cfg80211_mgd_wext_connect(rdev, wdev); | 789 | cfg80211_mgd_wext_connect(rdev, wdev); |
790 | break; | 790 | break; |
791 | #endif | 791 | #endif |
792 | #ifdef CONFIG_MAC80211_MESH | ||
792 | case NL80211_IFTYPE_MESH_POINT: | 793 | case NL80211_IFTYPE_MESH_POINT: |
793 | /* backward compat code ... */ | 794 | { |
794 | if (wdev->mesh_id_up_len) | 795 | /* backward compat code... */ |
795 | __cfg80211_join_mesh(rdev, dev, wdev->ssid, | 796 | struct mesh_setup setup; |
796 | wdev->mesh_id_up_len, | 797 | memcpy(&setup, &default_mesh_setup, |
797 | &default_mesh_config); | 798 | sizeof(setup)); |
798 | break; | 799 | /* back compat only needed for mesh_id */ |
800 | setup.mesh_id = wdev->ssid; | ||
801 | setup.mesh_id_len = wdev->mesh_id_up_len; | ||
802 | if (wdev->mesh_id_up_len) | ||
803 | __cfg80211_join_mesh(rdev, dev, | ||
804 | &setup, | ||
805 | &default_mesh_config); | ||
806 | break; | ||
807 | } | ||
808 | #endif | ||
799 | default: | 809 | default: |
800 | break; | 810 | break; |
801 | } | 811 | } |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 743203bb61ac..26a0a084e16b 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -287,13 +287,14 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
287 | 287 | ||
288 | /* mesh */ | 288 | /* mesh */ |
289 | extern const struct mesh_config default_mesh_config; | 289 | extern const struct mesh_config default_mesh_config; |
290 | extern const struct mesh_setup default_mesh_setup; | ||
290 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 291 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
291 | struct net_device *dev, | 292 | struct net_device *dev, |
292 | const u8 *mesh_id, u8 mesh_id_len, | 293 | const struct mesh_setup *setup, |
293 | const struct mesh_config *conf); | 294 | const struct mesh_config *conf); |
294 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 295 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
295 | struct net_device *dev, | 296 | struct net_device *dev, |
296 | const u8 *mesh_id, u8 mesh_id_len, | 297 | const struct mesh_setup *setup, |
297 | const struct mesh_config *conf); | 298 | const struct mesh_config *conf); |
298 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 299 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
299 | struct net_device *dev); | 300 | struct net_device *dev); |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index e0b9747fe50a..73e39c171ffb 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -50,17 +50,19 @@ const struct mesh_config default_mesh_config = { | |||
50 | .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, | 50 | .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, |
51 | }; | 51 | }; |
52 | 52 | ||
53 | const struct mesh_setup default_mesh_setup = { | ||
54 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, | ||
55 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, | ||
56 | .vendor_ie = NULL, | ||
57 | .vendor_ie_len = 0, | ||
58 | }; | ||
53 | 59 | ||
54 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 60 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
55 | struct net_device *dev, | 61 | struct net_device *dev, |
56 | const u8 *mesh_id, u8 mesh_id_len, | 62 | const struct mesh_setup *setup, |
57 | const struct mesh_config *conf) | 63 | const struct mesh_config *conf) |
58 | { | 64 | { |
59 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 65 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
60 | struct mesh_setup setup = { | ||
61 | .mesh_id = mesh_id, | ||
62 | .mesh_id_len = mesh_id_len, | ||
63 | }; | ||
64 | int err; | 66 | int err; |
65 | 67 | ||
66 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN); | 68 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN); |
@@ -73,16 +75,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
73 | if (wdev->mesh_id_len) | 75 | if (wdev->mesh_id_len) |
74 | return -EALREADY; | 76 | return -EALREADY; |
75 | 77 | ||
76 | if (!mesh_id_len) | 78 | if (!setup->mesh_id_len) |
77 | return -EINVAL; | 79 | return -EINVAL; |
78 | 80 | ||
79 | if (!rdev->ops->join_mesh) | 81 | if (!rdev->ops->join_mesh) |
80 | return -EOPNOTSUPP; | 82 | return -EOPNOTSUPP; |
81 | 83 | ||
82 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, &setup); | 84 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); |
83 | if (!err) { | 85 | if (!err) { |
84 | memcpy(wdev->ssid, mesh_id, mesh_id_len); | 86 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); |
85 | wdev->mesh_id_len = mesh_id_len; | 87 | wdev->mesh_id_len = setup->mesh_id_len; |
86 | } | 88 | } |
87 | 89 | ||
88 | return err; | 90 | return err; |
@@ -90,14 +92,14 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
90 | 92 | ||
91 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 93 | int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
92 | struct net_device *dev, | 94 | struct net_device *dev, |
93 | const u8 *mesh_id, u8 mesh_id_len, | 95 | const struct mesh_setup *setup, |
94 | const struct mesh_config *conf) | 96 | const struct mesh_config *conf) |
95 | { | 97 | { |
96 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 98 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
97 | int err; | 99 | int err; |
98 | 100 | ||
99 | wdev_lock(wdev); | 101 | wdev_lock(wdev); |
100 | err = __cfg80211_join_mesh(rdev, dev, mesh_id, mesh_id_len, conf); | 102 | err = __cfg80211_join_mesh(rdev, dev, setup, conf); |
101 | wdev_unlock(wdev); | 103 | wdev_unlock(wdev); |
102 | 104 | ||
103 | return err; | 105 | return err; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index d7680f2a4c5b..aa5df8865ff7 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -263,6 +263,28 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | |||
263 | } | 263 | } |
264 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 264 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
265 | 265 | ||
266 | void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, | ||
267 | size_t len) | ||
268 | { | ||
269 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
270 | struct wiphy *wiphy = wdev->wiphy; | ||
271 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
272 | |||
273 | nl80211_send_unprot_deauth(rdev, dev, buf, len, GFP_ATOMIC); | ||
274 | } | ||
275 | EXPORT_SYMBOL(cfg80211_send_unprot_deauth); | ||
276 | |||
277 | void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, | ||
278 | size_t len) | ||
279 | { | ||
280 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
281 | struct wiphy *wiphy = wdev->wiphy; | ||
282 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
283 | |||
284 | nl80211_send_unprot_disassoc(rdev, dev, buf, len, GFP_ATOMIC); | ||
285 | } | ||
286 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | ||
287 | |||
266 | static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) | 288 | static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) |
267 | { | 289 | { |
268 | int i; | 290 | int i; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c3f80e565365..9b62710891a2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -123,7 +123,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
123 | .len = NL80211_MAX_SUPP_RATES }, | 123 | .len = NL80211_MAX_SUPP_RATES }, |
124 | [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 }, | 124 | [NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 }, |
125 | 125 | ||
126 | [NL80211_ATTR_MESH_PARAMS] = { .type = NLA_NESTED }, | 126 | [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED }, |
127 | 127 | ||
128 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, | 128 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, |
129 | .len = NL80211_HT_CAPABILITY_LEN }, | 129 | .len = NL80211_HT_CAPABILITY_LEN }, |
@@ -171,6 +171,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
171 | [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 }, | 171 | [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 }, |
172 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, | 172 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, |
173 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, | 173 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, |
174 | [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, | ||
174 | }; | 175 | }; |
175 | 176 | ||
176 | /* policy for the key attributes */ | 177 | /* policy for the key attributes */ |
@@ -182,6 +183,14 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { | |||
182 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, | 183 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, |
183 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, | 184 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, |
184 | [NL80211_KEY_TYPE] = { .type = NLA_U32 }, | 185 | [NL80211_KEY_TYPE] = { .type = NLA_U32 }, |
186 | [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, | ||
187 | }; | ||
188 | |||
189 | /* policy for the key default flags */ | ||
190 | static const struct nla_policy | ||
191 | nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = { | ||
192 | [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG }, | ||
193 | [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG }, | ||
185 | }; | 194 | }; |
186 | 195 | ||
187 | /* ifidx get helper */ | 196 | /* ifidx get helper */ |
@@ -314,6 +323,7 @@ struct key_parse { | |||
314 | int idx; | 323 | int idx; |
315 | int type; | 324 | int type; |
316 | bool def, defmgmt; | 325 | bool def, defmgmt; |
326 | bool def_uni, def_multi; | ||
317 | }; | 327 | }; |
318 | 328 | ||
319 | static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | 329 | static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) |
@@ -327,6 +337,13 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | |||
327 | k->def = !!tb[NL80211_KEY_DEFAULT]; | 337 | k->def = !!tb[NL80211_KEY_DEFAULT]; |
328 | k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; | 338 | k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; |
329 | 339 | ||
340 | if (k->def) { | ||
341 | k->def_uni = true; | ||
342 | k->def_multi = true; | ||
343 | } | ||
344 | if (k->defmgmt) | ||
345 | k->def_multi = true; | ||
346 | |||
330 | if (tb[NL80211_KEY_IDX]) | 347 | if (tb[NL80211_KEY_IDX]) |
331 | k->idx = nla_get_u8(tb[NL80211_KEY_IDX]); | 348 | k->idx = nla_get_u8(tb[NL80211_KEY_IDX]); |
332 | 349 | ||
@@ -349,6 +366,19 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | |||
349 | return -EINVAL; | 366 | return -EINVAL; |
350 | } | 367 | } |
351 | 368 | ||
369 | if (tb[NL80211_KEY_DEFAULT_TYPES]) { | ||
370 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; | ||
371 | int err = nla_parse_nested(kdt, | ||
372 | NUM_NL80211_KEY_DEFAULT_TYPES - 1, | ||
373 | tb[NL80211_KEY_DEFAULT_TYPES], | ||
374 | nl80211_key_default_policy); | ||
375 | if (err) | ||
376 | return err; | ||
377 | |||
378 | k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST]; | ||
379 | k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST]; | ||
380 | } | ||
381 | |||
352 | return 0; | 382 | return 0; |
353 | } | 383 | } |
354 | 384 | ||
@@ -373,12 +403,32 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k) | |||
373 | k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; | 403 | k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; |
374 | k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; | 404 | k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; |
375 | 405 | ||
406 | if (k->def) { | ||
407 | k->def_uni = true; | ||
408 | k->def_multi = true; | ||
409 | } | ||
410 | if (k->defmgmt) | ||
411 | k->def_multi = true; | ||
412 | |||
376 | if (info->attrs[NL80211_ATTR_KEY_TYPE]) { | 413 | if (info->attrs[NL80211_ATTR_KEY_TYPE]) { |
377 | k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); | 414 | k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); |
378 | if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) | 415 | if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) |
379 | return -EINVAL; | 416 | return -EINVAL; |
380 | } | 417 | } |
381 | 418 | ||
419 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) { | ||
420 | struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; | ||
421 | int err = nla_parse_nested( | ||
422 | kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1, | ||
423 | info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES], | ||
424 | nl80211_key_default_policy); | ||
425 | if (err) | ||
426 | return err; | ||
427 | |||
428 | k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST]; | ||
429 | k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST]; | ||
430 | } | ||
431 | |||
382 | return 0; | 432 | return 0; |
383 | } | 433 | } |
384 | 434 | ||
@@ -401,6 +451,11 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k) | |||
401 | if (k->def && k->defmgmt) | 451 | if (k->def && k->defmgmt) |
402 | return -EINVAL; | 452 | return -EINVAL; |
403 | 453 | ||
454 | if (k->defmgmt) { | ||
455 | if (k->def_uni || !k->def_multi) | ||
456 | return -EINVAL; | ||
457 | } | ||
458 | |||
404 | if (k->idx != -1) { | 459 | if (k->idx != -1) { |
405 | if (k->defmgmt) { | 460 | if (k->defmgmt) { |
406 | if (k->idx < 4 || k->idx > 5) | 461 | if (k->idx < 4 || k->idx > 5) |
@@ -450,6 +505,8 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, | |||
450 | goto error; | 505 | goto error; |
451 | def = 1; | 506 | def = 1; |
452 | result->def = parse.idx; | 507 | result->def = parse.idx; |
508 | if (!parse.def_uni || !parse.def_multi) | ||
509 | goto error; | ||
453 | } else if (parse.defmgmt) | 510 | } else if (parse.defmgmt) |
454 | goto error; | 511 | goto error; |
455 | err = cfg80211_validate_key_settings(rdev, &parse.p, | 512 | err = cfg80211_validate_key_settings(rdev, &parse.p, |
@@ -548,7 +605,13 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
548 | if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) | 605 | if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) |
549 | NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); | 606 | NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE); |
550 | 607 | ||
551 | if (dev->ops->get_antenna) { | 608 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, |
609 | dev->wiphy.available_antennas_tx); | ||
610 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, | ||
611 | dev->wiphy.available_antennas_rx); | ||
612 | |||
613 | if ((dev->wiphy.available_antennas_tx || | ||
614 | dev->wiphy.available_antennas_rx) && dev->ops->get_antenna) { | ||
552 | u32 tx_ant = 0, rx_ant = 0; | 615 | u32 tx_ant = 0, rx_ant = 0; |
553 | int res; | 616 | int res; |
554 | res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant); | 617 | res = dev->ops->get_antenna(&dev->wiphy, &tx_ant, &rx_ant); |
@@ -662,7 +725,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
662 | CMD(add_beacon, NEW_BEACON); | 725 | CMD(add_beacon, NEW_BEACON); |
663 | CMD(add_station, NEW_STATION); | 726 | CMD(add_station, NEW_STATION); |
664 | CMD(add_mpath, NEW_MPATH); | 727 | CMD(add_mpath, NEW_MPATH); |
665 | CMD(update_mesh_params, SET_MESH_PARAMS); | 728 | CMD(update_mesh_config, SET_MESH_CONFIG); |
666 | CMD(change_bss, SET_BSS); | 729 | CMD(change_bss, SET_BSS); |
667 | CMD(auth, AUTHENTICATE); | 730 | CMD(auth, AUTHENTICATE); |
668 | CMD(assoc, ASSOCIATE); | 731 | CMD(assoc, ASSOCIATE); |
@@ -698,6 +761,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
698 | 761 | ||
699 | nla_nest_end(msg, nl_cmds); | 762 | nla_nest_end(msg, nl_cmds); |
700 | 763 | ||
764 | if (dev->ops->remain_on_channel) | ||
765 | NLA_PUT_U32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, | ||
766 | dev->wiphy.max_remain_on_channel_duration); | ||
767 | |||
701 | /* for now at least assume all drivers have it */ | 768 | /* for now at least assume all drivers have it */ |
702 | if (dev->ops->mgmt_tx) | 769 | if (dev->ops->mgmt_tx) |
703 | NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); | 770 | NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); |
@@ -1046,7 +1113,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1046 | if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && | 1113 | if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && |
1047 | info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { | 1114 | info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { |
1048 | u32 tx_ant, rx_ant; | 1115 | u32 tx_ant, rx_ant; |
1049 | if (!rdev->ops->set_antenna) { | 1116 | if ((!rdev->wiphy.available_antennas_tx && |
1117 | !rdev->wiphy.available_antennas_rx) || | ||
1118 | !rdev->ops->set_antenna) { | ||
1050 | result = -EOPNOTSUPP; | 1119 | result = -EOPNOTSUPP; |
1051 | goto bad_res; | 1120 | goto bad_res; |
1052 | } | 1121 | } |
@@ -1054,6 +1123,17 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1054 | tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]); | 1123 | tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]); |
1055 | rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); | 1124 | rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); |
1056 | 1125 | ||
1126 | /* reject antenna configurations which don't match the | ||
1127 | * available antenna masks, except for the "all" mask */ | ||
1128 | if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) || | ||
1129 | (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) { | ||
1130 | result = -EINVAL; | ||
1131 | goto bad_res; | ||
1132 | } | ||
1133 | |||
1134 | tx_ant = tx_ant & rdev->wiphy.available_antennas_tx; | ||
1135 | rx_ant = rx_ant & rdev->wiphy.available_antennas_rx; | ||
1136 | |||
1057 | result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant); | 1137 | result = rdev->ops->set_antenna(&rdev->wiphy, tx_ant, rx_ant); |
1058 | if (result) | 1138 | if (result) |
1059 | goto bad_res; | 1139 | goto bad_res; |
@@ -1575,8 +1655,6 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1575 | struct key_parse key; | 1655 | struct key_parse key; |
1576 | int err; | 1656 | int err; |
1577 | struct net_device *dev = info->user_ptr[1]; | 1657 | struct net_device *dev = info->user_ptr[1]; |
1578 | int (*func)(struct wiphy *wiphy, struct net_device *netdev, | ||
1579 | u8 key_index); | ||
1580 | 1658 | ||
1581 | err = nl80211_parse_key(info, &key); | 1659 | err = nl80211_parse_key(info, &key); |
1582 | if (err) | 1660 | if (err) |
@@ -1589,27 +1667,61 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1589 | if (!key.def && !key.defmgmt) | 1667 | if (!key.def && !key.defmgmt) |
1590 | return -EINVAL; | 1668 | return -EINVAL; |
1591 | 1669 | ||
1592 | if (key.def) | 1670 | wdev_lock(dev->ieee80211_ptr); |
1593 | func = rdev->ops->set_default_key; | ||
1594 | else | ||
1595 | func = rdev->ops->set_default_mgmt_key; | ||
1596 | 1671 | ||
1597 | if (!func) | 1672 | if (key.def) { |
1598 | return -EOPNOTSUPP; | 1673 | if (!rdev->ops->set_default_key) { |
1674 | err = -EOPNOTSUPP; | ||
1675 | goto out; | ||
1676 | } | ||
1599 | 1677 | ||
1600 | wdev_lock(dev->ieee80211_ptr); | 1678 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
1601 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 1679 | if (err) |
1602 | if (!err) | 1680 | goto out; |
1603 | err = func(&rdev->wiphy, dev, key.idx); | 1681 | |
1682 | if (!(rdev->wiphy.flags & | ||
1683 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) { | ||
1684 | if (!key.def_uni || !key.def_multi) { | ||
1685 | err = -EOPNOTSUPP; | ||
1686 | goto out; | ||
1687 | } | ||
1688 | } | ||
1689 | |||
1690 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx, | ||
1691 | key.def_uni, key.def_multi); | ||
1692 | |||
1693 | if (err) | ||
1694 | goto out; | ||
1604 | 1695 | ||
1605 | #ifdef CONFIG_CFG80211_WEXT | 1696 | #ifdef CONFIG_CFG80211_WEXT |
1606 | if (!err) { | 1697 | dev->ieee80211_ptr->wext.default_key = key.idx; |
1607 | if (func == rdev->ops->set_default_key) | ||
1608 | dev->ieee80211_ptr->wext.default_key = key.idx; | ||
1609 | else | ||
1610 | dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; | ||
1611 | } | ||
1612 | #endif | 1698 | #endif |
1699 | } else { | ||
1700 | if (key.def_uni || !key.def_multi) { | ||
1701 | err = -EINVAL; | ||
1702 | goto out; | ||
1703 | } | ||
1704 | |||
1705 | if (!rdev->ops->set_default_mgmt_key) { | ||
1706 | err = -EOPNOTSUPP; | ||
1707 | goto out; | ||
1708 | } | ||
1709 | |||
1710 | err = nl80211_key_allowed(dev->ieee80211_ptr); | ||
1711 | if (err) | ||
1712 | goto out; | ||
1713 | |||
1714 | err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, | ||
1715 | dev, key.idx); | ||
1716 | if (err) | ||
1717 | goto out; | ||
1718 | |||
1719 | #ifdef CONFIG_CFG80211_WEXT | ||
1720 | dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; | ||
1721 | #endif | ||
1722 | } | ||
1723 | |||
1724 | out: | ||
1613 | wdev_unlock(dev->ieee80211_ptr); | 1725 | wdev_unlock(dev->ieee80211_ptr); |
1614 | 1726 | ||
1615 | return err; | 1727 | return err; |
@@ -2569,7 +2681,7 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
2569 | return r; | 2681 | return r; |
2570 | } | 2682 | } |
2571 | 2683 | ||
2572 | static int nl80211_get_mesh_params(struct sk_buff *skb, | 2684 | static int nl80211_get_mesh_config(struct sk_buff *skb, |
2573 | struct genl_info *info) | 2685 | struct genl_info *info) |
2574 | { | 2686 | { |
2575 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2687 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -2584,7 +2696,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
2584 | if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) | 2696 | if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) |
2585 | return -EOPNOTSUPP; | 2697 | return -EOPNOTSUPP; |
2586 | 2698 | ||
2587 | if (!rdev->ops->get_mesh_params) | 2699 | if (!rdev->ops->get_mesh_config) |
2588 | return -EOPNOTSUPP; | 2700 | return -EOPNOTSUPP; |
2589 | 2701 | ||
2590 | wdev_lock(wdev); | 2702 | wdev_lock(wdev); |
@@ -2592,7 +2704,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
2592 | if (!wdev->mesh_id_len) | 2704 | if (!wdev->mesh_id_len) |
2593 | memcpy(&cur_params, &default_mesh_config, sizeof(cur_params)); | 2705 | memcpy(&cur_params, &default_mesh_config, sizeof(cur_params)); |
2594 | else | 2706 | else |
2595 | err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, | 2707 | err = rdev->ops->get_mesh_config(&rdev->wiphy, dev, |
2596 | &cur_params); | 2708 | &cur_params); |
2597 | wdev_unlock(wdev); | 2709 | wdev_unlock(wdev); |
2598 | 2710 | ||
@@ -2604,10 +2716,10 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
2604 | if (!msg) | 2716 | if (!msg) |
2605 | return -ENOMEM; | 2717 | return -ENOMEM; |
2606 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 2718 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
2607 | NL80211_CMD_GET_MESH_PARAMS); | 2719 | NL80211_CMD_GET_MESH_CONFIG); |
2608 | if (!hdr) | 2720 | if (!hdr) |
2609 | goto nla_put_failure; | 2721 | goto nla_put_failure; |
2610 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS); | 2722 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); |
2611 | if (!pinfoattr) | 2723 | if (!pinfoattr) |
2612 | goto nla_put_failure; | 2724 | goto nla_put_failure; |
2613 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 2725 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
@@ -2669,7 +2781,15 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
2669 | [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, | 2781 | [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, |
2670 | }; | 2782 | }; |
2671 | 2783 | ||
2672 | static int nl80211_parse_mesh_params(struct genl_info *info, | 2784 | static const struct nla_policy |
2785 | nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { | ||
2786 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, | ||
2787 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, | ||
2788 | [NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY, | ||
2789 | .len = IEEE80211_MAX_DATA_LEN }, | ||
2790 | }; | ||
2791 | |||
2792 | static int nl80211_parse_mesh_config(struct genl_info *info, | ||
2673 | struct mesh_config *cfg, | 2793 | struct mesh_config *cfg, |
2674 | u32 *mask_out) | 2794 | u32 *mask_out) |
2675 | { | 2795 | { |
@@ -2685,10 +2805,10 @@ do {\ | |||
2685 | } while (0);\ | 2805 | } while (0);\ |
2686 | 2806 | ||
2687 | 2807 | ||
2688 | if (!info->attrs[NL80211_ATTR_MESH_PARAMS]) | 2808 | if (!info->attrs[NL80211_ATTR_MESH_CONFIG]) |
2689 | return -EINVAL; | 2809 | return -EINVAL; |
2690 | if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX, | 2810 | if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX, |
2691 | info->attrs[NL80211_ATTR_MESH_PARAMS], | 2811 | info->attrs[NL80211_ATTR_MESH_CONFIG], |
2692 | nl80211_meshconf_params_policy)) | 2812 | nl80211_meshconf_params_policy)) |
2693 | return -EINVAL; | 2813 | return -EINVAL; |
2694 | 2814 | ||
@@ -2735,15 +2855,51 @@ do {\ | |||
2735 | dot11MeshHWMPRootMode, mask, | 2855 | dot11MeshHWMPRootMode, mask, |
2736 | NL80211_MESHCONF_HWMP_ROOTMODE, | 2856 | NL80211_MESHCONF_HWMP_ROOTMODE, |
2737 | nla_get_u8); | 2857 | nla_get_u8); |
2738 | |||
2739 | if (mask_out) | 2858 | if (mask_out) |
2740 | *mask_out = mask; | 2859 | *mask_out = mask; |
2860 | |||
2741 | return 0; | 2861 | return 0; |
2742 | 2862 | ||
2743 | #undef FILL_IN_MESH_PARAM_IF_SET | 2863 | #undef FILL_IN_MESH_PARAM_IF_SET |
2744 | } | 2864 | } |
2745 | 2865 | ||
2746 | static int nl80211_update_mesh_params(struct sk_buff *skb, | 2866 | static int nl80211_parse_mesh_setup(struct genl_info *info, |
2867 | struct mesh_setup *setup) | ||
2868 | { | ||
2869 | struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1]; | ||
2870 | |||
2871 | if (!info->attrs[NL80211_ATTR_MESH_SETUP]) | ||
2872 | return -EINVAL; | ||
2873 | if (nla_parse_nested(tb, NL80211_MESH_SETUP_ATTR_MAX, | ||
2874 | info->attrs[NL80211_ATTR_MESH_SETUP], | ||
2875 | nl80211_mesh_setup_params_policy)) | ||
2876 | return -EINVAL; | ||
2877 | |||
2878 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL]) | ||
2879 | setup->path_sel_proto = | ||
2880 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ? | ||
2881 | IEEE80211_PATH_PROTOCOL_VENDOR : | ||
2882 | IEEE80211_PATH_PROTOCOL_HWMP; | ||
2883 | |||
2884 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC]) | ||
2885 | setup->path_metric = | ||
2886 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ? | ||
2887 | IEEE80211_PATH_METRIC_VENDOR : | ||
2888 | IEEE80211_PATH_METRIC_AIRTIME; | ||
2889 | |||
2890 | if (tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]) { | ||
2891 | struct nlattr *ieattr = | ||
2892 | tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]; | ||
2893 | if (!is_valid_ie_attr(ieattr)) | ||
2894 | return -EINVAL; | ||
2895 | setup->vendor_ie = nla_data(ieattr); | ||
2896 | setup->vendor_ie_len = nla_len(ieattr); | ||
2897 | } | ||
2898 | |||
2899 | return 0; | ||
2900 | } | ||
2901 | |||
2902 | static int nl80211_update_mesh_config(struct sk_buff *skb, | ||
2747 | struct genl_info *info) | 2903 | struct genl_info *info) |
2748 | { | 2904 | { |
2749 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2905 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -2756,10 +2912,10 @@ static int nl80211_update_mesh_params(struct sk_buff *skb, | |||
2756 | if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) | 2912 | if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) |
2757 | return -EOPNOTSUPP; | 2913 | return -EOPNOTSUPP; |
2758 | 2914 | ||
2759 | if (!rdev->ops->update_mesh_params) | 2915 | if (!rdev->ops->update_mesh_config) |
2760 | return -EOPNOTSUPP; | 2916 | return -EOPNOTSUPP; |
2761 | 2917 | ||
2762 | err = nl80211_parse_mesh_params(info, &cfg, &mask); | 2918 | err = nl80211_parse_mesh_config(info, &cfg, &mask); |
2763 | if (err) | 2919 | if (err) |
2764 | return err; | 2920 | return err; |
2765 | 2921 | ||
@@ -2768,7 +2924,7 @@ static int nl80211_update_mesh_params(struct sk_buff *skb, | |||
2768 | err = -ENOLINK; | 2924 | err = -ENOLINK; |
2769 | 2925 | ||
2770 | if (!err) | 2926 | if (!err) |
2771 | err = rdev->ops->update_mesh_params(&rdev->wiphy, dev, | 2927 | err = rdev->ops->update_mesh_config(&rdev->wiphy, dev, |
2772 | mask, &cfg); | 2928 | mask, &cfg); |
2773 | 2929 | ||
2774 | wdev_unlock(wdev); | 2930 | wdev_unlock(wdev); |
@@ -4128,7 +4284,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, | |||
4128 | * We should be on that channel for at least one jiffie, | 4284 | * We should be on that channel for at least one jiffie, |
4129 | * and more than 5 seconds seems excessive. | 4285 | * and more than 5 seconds seems excessive. |
4130 | */ | 4286 | */ |
4131 | if (!duration || !msecs_to_jiffies(duration) || duration > 5000) | 4287 | if (!duration || !msecs_to_jiffies(duration) || |
4288 | duration > rdev->wiphy.max_remain_on_channel_duration) | ||
4132 | return -EINVAL; | 4289 | return -EINVAL; |
4133 | 4290 | ||
4134 | if (!rdev->ops->remain_on_channel) | 4291 | if (!rdev->ops->remain_on_channel) |
@@ -4296,6 +4453,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4296 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && | 4453 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && |
4297 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 4454 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
4298 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 4455 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
4456 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && | ||
4299 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 4457 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
4300 | return -EOPNOTSUPP; | 4458 | return -EOPNOTSUPP; |
4301 | 4459 | ||
@@ -4336,6 +4494,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4336 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && | 4494 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && |
4337 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 4495 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
4338 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 4496 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
4497 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && | ||
4339 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 4498 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
4340 | return -EOPNOTSUPP; | 4499 | return -EOPNOTSUPP; |
4341 | 4500 | ||
@@ -4562,14 +4721,16 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
4562 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4721 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
4563 | struct net_device *dev = info->user_ptr[1]; | 4722 | struct net_device *dev = info->user_ptr[1]; |
4564 | struct mesh_config cfg; | 4723 | struct mesh_config cfg; |
4724 | struct mesh_setup setup; | ||
4565 | int err; | 4725 | int err; |
4566 | 4726 | ||
4567 | /* start with default */ | 4727 | /* start with default */ |
4568 | memcpy(&cfg, &default_mesh_config, sizeof(cfg)); | 4728 | memcpy(&cfg, &default_mesh_config, sizeof(cfg)); |
4729 | memcpy(&setup, &default_mesh_setup, sizeof(setup)); | ||
4569 | 4730 | ||
4570 | if (info->attrs[NL80211_ATTR_MESH_PARAMS]) { | 4731 | if (info->attrs[NL80211_ATTR_MESH_CONFIG]) { |
4571 | /* and parse parameters if given */ | 4732 | /* and parse parameters if given */ |
4572 | err = nl80211_parse_mesh_params(info, &cfg, NULL); | 4733 | err = nl80211_parse_mesh_config(info, &cfg, NULL); |
4573 | if (err) | 4734 | if (err) |
4574 | return err; | 4735 | return err; |
4575 | } | 4736 | } |
@@ -4578,10 +4739,17 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
4578 | !nla_len(info->attrs[NL80211_ATTR_MESH_ID])) | 4739 | !nla_len(info->attrs[NL80211_ATTR_MESH_ID])) |
4579 | return -EINVAL; | 4740 | return -EINVAL; |
4580 | 4741 | ||
4581 | return cfg80211_join_mesh(rdev, dev, | 4742 | setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
4582 | nla_data(info->attrs[NL80211_ATTR_MESH_ID]), | 4743 | setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
4583 | nla_len(info->attrs[NL80211_ATTR_MESH_ID]), | 4744 | |
4584 | &cfg); | 4745 | if (info->attrs[NL80211_ATTR_MESH_SETUP]) { |
4746 | /* parse additional setup parameters if given */ | ||
4747 | err = nl80211_parse_mesh_setup(info, &setup); | ||
4748 | if (err) | ||
4749 | return err; | ||
4750 | } | ||
4751 | |||
4752 | return cfg80211_join_mesh(rdev, dev, &setup, &cfg); | ||
4585 | } | 4753 | } |
4586 | 4754 | ||
4587 | static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) | 4755 | static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) |
@@ -4847,16 +5015,16 @@ static struct genl_ops nl80211_ops[] = { | |||
4847 | .flags = GENL_ADMIN_PERM, | 5015 | .flags = GENL_ADMIN_PERM, |
4848 | }, | 5016 | }, |
4849 | { | 5017 | { |
4850 | .cmd = NL80211_CMD_GET_MESH_PARAMS, | 5018 | .cmd = NL80211_CMD_GET_MESH_CONFIG, |
4851 | .doit = nl80211_get_mesh_params, | 5019 | .doit = nl80211_get_mesh_config, |
4852 | .policy = nl80211_policy, | 5020 | .policy = nl80211_policy, |
4853 | /* can be retrieved by unprivileged users */ | 5021 | /* can be retrieved by unprivileged users */ |
4854 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 5022 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
4855 | NL80211_FLAG_NEED_RTNL, | 5023 | NL80211_FLAG_NEED_RTNL, |
4856 | }, | 5024 | }, |
4857 | { | 5025 | { |
4858 | .cmd = NL80211_CMD_SET_MESH_PARAMS, | 5026 | .cmd = NL80211_CMD_SET_MESH_CONFIG, |
4859 | .doit = nl80211_update_mesh_params, | 5027 | .doit = nl80211_update_mesh_config, |
4860 | .policy = nl80211_policy, | 5028 | .policy = nl80211_policy, |
4861 | .flags = GENL_ADMIN_PERM, | 5029 | .flags = GENL_ADMIN_PERM, |
4862 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5030 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
@@ -5368,6 +5536,22 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | |||
5368 | NL80211_CMD_DISASSOCIATE, gfp); | 5536 | NL80211_CMD_DISASSOCIATE, gfp); |
5369 | } | 5537 | } |
5370 | 5538 | ||
5539 | void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, | ||
5540 | struct net_device *netdev, const u8 *buf, | ||
5541 | size_t len, gfp_t gfp) | ||
5542 | { | ||
5543 | nl80211_send_mlme_event(rdev, netdev, buf, len, | ||
5544 | NL80211_CMD_UNPROT_DEAUTHENTICATE, gfp); | ||
5545 | } | ||
5546 | |||
5547 | void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, | ||
5548 | struct net_device *netdev, const u8 *buf, | ||
5549 | size_t len, gfp_t gfp) | ||
5550 | { | ||
5551 | nl80211_send_mlme_event(rdev, netdev, buf, len, | ||
5552 | NL80211_CMD_UNPROT_DISASSOCIATE, gfp); | ||
5553 | } | ||
5554 | |||
5371 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, | 5555 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, |
5372 | struct net_device *netdev, int cmd, | 5556 | struct net_device *netdev, int cmd, |
5373 | const u8 *addr, gfp_t gfp) | 5557 | const u8 *addr, gfp_t gfp) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 16c2f7190768..e3f7fa886966 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -25,6 +25,12 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev, | |||
25 | void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | 25 | void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, |
26 | struct net_device *netdev, | 26 | struct net_device *netdev, |
27 | const u8 *buf, size_t len, gfp_t gfp); | 27 | const u8 *buf, size_t len, gfp_t gfp); |
28 | void nl80211_send_unprot_deauth(struct cfg80211_registered_device *rdev, | ||
29 | struct net_device *netdev, | ||
30 | const u8 *buf, size_t len, gfp_t gfp); | ||
31 | void nl80211_send_unprot_disassoc(struct cfg80211_registered_device *rdev, | ||
32 | struct net_device *netdev, | ||
33 | const u8 *buf, size_t len, gfp_t gfp); | ||
28 | void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, | 34 | void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev, |
29 | struct net_device *netdev, | 35 | struct net_device *netdev, |
30 | const u8 *addr, gfp_t gfp); | 36 | const u8 *addr, gfp_t gfp); |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5ed615f94e0c..99d41831d76e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -661,7 +661,8 @@ static int freq_reg_info_regd(struct wiphy *wiphy, | |||
661 | * Follow the driver's regulatory domain, if present, unless a country | 661 | * Follow the driver's regulatory domain, if present, unless a country |
662 | * IE has been processed or a user wants to help complaince further | 662 | * IE has been processed or a user wants to help complaince further |
663 | */ | 663 | */ |
664 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | 664 | if (!custom_regd && |
665 | last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
665 | last_request->initiator != NL80211_REGDOM_SET_BY_USER && | 666 | last_request->initiator != NL80211_REGDOM_SET_BY_USER && |
666 | wiphy->regd) | 667 | wiphy->regd) |
667 | regd = wiphy->regd; | 668 | regd = wiphy->regd; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 503ebb86ba18..ea427f418f64 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -464,6 +464,9 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
464 | if (res->pub.beacon_ies) { | 464 | if (res->pub.beacon_ies) { |
465 | size_t used = dev->wiphy.bss_priv_size + sizeof(*res); | 465 | size_t used = dev->wiphy.bss_priv_size + sizeof(*res); |
466 | size_t ielen = res->pub.len_beacon_ies; | 466 | size_t ielen = res->pub.len_beacon_ies; |
467 | bool information_elements_is_beacon_ies = | ||
468 | (found->pub.information_elements == | ||
469 | found->pub.beacon_ies); | ||
467 | 470 | ||
468 | if (found->pub.beacon_ies && | 471 | if (found->pub.beacon_ies && |
469 | !found->beacon_ies_allocated && | 472 | !found->beacon_ies_allocated && |
@@ -487,6 +490,14 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
487 | found->pub.len_beacon_ies = ielen; | 490 | found->pub.len_beacon_ies = ielen; |
488 | } | 491 | } |
489 | } | 492 | } |
493 | |||
494 | /* Override IEs if they were from a beacon before */ | ||
495 | if (information_elements_is_beacon_ies) { | ||
496 | found->pub.information_elements = | ||
497 | found->pub.beacon_ies; | ||
498 | found->pub.len_information_elements = | ||
499 | found->pub.len_beacon_ies; | ||
500 | } | ||
490 | } | 501 | } |
491 | 502 | ||
492 | kref_put(&res->ref, bss_release); | 503 | kref_put(&res->ref, bss_release); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 4de624ca4c63..7620ae2fcf18 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -689,7 +689,8 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) | |||
689 | continue; | 689 | continue; |
690 | } | 690 | } |
691 | if (wdev->connect_keys->def == i) | 691 | if (wdev->connect_keys->def == i) |
692 | if (rdev->ops->set_default_key(wdev->wiphy, dev, i)) { | 692 | if (rdev->ops->set_default_key(wdev->wiphy, dev, |
693 | i, true, true)) { | ||
693 | netdev_err(dev, "failed to set defkey %d\n", i); | 694 | netdev_err(dev, "failed to set defkey %d\n", i); |
694 | continue; | 695 | continue; |
695 | } | 696 | } |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 12222ee6ebf2..3e5dbd4e4cd5 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -548,8 +548,8 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
548 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); | 548 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); |
549 | rejoin = true; | 549 | rejoin = true; |
550 | } | 550 | } |
551 | err = rdev->ops->set_default_key(&rdev->wiphy, | 551 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, |
552 | dev, idx); | 552 | idx, true, true); |
553 | } | 553 | } |
554 | if (!err) { | 554 | if (!err) { |
555 | wdev->wext.default_key = idx; | 555 | wdev->wext.default_key = idx; |
@@ -627,8 +627,8 @@ int cfg80211_wext_siwencode(struct net_device *dev, | |||
627 | err = 0; | 627 | err = 0; |
628 | wdev_lock(wdev); | 628 | wdev_lock(wdev); |
629 | if (wdev->current_bss) | 629 | if (wdev->current_bss) |
630 | err = rdev->ops->set_default_key(&rdev->wiphy, | 630 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, |
631 | dev, idx); | 631 | idx, true, true); |
632 | if (!err) | 632 | if (!err) |
633 | wdev->wext.default_key = idx; | 633 | wdev->wext.default_key = idx; |
634 | wdev_unlock(wdev); | 634 | wdev_unlock(wdev); |