aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-04-25 14:34:25 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-25 14:34:25 -0400
commitcfef6047c4027a8448ec8dafeaf2bb362cc882e4 (patch)
treec254bd25aa8b4b0696b5b5cc45d8e30c7c1bb9dd /net/mac80211
parentb71d1d426d263b0b6cb5760322efebbfc89d4463 (diff)
parent73b48099cc265f88fa1255f3f43e52fe6a94fd5c (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: drivers/net/wireless/iwlwifi/iwl-core.c drivers/net/wireless/rt2x00/rt2x00queue.c drivers/net/wireless/rt2x00/rt2x00queue.h
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c29
-rw-r--r--net/mac80211/debugfs_sta.c26
-rw-r--r--net/mac80211/driver-ops.h13
-rw-r--r--net/mac80211/driver-trace.h20
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/main.c9
-rw-r--r--net/mac80211/mesh.c14
-rw-r--r--net/mac80211/mesh.h3
-rw-r--r--net/mac80211/mesh_pathtbl.c49
-rw-r--r--net/mac80211/mesh_plink.c35
-rw-r--r--net/mac80211/mlme.c17
-rw-r--r--net/mac80211/rx.c26
-rw-r--r--net/mac80211/sta_info.c16
-rw-r--r--net/mac80211/sta_info.h5
-rw-r--r--net/mac80211/tx.c2
15 files changed, 203 insertions, 66 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index bf5d28da46e6..a6d191f2a0fe 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -330,6 +330,7 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in
330static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) 330static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
331{ 331{
332 struct ieee80211_sub_if_data *sdata = sta->sdata; 332 struct ieee80211_sub_if_data *sdata = sta->sdata;
333 struct timespec uptime;
333 334
334 sinfo->generation = sdata->local->sta_generation; 335 sinfo->generation = sdata->local->sta_generation;
335 336
@@ -343,7 +344,11 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
343 STATION_INFO_TX_BITRATE | 344 STATION_INFO_TX_BITRATE |
344 STATION_INFO_RX_BITRATE | 345 STATION_INFO_RX_BITRATE |
345 STATION_INFO_RX_DROP_MISC | 346 STATION_INFO_RX_DROP_MISC |
346 STATION_INFO_BSS_PARAM; 347 STATION_INFO_BSS_PARAM |
348 STATION_INFO_CONNECTED_TIME;
349
350 do_posix_clock_monotonic_gettime(&uptime);
351 sinfo->connected_time = uptime.tv_sec - sta->last_connected;
347 352
348 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); 353 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
349 sinfo->rx_bytes = sta->rx_bytes; 354 sinfo->rx_bytes = sta->rx_bytes;
@@ -686,6 +691,12 @@ static void sta_apply_parameters(struct ieee80211_local *local,
686 if (set & BIT(NL80211_STA_FLAG_MFP)) 691 if (set & BIT(NL80211_STA_FLAG_MFP))
687 sta->flags |= WLAN_STA_MFP; 692 sta->flags |= WLAN_STA_MFP;
688 } 693 }
694
695 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
696 sta->flags &= ~WLAN_STA_AUTH;
697 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
698 sta->flags |= WLAN_STA_AUTH;
699 }
689 spin_unlock_irqrestore(&sta->flaglock, flags); 700 spin_unlock_irqrestore(&sta->flaglock, flags);
690 701
691 /* 702 /*
@@ -1034,26 +1045,26 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
1034 u8 *new_ie; 1045 u8 *new_ie;
1035 const u8 *old_ie; 1046 const u8 *old_ie;
1036 1047
1037 /* first allocate the new vendor information element */ 1048 /* allocate information elements */
1038 new_ie = NULL; 1049 new_ie = NULL;
1039 old_ie = ifmsh->vendor_ie; 1050 old_ie = ifmsh->ie;
1040 1051
1041 ifmsh->vendor_ie_len = setup->vendor_ie_len; 1052 if (setup->ie_len) {
1042 if (setup->vendor_ie_len) { 1053 new_ie = kmemdup(setup->ie, setup->ie_len,
1043 new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len,
1044 GFP_KERNEL); 1054 GFP_KERNEL);
1045 if (!new_ie) 1055 if (!new_ie)
1046 return -ENOMEM; 1056 return -ENOMEM;
1047 } 1057 }
1058 ifmsh->ie_len = setup->ie_len;
1059 ifmsh->ie = new_ie;
1060 kfree(old_ie);
1048 1061
1049 /* now copy the rest of the setup parameters */ 1062 /* now copy the rest of the setup parameters */
1050 ifmsh->mesh_id_len = setup->mesh_id_len; 1063 ifmsh->mesh_id_len = setup->mesh_id_len;
1051 memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); 1064 memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);
1052 ifmsh->mesh_pp_id = setup->path_sel_proto; 1065 ifmsh->mesh_pp_id = setup->path_sel_proto;
1053 ifmsh->mesh_pm_id = setup->path_metric; 1066 ifmsh->mesh_pm_id = setup->path_metric;
1054 ifmsh->vendor_ie = new_ie; 1067 ifmsh->is_secure = setup->is_secure;
1055
1056 kfree(old_ie);
1057 1068
1058 return 0; 1069 return 0;
1059} 1070}
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index c04a1396cf8d..a01d2137fddc 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -92,6 +92,31 @@ static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
92} 92}
93STA_OPS(inactive_ms); 93STA_OPS(inactive_ms);
94 94
95
96static ssize_t sta_connected_time_read(struct file *file, char __user *userbuf,
97 size_t count, loff_t *ppos)
98{
99 struct sta_info *sta = file->private_data;
100 struct timespec uptime;
101 struct tm result;
102 long connected_time_secs;
103 char buf[100];
104 int res;
105 do_posix_clock_monotonic_gettime(&uptime);
106 connected_time_secs = uptime.tv_sec - sta->last_connected;
107 time_to_tm(connected_time_secs, 0, &result);
108 result.tm_year -= 70;
109 result.tm_mday -= 1;
110 res = scnprintf(buf, sizeof(buf),
111 "years - %ld\nmonths - %d\ndays - %d\nclock - %d:%d:%d\n\n",
112 result.tm_year, result.tm_mon, result.tm_mday,
113 result.tm_hour, result.tm_min, result.tm_sec);
114 return simple_read_from_buffer(userbuf, count, ppos, buf, res);
115}
116STA_OPS(connected_time);
117
118
119
95static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, 120static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
96 size_t count, loff_t *ppos) 121 size_t count, loff_t *ppos)
97{ 122{
@@ -324,6 +349,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
324 DEBUGFS_ADD(flags); 349 DEBUGFS_ADD(flags);
325 DEBUGFS_ADD(num_ps_buf_frames); 350 DEBUGFS_ADD(num_ps_buf_frames);
326 DEBUGFS_ADD(inactive_ms); 351 DEBUGFS_ADD(inactive_ms);
352 DEBUGFS_ADD(connected_time);
327 DEBUGFS_ADD(last_seq_ctrl); 353 DEBUGFS_ADD(last_seq_ctrl);
328 DEBUGFS_ADD(agg_status); 354 DEBUGFS_ADD(agg_status);
329 DEBUGFS_ADD(dev); 355 DEBUGFS_ADD(dev);
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 9c0d62bb0ea3..00a0685f2403 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -552,4 +552,17 @@ static inline void drv_get_ringparam(struct ieee80211_local *local,
552 trace_drv_return_void(local); 552 trace_drv_return_void(local);
553} 553}
554 554
555static inline bool drv_tx_frames_pending(struct ieee80211_local *local)
556{
557 bool ret = false;
558
559 might_sleep();
560
561 trace_drv_tx_frames_pending(local);
562 if (local->ops->tx_frames_pending)
563 ret = local->ops->tx_frames_pending(&local->hw);
564 trace_drv_return_bool(local, ret);
565
566 return ret;
567}
555#endif /* __MAC80211_DRIVER_OPS */ 568#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 45aab80738e2..c8c934d48b7a 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -74,6 +74,21 @@ TRACE_EVENT(drv_return_int,
74 TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret) 74 TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret)
75); 75);
76 76
77TRACE_EVENT(drv_return_bool,
78 TP_PROTO(struct ieee80211_local *local, bool ret),
79 TP_ARGS(local, ret),
80 TP_STRUCT__entry(
81 LOCAL_ENTRY
82 __field(bool, ret)
83 ),
84 TP_fast_assign(
85 LOCAL_ASSIGN;
86 __entry->ret = ret;
87 ),
88 TP_printk(LOCAL_PR_FMT " - %s", LOCAL_PR_ARG, (__entry->ret) ?
89 "true" : "false")
90);
91
77TRACE_EVENT(drv_return_u64, 92TRACE_EVENT(drv_return_u64,
78 TP_PROTO(struct ieee80211_local *local, u64 ret), 93 TP_PROTO(struct ieee80211_local *local, u64 ret),
79 TP_ARGS(local, ret), 94 TP_ARGS(local, ret),
@@ -964,6 +979,11 @@ TRACE_EVENT(drv_get_ringparam,
964 ) 979 )
965); 980);
966 981
982DEFINE_EVENT(local_only_evt, drv_tx_frames_pending,
983 TP_PROTO(struct ieee80211_local *local),
984 TP_ARGS(local)
985);
986
967DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait, 987DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait,
968 TP_PROTO(struct ieee80211_local *local), 988 TP_PROTO(struct ieee80211_local *local),
969 TP_ARGS(local) 989 TP_ARGS(local)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 89ce1e329b5d..a77849970914 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -488,8 +488,9 @@ struct ieee80211_if_mesh {
488 struct mesh_config mshcfg; 488 struct mesh_config mshcfg;
489 u32 mesh_seqnum; 489 u32 mesh_seqnum;
490 bool accepting_plinks; 490 bool accepting_plinks;
491 const u8 *vendor_ie; 491 const u8 *ie;
492 u8 vendor_ie_len; 492 u8 ie_len;
493 bool is_secure;
493}; 494};
494 495
495#ifdef CONFIG_MAC80211_MESH 496#ifdef CONFIG_MAC80211_MESH
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index dc50fc3153e5..0ab2a8df312d 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -545,7 +545,9 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
545 }, 545 },
546 [NL80211_IFTYPE_MESH_POINT] = { 546 [NL80211_IFTYPE_MESH_POINT] = {
547 .tx = 0xffff, 547 .tx = 0xffff,
548 .rx = BIT(IEEE80211_STYPE_ACTION >> 4), 548 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
549 BIT(IEEE80211_STYPE_AUTH >> 4) |
550 BIT(IEEE80211_STYPE_DEAUTH >> 4),
549 }, 551 },
550}; 552};
551 553
@@ -760,6 +762,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
760 local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT); 762 local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
761#endif 763#endif
762 764
765 /* if the underlying driver supports mesh, mac80211 will (at least)
766 * provide routing of mesh authentication frames to userspace */
767 if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
768 local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH;
769
763 /* mac80211 supports control port protocol changing */ 770 /* mac80211 supports control port protocol changing */
764 local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; 771 local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
765 772
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 2a57cc02c618..11207979e2e2 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -279,9 +279,9 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
279 MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; 279 MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
280 *pos++ = 0x00; 280 *pos++ = 0x00;
281 281
282 if (sdata->u.mesh.vendor_ie) { 282 if (sdata->u.mesh.ie) {
283 int len = sdata->u.mesh.vendor_ie_len; 283 int len = sdata->u.mesh.ie_len;
284 const u8 *data = sdata->u.mesh.vendor_ie; 284 const u8 *data = sdata->u.mesh.ie;
285 if (skb_tailroom(skb) > len) 285 if (skb_tailroom(skb) > len)
286 memcpy(skb_put(skb, len), data, len); 286 memcpy(skb_put(skb, len), data, len);
287 } 287 }
@@ -573,6 +573,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
573 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, 573 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
574 &elems); 574 &elems);
575 575
576 /* ignore beacons from secure mesh peers if our security is off */
577 if (elems.rsn_len && !sdata->u.mesh.is_secure)
578 return;
579
576 if (elems.ds_params && elems.ds_params_len == 1) 580 if (elems.ds_params && elems.ds_params_len == 1)
577 freq = ieee80211_channel_to_frequency(elems.ds_params[0], band); 581 freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
578 else 582 else
@@ -586,9 +590,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
586 if (elems.mesh_id && elems.mesh_config && 590 if (elems.mesh_id && elems.mesh_config &&
587 mesh_matches_local(&elems, sdata)) { 591 mesh_matches_local(&elems, sdata)) {
588 supp_rates = ieee80211_sta_get_rates(local, &elems, band); 592 supp_rates = ieee80211_sta_get_rates(local, &elems, band);
589 593 mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems);
590 mesh_neighbour_update(mgmt->sa, supp_rates, sdata,
591 mesh_peer_accepts_plinks(&elems));
592 } 594 }
593} 595}
594 596
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index b99e230fe31c..10acf1cc8082 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -226,7 +226,8 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
226int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); 226int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);
227/* Mesh plinks */ 227/* Mesh plinks */
228void mesh_neighbour_update(u8 *hw_addr, u32 rates, 228void mesh_neighbour_update(u8 *hw_addr, u32 rates,
229 struct ieee80211_sub_if_data *sdata, bool add); 229 struct ieee80211_sub_if_data *sdata,
230 struct ieee802_11_elems *ie);
230bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); 231bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
231void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); 232void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
232void mesh_plink_broken(struct sta_info *sta); 233void mesh_plink_broken(struct sta_info *sta);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 336ca9d0c5c4..35c715adaae2 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -65,42 +65,37 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
65 __mesh_table_free(tbl); 65 __mesh_table_free(tbl);
66} 66}
67 67
68static struct mesh_table *mesh_table_grow(struct mesh_table *tbl) 68static int mesh_table_grow(struct mesh_table *oldtbl,
69 struct mesh_table *newtbl)
69{ 70{
70 struct mesh_table *newtbl;
71 struct hlist_head *oldhash; 71 struct hlist_head *oldhash;
72 struct hlist_node *p, *q; 72 struct hlist_node *p, *q;
73 int i; 73 int i;
74 74
75 if (atomic_read(&tbl->entries) 75 if (atomic_read(&oldtbl->entries)
76 < tbl->mean_chain_len * (tbl->hash_mask + 1)) 76 < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1))
77 goto endgrow; 77 return -EAGAIN;
78 78
79 newtbl = mesh_table_alloc(tbl->size_order + 1);
80 if (!newtbl)
81 goto endgrow;
82 79
83 newtbl->free_node = tbl->free_node; 80 newtbl->free_node = oldtbl->free_node;
84 newtbl->mean_chain_len = tbl->mean_chain_len; 81 newtbl->mean_chain_len = oldtbl->mean_chain_len;
85 newtbl->copy_node = tbl->copy_node; 82 newtbl->copy_node = oldtbl->copy_node;
86 atomic_set(&newtbl->entries, atomic_read(&tbl->entries)); 83 atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries));
87 84
88 oldhash = tbl->hash_buckets; 85 oldhash = oldtbl->hash_buckets;
89 for (i = 0; i <= tbl->hash_mask; i++) 86 for (i = 0; i <= oldtbl->hash_mask; i++)
90 hlist_for_each(p, &oldhash[i]) 87 hlist_for_each(p, &oldhash[i])
91 if (tbl->copy_node(p, newtbl) < 0) 88 if (oldtbl->copy_node(p, newtbl) < 0)
92 goto errcopy; 89 goto errcopy;
93 90
94 return newtbl; 91 return 0;
95 92
96errcopy: 93errcopy:
97 for (i = 0; i <= newtbl->hash_mask; i++) { 94 for (i = 0; i <= newtbl->hash_mask; i++) {
98 hlist_for_each_safe(p, q, &newtbl->hash_buckets[i]) 95 hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
99 tbl->free_node(p, 0); 96 oldtbl->free_node(p, 0);
100 } 97 }
101 __mesh_table_free(newtbl); 98 return -ENOMEM;
102endgrow:
103 return NULL;
104} 99}
105 100
106 101
@@ -334,10 +329,13 @@ void mesh_mpath_table_grow(void)
334{ 329{
335 struct mesh_table *oldtbl, *newtbl; 330 struct mesh_table *oldtbl, *newtbl;
336 331
332 newtbl = mesh_table_alloc(mesh_paths->size_order + 1);
333 if (!newtbl)
334 return;
337 write_lock(&pathtbl_resize_lock); 335 write_lock(&pathtbl_resize_lock);
338 oldtbl = mesh_paths; 336 oldtbl = mesh_paths;
339 newtbl = mesh_table_grow(mesh_paths); 337 if (mesh_table_grow(mesh_paths, newtbl) < 0) {
340 if (!newtbl) { 338 __mesh_table_free(newtbl);
341 write_unlock(&pathtbl_resize_lock); 339 write_unlock(&pathtbl_resize_lock);
342 return; 340 return;
343 } 341 }
@@ -352,10 +350,13 @@ void mesh_mpp_table_grow(void)
352{ 350{
353 struct mesh_table *oldtbl, *newtbl; 351 struct mesh_table *oldtbl, *newtbl;
354 352
353 newtbl = mesh_table_alloc(mpp_paths->size_order + 1);
354 if (!newtbl)
355 return;
355 write_lock(&pathtbl_resize_lock); 356 write_lock(&pathtbl_resize_lock);
356 oldtbl = mpp_paths; 357 oldtbl = mpp_paths;
357 newtbl = mesh_table_grow(mpp_paths); 358 if (mesh_table_grow(mpp_paths, newtbl) < 0) {
358 if (!newtbl) { 359 __mesh_table_free(newtbl);
359 write_unlock(&pathtbl_resize_lock); 360 write_unlock(&pathtbl_resize_lock);
360 return; 361 return;
361 } 362 }
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 44b53931ba5e..84e5b056af02 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
105 if (!sta) 105 if (!sta)
106 return NULL; 106 return NULL;
107 107
108 sta->flags = WLAN_STA_AUTHORIZED; 108 sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH;
109 sta->sta.supp_rates[local->hw.conf.channel->band] = rates; 109 sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
110 rate_control_rate_init(sta); 110 rate_control_rate_init(sta);
111 111
@@ -161,7 +161,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
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 sdata->u.mesh.ie_len);
165 struct ieee80211_mgmt *mgmt; 165 struct ieee80211_mgmt *mgmt;
166 bool include_plid = false; 166 bool include_plid = false;
167 static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; 167 static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A };
@@ -237,8 +237,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
237 return 0; 237 return 0;
238} 238}
239 239
240void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, 240void mesh_neighbour_update(u8 *hw_addr, u32 rates,
241 bool peer_accepting_plinks) 241 struct ieee80211_sub_if_data *sdata,
242 struct ieee802_11_elems *elems)
242{ 243{
243 struct ieee80211_local *local = sdata->local; 244 struct ieee80211_local *local = sdata->local;
244 struct sta_info *sta; 245 struct sta_info *sta;
@@ -248,8 +249,14 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data
248 sta = sta_info_get(sdata, hw_addr); 249 sta = sta_info_get(sdata, hw_addr);
249 if (!sta) { 250 if (!sta) {
250 rcu_read_unlock(); 251 rcu_read_unlock();
251 252 /* Userspace handles peer allocation when security is enabled
252 sta = mesh_plink_alloc(sdata, hw_addr, rates); 253 * */
254 if (sdata->u.mesh.is_secure)
255 cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
256 elems->ie_start, elems->total_len,
257 GFP_KERNEL);
258 else
259 sta = mesh_plink_alloc(sdata, hw_addr, rates);
253 if (!sta) 260 if (!sta)
254 return; 261 return;
255 if (sta_info_insert_rcu(sta)) { 262 if (sta_info_insert_rcu(sta)) {
@@ -260,7 +267,8 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data
260 267
261 sta->last_rx = jiffies; 268 sta->last_rx = jiffies;
262 sta->sta.supp_rates[local->hw.conf.channel->band] = rates; 269 sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
263 if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && 270 if (mesh_peer_accepts_plinks(elems) &&
271 sta->plink_state == PLINK_LISTEN &&
264 sdata->u.mesh.accepting_plinks && 272 sdata->u.mesh.accepting_plinks &&
265 sdata->u.mesh.mshcfg.auto_open_plinks) 273 sdata->u.mesh.mshcfg.auto_open_plinks)
266 mesh_plink_open(sta); 274 mesh_plink_open(sta);
@@ -372,6 +380,9 @@ int mesh_plink_open(struct sta_info *sta)
372 __le16 llid; 380 __le16 llid;
373 struct ieee80211_sub_if_data *sdata = sta->sdata; 381 struct ieee80211_sub_if_data *sdata = sta->sdata;
374 382
383 if (!test_sta_flags(sta, WLAN_STA_AUTH))
384 return -EPERM;
385
375 spin_lock_bh(&sta->lock); 386 spin_lock_bh(&sta->lock);
376 get_random_bytes(&llid, 2); 387 get_random_bytes(&llid, 2);
377 sta->llid = llid; 388 sta->llid = llid;
@@ -449,6 +460,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
449 mpl_dbg("Mesh plink: missing necessary peer link ie\n"); 460 mpl_dbg("Mesh plink: missing necessary peer link ie\n");
450 return; 461 return;
451 } 462 }
463 if (elems.rsn_len && !sdata->u.mesh.is_secure) {
464 mpl_dbg("Mesh plink: can't establish link with secure peer\n");
465 return;
466 }
452 467
453 ftype = mgmt->u.action.u.plink_action.action_code; 468 ftype = mgmt->u.action.u.plink_action.action_code;
454 ie_len = elems.peer_link_len; 469 ie_len = elems.peer_link_len;
@@ -480,6 +495,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
480 return; 495 return;
481 } 496 }
482 497
498 if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) {
499 mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
500 rcu_read_unlock();
501 return;
502 }
503
483 if (sta && sta->plink_state == PLINK_BLOCKED) { 504 if (sta && sta->plink_state == PLINK_BLOCKED) {
484 rcu_read_unlock(); 505 rcu_read_unlock();
485 return; 506 return;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 865fed4cc18b..a41f234bd486 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -761,15 +761,16 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
761 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && 761 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
762 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { 762 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
763 netif_tx_stop_all_queues(sdata->dev); 763 netif_tx_stop_all_queues(sdata->dev);
764 /*
765 * Flush all the frames queued in the driver before
766 * going to power save
767 */
768 drv_flush(local, false);
769 ieee80211_send_nullfunc(local, sdata, 1);
770 764
771 /* Flush once again to get the tx status of nullfunc frame */ 765 if (drv_tx_frames_pending(local))
772 drv_flush(local, false); 766 mod_timer(&local->dynamic_ps_timer, jiffies +
767 msecs_to_jiffies(
768 local->hw.conf.dynamic_ps_timeout));
769 else {
770 ieee80211_send_nullfunc(local, sdata, 1);
771 /* Flush to get the tx status of nullfunc frame */
772 drv_flush(local, false);
773 }
773 } 774 }
774 775
775 if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && 776 if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 1f0b010904b8..a864890e4d03 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -143,7 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
143 if (status->flag & RX_FLAG_HT) { 143 if (status->flag & RX_FLAG_HT) {
144 /* 144 /*
145 * MCS information is a separate field in radiotap, 145 * MCS information is a separate field in radiotap,
146 * added below. 146 * added below. The byte here is needed as padding
147 * for the channel though, so initialise it to 0.
147 */ 148 */
148 *pos = 0; 149 *pos = 0;
149 } else { 150 } else {
@@ -502,7 +503,8 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
502 503
503 if (ieee80211_is_probe_req(hdr->frame_control) || 504 if (ieee80211_is_probe_req(hdr->frame_control) ||
504 ieee80211_is_probe_resp(hdr->frame_control) || 505 ieee80211_is_probe_resp(hdr->frame_control) ||
505 ieee80211_is_beacon(hdr->frame_control)) 506 ieee80211_is_beacon(hdr->frame_control) ||
507 ieee80211_is_auth(hdr->frame_control))
506 return RX_CONTINUE; 508 return RX_CONTINUE;
507 509
508 return RX_DROP_MONITOR; 510 return RX_DROP_MONITOR;
@@ -1585,7 +1587,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
1585} 1587}
1586 1588
1587static int 1589static int
1588__ieee80211_data_to_8023(struct ieee80211_rx_data *rx) 1590__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
1589{ 1591{
1590 struct ieee80211_sub_if_data *sdata = rx->sdata; 1592 struct ieee80211_sub_if_data *sdata = rx->sdata;
1591 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 1593 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
@@ -1593,6 +1595,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
1593 struct ethhdr *ehdr; 1595 struct ethhdr *ehdr;
1594 int ret; 1596 int ret;
1595 1597
1598 *port_control = false;
1596 if (ieee80211_has_a4(hdr->frame_control) && 1599 if (ieee80211_has_a4(hdr->frame_control) &&
1597 sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) 1600 sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
1598 return -1; 1601 return -1;
@@ -1611,11 +1614,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
1611 return -1; 1614 return -1;
1612 1615
1613 ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); 1616 ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
1614 if (ret < 0 || !check_port_control) 1617 if (ret < 0)
1615 return ret; 1618 return ret;
1616 1619
1617 ehdr = (struct ethhdr *) rx->skb->data; 1620 ehdr = (struct ethhdr *) rx->skb->data;
1618 if (ehdr->h_proto != rx->sdata->control_port_protocol) 1621 if (ehdr->h_proto == rx->sdata->control_port_protocol)
1622 *port_control = true;
1623 else if (check_port_control)
1619 return -1; 1624 return -1;
1620 1625
1621 return 0; 1626 return 0;
@@ -1916,6 +1921,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
1916 struct net_device *dev = sdata->dev; 1921 struct net_device *dev = sdata->dev;
1917 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 1922 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
1918 __le16 fc = hdr->frame_control; 1923 __le16 fc = hdr->frame_control;
1924 bool port_control;
1919 int err; 1925 int err;
1920 1926
1921 if (unlikely(!ieee80211_is_data(hdr->frame_control))) 1927 if (unlikely(!ieee80211_is_data(hdr->frame_control)))
@@ -1932,13 +1938,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
1932 sdata->vif.type == NL80211_IFTYPE_AP) 1938 sdata->vif.type == NL80211_IFTYPE_AP)
1933 return RX_DROP_MONITOR; 1939 return RX_DROP_MONITOR;
1934 1940
1935 err = __ieee80211_data_to_8023(rx); 1941 err = __ieee80211_data_to_8023(rx, &port_control);
1936 if (unlikely(err)) 1942 if (unlikely(err))
1937 return RX_DROP_UNUSABLE; 1943 return RX_DROP_UNUSABLE;
1938 1944
1939 if (!ieee80211_frame_allowed(rx, fc)) 1945 if (!ieee80211_frame_allowed(rx, fc))
1940 return RX_DROP_MONITOR; 1946 return RX_DROP_MONITOR;
1941 1947
1948 if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
1949 unlikely(port_control) && sdata->bss) {
1950 sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
1951 u.ap);
1952 dev = sdata->dev;
1953 rx->sdata = sdata;
1954 }
1955
1942 rx->skb->dev = dev; 1956 rx->skb->dev = dev;
1943 1957
1944 dev->stats.rx_packets++; 1958 dev->stats.rx_packets++;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 52d4b1a695c9..a03d8a312875 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -228,6 +228,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
228{ 228{
229 struct ieee80211_local *local = sdata->local; 229 struct ieee80211_local *local = sdata->local;
230 struct sta_info *sta; 230 struct sta_info *sta;
231 struct timespec uptime;
231 int i; 232 int i;
232 233
233 sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); 234 sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);
@@ -245,6 +246,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
245 sta->sdata = sdata; 246 sta->sdata = sdata;
246 sta->last_rx = jiffies; 247 sta->last_rx = jiffies;
247 248
249 do_posix_clock_monotonic_gettime(&uptime);
250 sta->last_connected = uptime.tv_sec;
248 ewma_init(&sta->avg_signal, 1024, 8); 251 ewma_init(&sta->avg_signal, 1024, 8);
249 252
250 if (sta_prepare_rate_control(local, sta, gfp)) { 253 if (sta_prepare_rate_control(local, sta, gfp)) {
@@ -609,7 +612,8 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
609#endif 612#endif
610 dev_kfree_skb(skb); 613 dev_kfree_skb(skb);
611 614
612 if (skb_queue_empty(&sta->ps_tx_buf)) 615 if (skb_queue_empty(&sta->ps_tx_buf) &&
616 !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF))
613 sta_info_clear_tim_bit(sta); 617 sta_info_clear_tim_bit(sta);
614 } 618 }
615 619
@@ -893,6 +897,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
893 struct ieee80211_local *local = sdata->local; 897 struct ieee80211_local *local = sdata->local;
894 int sent, buffered; 898 int sent, buffered;
895 899
900 clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
896 if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) 901 if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
897 drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); 902 drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
898 903
@@ -985,3 +990,12 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
985 ieee80211_queue_work(hw, &sta->drv_unblock_wk); 990 ieee80211_queue_work(hw, &sta->drv_unblock_wk);
986} 991}
987EXPORT_SYMBOL(ieee80211_sta_block_awake); 992EXPORT_SYMBOL(ieee80211_sta_block_awake);
993
994void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta)
995{
996 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
997
998 set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
999 sta_info_set_tim_bit(sta);
1000}
1001EXPORT_SYMBOL(ieee80211_sta_set_tim);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 87b18ba1e0e9..aa0adcbf3a93 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -43,6 +43,8 @@
43 * be in the queues 43 * be in the queues
44 * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping 44 * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping
45 * station in power-save mode, reply when the driver unblocks. 45 * station in power-save mode, reply when the driver unblocks.
46 * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
47 * buffers. Automatically cleared on station wake-up.
46 */ 48 */
47enum ieee80211_sta_info_flags { 49enum ieee80211_sta_info_flags {
48 WLAN_STA_AUTH = 1<<0, 50 WLAN_STA_AUTH = 1<<0,
@@ -58,6 +60,7 @@ enum ieee80211_sta_info_flags {
58 WLAN_STA_BLOCK_BA = 1<<11, 60 WLAN_STA_BLOCK_BA = 1<<11,
59 WLAN_STA_PS_DRIVER = 1<<12, 61 WLAN_STA_PS_DRIVER = 1<<12,
60 WLAN_STA_PSPOLL = 1<<13, 62 WLAN_STA_PSPOLL = 1<<13,
63 WLAN_STA_PS_DRIVER_BUF = 1<<14,
61}; 64};
62 65
63#define STA_TID_NUM 16 66#define STA_TID_NUM 16
@@ -226,6 +229,7 @@ enum plink_state {
226 * @rx_bytes: Number of bytes received from this STA 229 * @rx_bytes: Number of bytes received from this STA
227 * @wep_weak_iv_count: number of weak WEP IVs received from this station 230 * @wep_weak_iv_count: number of weak WEP IVs received from this station
228 * @last_rx: time (in jiffies) when last frame was received from this STA 231 * @last_rx: time (in jiffies) when last frame was received from this STA
232 * @last_connected: time (in seconds) when a station got connected
229 * @num_duplicates: number of duplicate frames received from this STA 233 * @num_duplicates: number of duplicate frames received from this STA
230 * @rx_fragments: number of received MPDUs 234 * @rx_fragments: number of received MPDUs
231 * @rx_dropped: number of dropped MPDUs from this STA 235 * @rx_dropped: number of dropped MPDUs from this STA
@@ -295,6 +299,7 @@ struct sta_info {
295 unsigned long rx_packets, rx_bytes; 299 unsigned long rx_packets, rx_bytes;
296 unsigned long wep_weak_iv_count; 300 unsigned long wep_weak_iv_count;
297 unsigned long last_rx; 301 unsigned long last_rx;
302 long last_connected;
298 unsigned long num_duplicates; 303 unsigned long num_duplicates;
299 unsigned long rx_fragments; 304 unsigned long rx_fragments;
300 unsigned long rx_dropped; 305 unsigned long rx_dropped;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ce4596ed1268..17b10be31f55 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2262,7 +2262,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2262 2262
2263 /* headroom, head length, tail length and maximum TIM length */ 2263 /* headroom, head length, tail length and maximum TIM length */
2264 skb = dev_alloc_skb(local->tx_headroom + 400 + 2264 skb = dev_alloc_skb(local->tx_headroom + 400 +
2265 sdata->u.mesh.vendor_ie_len); 2265 sdata->u.mesh.ie_len);
2266 if (!skb) 2266 if (!skb)
2267 goto out; 2267 goto out;
2268 2268