diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-04-25 14:34:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-25 14:34:25 -0400 |
commit | cfef6047c4027a8448ec8dafeaf2bb362cc882e4 (patch) | |
tree | c254bd25aa8b4b0696b5b5cc45d8e30c7c1bb9dd /net/mac80211 | |
parent | b71d1d426d263b0b6cb5760322efebbfc89d4463 (diff) | |
parent | 73b48099cc265f88fa1255f3f43e52fe6a94fd5c (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.c | 29 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 26 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 13 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 20 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 5 | ||||
-rw-r--r-- | net/mac80211/main.c | 9 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 14 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 49 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 35 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 17 | ||||
-rw-r--r-- | net/mac80211/rx.c | 26 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 16 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 5 | ||||
-rw-r--r-- | net/mac80211/tx.c | 2 |
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 | |||
330 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 330 | static 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 | } |
93 | STA_OPS(inactive_ms); | 93 | STA_OPS(inactive_ms); |
94 | 94 | ||
95 | |||
96 | static 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 | } | ||
116 | STA_OPS(connected_time); | ||
117 | |||
118 | |||
119 | |||
95 | static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf, | 120 | static 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 | ||
555 | static 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 | ||
77 | TRACE_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 | |||
77 | TRACE_EVENT(drv_return_u64, | 92 | TRACE_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 | ||
982 | DEFINE_EVENT(local_only_evt, drv_tx_frames_pending, | ||
983 | TP_PROTO(struct ieee80211_local *local), | ||
984 | TP_ARGS(local) | ||
985 | ); | ||
986 | |||
967 | DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait, | 987 | DEFINE_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, | |||
226 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); | 226 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); |
227 | /* Mesh plinks */ | 227 | /* Mesh plinks */ |
228 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, | 228 | void 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); | ||
230 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); | 231 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
231 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 232 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
232 | void mesh_plink_broken(struct sta_info *sta); | 233 | void 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 | ||
68 | static struct mesh_table *mesh_table_grow(struct mesh_table *tbl) | 68 | static 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 | ||
96 | errcopy: | 93 | errcopy: |
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; |
102 | endgrow: | ||
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 | ||
240 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, | 240 | void 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 | ||
1587 | static int | 1589 | static 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 | } |
987 | EXPORT_SYMBOL(ieee80211_sta_block_awake); | 992 | EXPORT_SYMBOL(ieee80211_sta_block_awake); |
993 | |||
994 | void 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 | } | ||
1001 | EXPORT_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 | */ |
47 | enum ieee80211_sta_info_flags { | 49 | enum 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 | ||