diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-11-02 23:56:40 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-11-02 23:56:40 -0400 |
commit | 31cbecb4ab538f433145bc5a46f3bea9b9627031 (patch) | |
tree | d6206d42dea7298f7ef05fd1f7bf474245f0d43a /net/mac80211 | |
parent | 2b72c9ccd22c4a3299e5a358dcd639fb253730f4 (diff) | |
parent | 278c023a99b0d6b471d0f4a79835c703482e29ac (diff) |
Merge branch 'osd-devel' into nfs-for-next
Diffstat (limited to 'net/mac80211')
36 files changed, 3355 insertions, 1657 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index f5fdfcbf552a..7d3b438755f0 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -199,6 +199,19 @@ config MAC80211_VERBOSE_MPL_DEBUG | |||
199 | 199 | ||
200 | Do not select this option. | 200 | Do not select this option. |
201 | 201 | ||
202 | config MAC80211_VERBOSE_MPATH_DEBUG | ||
203 | bool "Verbose mesh path debugging" | ||
204 | depends on MAC80211_DEBUG_MENU | ||
205 | depends on MAC80211_MESH | ||
206 | ---help--- | ||
207 | Selecting this option causes mac80211 to print out very | ||
208 | verbose mesh path selection debugging messages (when mac80211 | ||
209 | is taking part in a mesh network). | ||
210 | It should not be selected on production systems as those | ||
211 | messages are remotely triggerable. | ||
212 | |||
213 | Do not select this option. | ||
214 | |||
202 | config MAC80211_VERBOSE_MHWMP_DEBUG | 215 | config MAC80211_VERBOSE_MHWMP_DEBUG |
203 | bool "Verbose mesh HWMP routing debugging" | 216 | bool "Verbose mesh HWMP routing debugging" |
204 | depends on MAC80211_DEBUG_MENU | 217 | depends on MAC80211_DEBUG_MENU |
@@ -212,6 +225,18 @@ config MAC80211_VERBOSE_MHWMP_DEBUG | |||
212 | 225 | ||
213 | Do not select this option. | 226 | Do not select this option. |
214 | 227 | ||
228 | config MAC80211_VERBOSE_TDLS_DEBUG | ||
229 | bool "Verbose TDLS debugging" | ||
230 | depends on MAC80211_DEBUG_MENU | ||
231 | ---help--- | ||
232 | Selecting this option causes mac80211 to print out very | ||
233 | verbose TDLS selection debugging messages (when mac80211 | ||
234 | is a TDLS STA). | ||
235 | It should not be selected on production systems as those | ||
236 | messages are remotely triggerable. | ||
237 | |||
238 | Do not select this option. | ||
239 | |||
215 | config MAC80211_DEBUG_COUNTERS | 240 | config MAC80211_DEBUG_COUNTERS |
216 | bool "Extra statistics for TX/RX debugging" | 241 | bool "Extra statistics for TX/RX debugging" |
217 | depends on MAC80211_DEBUG_MENU | 242 | depends on MAC80211_DEBUG_MENU |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index fd1aaf2a4a6c..97f33588b65f 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -69,7 +69,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
69 | if (!tid_rx) | 69 | if (!tid_rx) |
70 | return; | 70 | return; |
71 | 71 | ||
72 | rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], NULL); | 72 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); |
73 | 73 | ||
74 | #ifdef CONFIG_MAC80211_HT_DEBUG | 74 | #ifdef CONFIG_MAC80211_HT_DEBUG |
75 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", | 75 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", |
@@ -167,12 +167,8 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
167 | u16 capab; | 167 | u16 capab; |
168 | 168 | ||
169 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | 169 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); |
170 | 170 | if (!skb) | |
171 | if (!skb) { | ||
172 | printk(KERN_DEBUG "%s: failed to allocate buffer " | ||
173 | "for addba resp frame\n", sdata->name); | ||
174 | return; | 171 | return; |
175 | } | ||
176 | 172 | ||
177 | skb_reserve(skb, local->hw.extra_tx_headroom); | 173 | skb_reserve(skb, local->hw.extra_tx_headroom); |
178 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 174 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
@@ -227,7 +223,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
227 | 223 | ||
228 | status = WLAN_STATUS_REQUEST_DECLINED; | 224 | status = WLAN_STATUS_REQUEST_DECLINED; |
229 | 225 | ||
230 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { | 226 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
231 | #ifdef CONFIG_MAC80211_HT_DEBUG | 227 | #ifdef CONFIG_MAC80211_HT_DEBUG |
232 | printk(KERN_DEBUG "Suspend in progress. " | 228 | printk(KERN_DEBUG "Suspend in progress. " |
233 | "Denying ADDBA request\n"); | 229 | "Denying ADDBA request\n"); |
@@ -279,14 +275,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
279 | 275 | ||
280 | /* prepare A-MPDU MLME for Rx aggregation */ | 276 | /* prepare A-MPDU MLME for Rx aggregation */ |
281 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL); | 277 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL); |
282 | if (!tid_agg_rx) { | 278 | if (!tid_agg_rx) |
283 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
284 | if (net_ratelimit()) | ||
285 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | ||
286 | tid); | ||
287 | #endif | ||
288 | goto end; | 279 | goto end; |
289 | } | ||
290 | 280 | ||
291 | spin_lock_init(&tid_agg_rx->reorder_lock); | 281 | spin_lock_init(&tid_agg_rx->reorder_lock); |
292 | 282 | ||
@@ -306,11 +296,6 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
306 | tid_agg_rx->reorder_time = | 296 | tid_agg_rx->reorder_time = |
307 | kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL); | 297 | kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL); |
308 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { | 298 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { |
309 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
310 | if (net_ratelimit()) | ||
311 | printk(KERN_ERR "can not allocate reordering buffer " | ||
312 | "to tid %d\n", tid); | ||
313 | #endif | ||
314 | kfree(tid_agg_rx->reorder_buf); | 299 | kfree(tid_agg_rx->reorder_buf); |
315 | kfree(tid_agg_rx->reorder_time); | 300 | kfree(tid_agg_rx->reorder_time); |
316 | kfree(tid_agg_rx); | 301 | kfree(tid_agg_rx); |
@@ -340,7 +325,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
340 | status = WLAN_STATUS_SUCCESS; | 325 | status = WLAN_STATUS_SUCCESS; |
341 | 326 | ||
342 | /* activate it for RX */ | 327 | /* activate it for RX */ |
343 | rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); | 328 | RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); |
344 | 329 | ||
345 | if (timeout) | 330 | if (timeout) |
346 | mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); | 331 | mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index c8be8eff70da..2ac033989e01 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -68,11 +68,9 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
68 | 68 | ||
69 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | 69 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); |
70 | 70 | ||
71 | if (!skb) { | 71 | if (!skb) |
72 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
73 | "for addba request frame\n", sdata->name); | ||
74 | return; | 72 | return; |
75 | } | 73 | |
76 | skb_reserve(skb, local->hw.extra_tx_headroom); | 74 | skb_reserve(skb, local->hw.extra_tx_headroom); |
77 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 75 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
78 | memset(mgmt, 0, 24); | 76 | memset(mgmt, 0, 24); |
@@ -106,19 +104,18 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
106 | ieee80211_tx_skb(sdata, skb); | 104 | ieee80211_tx_skb(sdata, skb); |
107 | } | 105 | } |
108 | 106 | ||
109 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) | 107 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) |
110 | { | 108 | { |
109 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
111 | struct ieee80211_local *local = sdata->local; | 110 | struct ieee80211_local *local = sdata->local; |
112 | struct sk_buff *skb; | 111 | struct sk_buff *skb; |
113 | struct ieee80211_bar *bar; | 112 | struct ieee80211_bar *bar; |
114 | u16 bar_control = 0; | 113 | u16 bar_control = 0; |
115 | 114 | ||
116 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | 115 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); |
117 | if (!skb) { | 116 | if (!skb) |
118 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
119 | "bar frame\n", sdata->name); | ||
120 | return; | 117 | return; |
121 | } | 118 | |
122 | skb_reserve(skb, local->hw.extra_tx_headroom); | 119 | skb_reserve(skb, local->hw.extra_tx_headroom); |
123 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); | 120 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); |
124 | memset(bar, 0, sizeof(*bar)); | 121 | memset(bar, 0, sizeof(*bar)); |
@@ -128,13 +125,14 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
128 | memcpy(bar->ta, sdata->vif.addr, ETH_ALEN); | 125 | memcpy(bar->ta, sdata->vif.addr, ETH_ALEN); |
129 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | 126 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; |
130 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | 127 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; |
131 | bar_control |= (u16)(tid << 12); | 128 | bar_control |= (u16)(tid << IEEE80211_BAR_CTRL_TID_INFO_SHIFT); |
132 | bar->control = cpu_to_le16(bar_control); | 129 | bar->control = cpu_to_le16(bar_control); |
133 | bar->start_seq_num = cpu_to_le16(ssn); | 130 | bar->start_seq_num = cpu_to_le16(ssn); |
134 | 131 | ||
135 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 132 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
136 | ieee80211_tx_skb(sdata, skb); | 133 | ieee80211_tx_skb(sdata, skb); |
137 | } | 134 | } |
135 | EXPORT_SYMBOL(ieee80211_send_bar); | ||
138 | 136 | ||
139 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, | 137 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, |
140 | struct tid_ampdu_tx *tid_tx) | 138 | struct tid_ampdu_tx *tid_tx) |
@@ -364,7 +362,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
364 | return -EINVAL; | 362 | return -EINVAL; |
365 | 363 | ||
366 | if ((tid >= STA_TID_NUM) || | 364 | if ((tid >= STA_TID_NUM) || |
367 | !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) | 365 | !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) || |
366 | (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) | ||
368 | return -EINVAL; | 367 | return -EINVAL; |
369 | 368 | ||
370 | #ifdef CONFIG_MAC80211_HT_DEBUG | 369 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -383,7 +382,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
383 | sdata->vif.type != NL80211_IFTYPE_AP) | 382 | sdata->vif.type != NL80211_IFTYPE_AP) |
384 | return -EINVAL; | 383 | return -EINVAL; |
385 | 384 | ||
386 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { | 385 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
387 | #ifdef CONFIG_MAC80211_HT_DEBUG | 386 | #ifdef CONFIG_MAC80211_HT_DEBUG |
388 | printk(KERN_DEBUG "BA sessions blocked. " | 387 | printk(KERN_DEBUG "BA sessions blocked. " |
389 | "Denying BA session request\n"); | 388 | "Denying BA session request\n"); |
@@ -413,11 +412,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
413 | /* prepare A-MPDU MLME for Tx aggregation */ | 412 | /* prepare A-MPDU MLME for Tx aggregation */ |
414 | tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | 413 | tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); |
415 | if (!tid_tx) { | 414 | if (!tid_tx) { |
416 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
417 | if (net_ratelimit()) | ||
418 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
419 | tid); | ||
420 | #endif | ||
421 | ret = -ENOMEM; | 415 | ret = -ENOMEM; |
422 | goto err_unlock_sta; | 416 | goto err_unlock_sta; |
423 | } | 417 | } |
@@ -574,14 +568,9 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
574 | struct ieee80211_ra_tid *ra_tid; | 568 | struct ieee80211_ra_tid *ra_tid; |
575 | struct sk_buff *skb = dev_alloc_skb(0); | 569 | struct sk_buff *skb = dev_alloc_skb(0); |
576 | 570 | ||
577 | if (unlikely(!skb)) { | 571 | if (unlikely(!skb)) |
578 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
579 | if (net_ratelimit()) | ||
580 | printk(KERN_WARNING "%s: Not enough memory, " | ||
581 | "dropping start BA session", sdata->name); | ||
582 | #endif | ||
583 | return; | 572 | return; |
584 | } | 573 | |
585 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 574 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
586 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | 575 | memcpy(&ra_tid->ra, ra, ETH_ALEN); |
587 | ra_tid->tid = tid; | 576 | ra_tid->tid = tid; |
@@ -727,14 +716,9 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
727 | struct ieee80211_ra_tid *ra_tid; | 716 | struct ieee80211_ra_tid *ra_tid; |
728 | struct sk_buff *skb = dev_alloc_skb(0); | 717 | struct sk_buff *skb = dev_alloc_skb(0); |
729 | 718 | ||
730 | if (unlikely(!skb)) { | 719 | if (unlikely(!skb)) |
731 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
732 | if (net_ratelimit()) | ||
733 | printk(KERN_WARNING "%s: Not enough memory, " | ||
734 | "dropping stop BA session", sdata->name); | ||
735 | #endif | ||
736 | return; | 720 | return; |
737 | } | 721 | |
738 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 722 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
739 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | 723 | memcpy(&ra_tid->ra, ra, ETH_ALEN); |
740 | ra_tid->tid = tid; | 724 | ra_tid->tid = tid; |
@@ -777,18 +761,14 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
777 | #ifdef CONFIG_MAC80211_HT_DEBUG | 761 | #ifdef CONFIG_MAC80211_HT_DEBUG |
778 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); | 762 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); |
779 | #endif | 763 | #endif |
780 | 764 | /* | |
765 | * IEEE 802.11-2007 7.3.1.14: | ||
766 | * In an ADDBA Response frame, when the Status Code field | ||
767 | * is set to 0, the Buffer Size subfield is set to a value | ||
768 | * of at least 1. | ||
769 | */ | ||
781 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 770 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
782 | == WLAN_STATUS_SUCCESS) { | 771 | == WLAN_STATUS_SUCCESS && buf_size) { |
783 | /* | ||
784 | * IEEE 802.11-2007 7.3.1.14: | ||
785 | * In an ADDBA Response frame, when the Status Code field | ||
786 | * is set to 0, the Buffer Size subfield is set to a value | ||
787 | * of at least 1. | ||
788 | */ | ||
789 | if (!buf_size) | ||
790 | goto out; | ||
791 | |||
792 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, | 772 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, |
793 | &tid_tx->state)) { | 773 | &tid_tx->state)) { |
794 | /* ignore duplicate response */ | 774 | /* ignore duplicate response */ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 3d1b091d9b2e..ebd7fb101fbf 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <net/net_namespace.h> | 13 | #include <net/net_namespace.h> |
14 | #include <linux/rcupdate.h> | 14 | #include <linux/rcupdate.h> |
15 | #include <linux/if_ether.h> | ||
15 | #include <net/cfg80211.h> | 16 | #include <net/cfg80211.h> |
16 | #include "ieee80211_i.h" | 17 | #include "ieee80211_i.h" |
17 | #include "driver-ops.h" | 18 | #include "driver-ops.h" |
@@ -62,7 +63,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
62 | 63 | ||
63 | if (type == NL80211_IFTYPE_AP_VLAN && | 64 | if (type == NL80211_IFTYPE_AP_VLAN && |
64 | params && params->use_4addr == 0) | 65 | params && params->use_4addr == 0) |
65 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | 66 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); |
66 | else if (type == NL80211_IFTYPE_STATION && | 67 | else if (type == NL80211_IFTYPE_STATION && |
67 | params && params->use_4addr >= 0) | 68 | params && params->use_4addr >= 0) |
68 | sdata->u.mgd.use_4addr = params->use_4addr; | 69 | sdata->u.mgd.use_4addr = params->use_4addr; |
@@ -343,7 +344,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
343 | STATION_INFO_RX_BITRATE | | 344 | STATION_INFO_RX_BITRATE | |
344 | STATION_INFO_RX_DROP_MISC | | 345 | STATION_INFO_RX_DROP_MISC | |
345 | STATION_INFO_BSS_PARAM | | 346 | STATION_INFO_BSS_PARAM | |
346 | STATION_INFO_CONNECTED_TIME; | 347 | STATION_INFO_CONNECTED_TIME | |
348 | STATION_INFO_STA_FLAGS; | ||
347 | 349 | ||
348 | do_posix_clock_monotonic_gettime(&uptime); | 350 | do_posix_clock_monotonic_gettime(&uptime); |
349 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | 351 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; |
@@ -403,6 +405,23 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
403 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; | 405 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; |
404 | sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; | 406 | sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; |
405 | sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; | 407 | sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; |
408 | |||
409 | sinfo->sta_flags.set = 0; | ||
410 | sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
411 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
412 | BIT(NL80211_STA_FLAG_WME) | | ||
413 | BIT(NL80211_STA_FLAG_MFP) | | ||
414 | BIT(NL80211_STA_FLAG_AUTHENTICATED); | ||
415 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
416 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
417 | if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE)) | ||
418 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE); | ||
419 | if (test_sta_flag(sta, WLAN_STA_WME)) | ||
420 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME); | ||
421 | if (test_sta_flag(sta, WLAN_STA_MFP)) | ||
422 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); | ||
423 | if (test_sta_flag(sta, WLAN_STA_AUTH)) | ||
424 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); | ||
406 | } | 425 | } |
407 | 426 | ||
408 | 427 | ||
@@ -455,6 +474,20 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
455 | return ret; | 474 | return ret; |
456 | } | 475 | } |
457 | 476 | ||
477 | static void ieee80211_config_ap_ssid(struct ieee80211_sub_if_data *sdata, | ||
478 | struct beacon_parameters *params) | ||
479 | { | ||
480 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | ||
481 | |||
482 | bss_conf->ssid_len = params->ssid_len; | ||
483 | |||
484 | if (params->ssid_len) | ||
485 | memcpy(bss_conf->ssid, params->ssid, params->ssid_len); | ||
486 | |||
487 | bss_conf->hidden_ssid = | ||
488 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); | ||
489 | } | ||
490 | |||
458 | /* | 491 | /* |
459 | * This handles both adding a beacon and setting new beacon info | 492 | * This handles both adding a beacon and setting new beacon info |
460 | */ | 493 | */ |
@@ -542,14 +575,17 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
542 | 575 | ||
543 | sdata->vif.bss_conf.dtim_period = new->dtim_period; | 576 | sdata->vif.bss_conf.dtim_period = new->dtim_period; |
544 | 577 | ||
545 | rcu_assign_pointer(sdata->u.ap.beacon, new); | 578 | RCU_INIT_POINTER(sdata->u.ap.beacon, new); |
546 | 579 | ||
547 | synchronize_rcu(); | 580 | synchronize_rcu(); |
548 | 581 | ||
549 | kfree(old); | 582 | kfree(old); |
550 | 583 | ||
584 | ieee80211_config_ap_ssid(sdata, params); | ||
585 | |||
551 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | 586 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | |
552 | BSS_CHANGED_BEACON); | 587 | BSS_CHANGED_BEACON | |
588 | BSS_CHANGED_SSID); | ||
553 | return 0; | 589 | return 0; |
554 | } | 590 | } |
555 | 591 | ||
@@ -594,7 +630,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
594 | if (!old) | 630 | if (!old) |
595 | return -ENOENT; | 631 | return -ENOENT; |
596 | 632 | ||
597 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | 633 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
598 | synchronize_rcu(); | 634 | synchronize_rcu(); |
599 | kfree(old); | 635 | kfree(old); |
600 | 636 | ||
@@ -650,7 +686,6 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
650 | struct sta_info *sta, | 686 | struct sta_info *sta, |
651 | struct station_parameters *params) | 687 | struct station_parameters *params) |
652 | { | 688 | { |
653 | unsigned long flags; | ||
654 | u32 rates; | 689 | u32 rates; |
655 | int i, j; | 690 | int i, j; |
656 | struct ieee80211_supported_band *sband; | 691 | struct ieee80211_supported_band *sband; |
@@ -659,43 +694,58 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
659 | 694 | ||
660 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 695 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
661 | 696 | ||
662 | spin_lock_irqsave(&sta->flaglock, flags); | ||
663 | mask = params->sta_flags_mask; | 697 | mask = params->sta_flags_mask; |
664 | set = params->sta_flags_set; | 698 | set = params->sta_flags_set; |
665 | 699 | ||
666 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | 700 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
667 | sta->flags &= ~WLAN_STA_AUTHORIZED; | ||
668 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 701 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) |
669 | sta->flags |= WLAN_STA_AUTHORIZED; | 702 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); |
703 | else | ||
704 | clear_sta_flag(sta, WLAN_STA_AUTHORIZED); | ||
670 | } | 705 | } |
671 | 706 | ||
672 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { | 707 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { |
673 | sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; | ||
674 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) | 708 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) |
675 | sta->flags |= WLAN_STA_SHORT_PREAMBLE; | 709 | set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE); |
710 | else | ||
711 | clear_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE); | ||
676 | } | 712 | } |
677 | 713 | ||
678 | if (mask & BIT(NL80211_STA_FLAG_WME)) { | 714 | if (mask & BIT(NL80211_STA_FLAG_WME)) { |
679 | sta->flags &= ~WLAN_STA_WME; | ||
680 | sta->sta.wme = false; | ||
681 | if (set & BIT(NL80211_STA_FLAG_WME)) { | 715 | if (set & BIT(NL80211_STA_FLAG_WME)) { |
682 | sta->flags |= WLAN_STA_WME; | 716 | set_sta_flag(sta, WLAN_STA_WME); |
683 | sta->sta.wme = true; | 717 | sta->sta.wme = true; |
718 | } else { | ||
719 | clear_sta_flag(sta, WLAN_STA_WME); | ||
720 | sta->sta.wme = false; | ||
684 | } | 721 | } |
685 | } | 722 | } |
686 | 723 | ||
687 | if (mask & BIT(NL80211_STA_FLAG_MFP)) { | 724 | if (mask & BIT(NL80211_STA_FLAG_MFP)) { |
688 | sta->flags &= ~WLAN_STA_MFP; | ||
689 | if (set & BIT(NL80211_STA_FLAG_MFP)) | 725 | if (set & BIT(NL80211_STA_FLAG_MFP)) |
690 | sta->flags |= WLAN_STA_MFP; | 726 | set_sta_flag(sta, WLAN_STA_MFP); |
727 | else | ||
728 | clear_sta_flag(sta, WLAN_STA_MFP); | ||
691 | } | 729 | } |
692 | 730 | ||
693 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | 731 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { |
694 | sta->flags &= ~WLAN_STA_AUTH; | ||
695 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) | 732 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) |
696 | sta->flags |= WLAN_STA_AUTH; | 733 | set_sta_flag(sta, WLAN_STA_AUTH); |
734 | else | ||
735 | clear_sta_flag(sta, WLAN_STA_AUTH); | ||
736 | } | ||
737 | |||
738 | if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) { | ||
739 | if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
740 | set_sta_flag(sta, WLAN_STA_TDLS_PEER); | ||
741 | else | ||
742 | clear_sta_flag(sta, WLAN_STA_TDLS_PEER); | ||
743 | } | ||
744 | |||
745 | if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) { | ||
746 | sta->sta.uapsd_queues = params->uapsd_queues; | ||
747 | sta->sta.max_sp = params->max_sp; | ||
697 | } | 748 | } |
698 | spin_unlock_irqrestore(&sta->flaglock, flags); | ||
699 | 749 | ||
700 | /* | 750 | /* |
701 | * cfg80211 validates this (1-2007) and allows setting the AID | 751 | * cfg80211 validates this (1-2007) and allows setting the AID |
@@ -786,10 +836,17 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
786 | if (!sta) | 836 | if (!sta) |
787 | return -ENOMEM; | 837 | return -ENOMEM; |
788 | 838 | ||
789 | sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; | 839 | set_sta_flag(sta, WLAN_STA_AUTH); |
840 | set_sta_flag(sta, WLAN_STA_ASSOC); | ||
790 | 841 | ||
791 | sta_apply_parameters(local, sta, params); | 842 | sta_apply_parameters(local, sta, params); |
792 | 843 | ||
844 | /* Only TDLS-supporting stations can add TDLS peers */ | ||
845 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && | ||
846 | !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) && | ||
847 | sdata->vif.type == NL80211_IFTYPE_STATION)) | ||
848 | return -ENOTSUPP; | ||
849 | |||
793 | rate_control_rate_init(sta); | 850 | rate_control_rate_init(sta); |
794 | 851 | ||
795 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 852 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
@@ -842,6 +899,14 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
842 | return -ENOENT; | 899 | return -ENOENT; |
843 | } | 900 | } |
844 | 901 | ||
902 | /* The TDLS bit cannot be toggled after the STA was added */ | ||
903 | if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) && | ||
904 | !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) != | ||
905 | !!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | ||
906 | rcu_read_unlock(); | ||
907 | return -EINVAL; | ||
908 | } | ||
909 | |||
845 | if (params->vlan && params->vlan != sta->sdata->dev) { | 910 | if (params->vlan && params->vlan != sta->sdata->dev) { |
846 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 911 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
847 | 912 | ||
@@ -857,7 +922,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
857 | return -EBUSY; | 922 | return -EBUSY; |
858 | } | 923 | } |
859 | 924 | ||
860 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); | 925 | RCU_INIT_POINTER(vlansdata->u.vlan.sta, sta); |
861 | } | 926 | } |
862 | 927 | ||
863 | sta->sdata = vlansdata; | 928 | sta->sdata = vlansdata; |
@@ -918,7 +983,7 @@ static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
918 | if (dst) | 983 | if (dst) |
919 | return mesh_path_del(dst, sdata); | 984 | return mesh_path_del(dst, sdata); |
920 | 985 | ||
921 | mesh_path_flush(sdata); | 986 | mesh_path_flush_by_iface(sdata); |
922 | return 0; | 987 | return 0; |
923 | } | 988 | } |
924 | 989 | ||
@@ -1137,6 +1202,22 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1137 | conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode; | 1202 | conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode; |
1138 | ieee80211_mesh_root_setup(ifmsh); | 1203 | ieee80211_mesh_root_setup(ifmsh); |
1139 | } | 1204 | } |
1205 | if (_chg_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask)) { | ||
1206 | /* our current gate announcement implementation rides on root | ||
1207 | * announcements, so require this ifmsh to also be a root node | ||
1208 | * */ | ||
1209 | if (nconf->dot11MeshGateAnnouncementProtocol && | ||
1210 | !conf->dot11MeshHWMPRootMode) { | ||
1211 | conf->dot11MeshHWMPRootMode = 1; | ||
1212 | ieee80211_mesh_root_setup(ifmsh); | ||
1213 | } | ||
1214 | conf->dot11MeshGateAnnouncementProtocol = | ||
1215 | nconf->dot11MeshGateAnnouncementProtocol; | ||
1216 | } | ||
1217 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) { | ||
1218 | conf->dot11MeshHWMPRannInterval = | ||
1219 | nconf->dot11MeshHWMPRannInterval; | ||
1220 | } | ||
1140 | return 0; | 1221 | return 0; |
1141 | } | 1222 | } |
1142 | 1223 | ||
@@ -1235,9 +1316,11 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1235 | } | 1316 | } |
1236 | 1317 | ||
1237 | static int ieee80211_set_txq_params(struct wiphy *wiphy, | 1318 | static int ieee80211_set_txq_params(struct wiphy *wiphy, |
1319 | struct net_device *dev, | ||
1238 | struct ieee80211_txq_params *params) | 1320 | struct ieee80211_txq_params *params) |
1239 | { | 1321 | { |
1240 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1322 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1323 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1241 | struct ieee80211_tx_queue_params p; | 1324 | struct ieee80211_tx_queue_params p; |
1242 | 1325 | ||
1243 | if (!local->ops->conf_tx) | 1326 | if (!local->ops->conf_tx) |
@@ -1258,8 +1341,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1258 | if (params->queue >= local->hw.queues) | 1341 | if (params->queue >= local->hw.queues) |
1259 | return -EINVAL; | 1342 | return -EINVAL; |
1260 | 1343 | ||
1261 | local->tx_conf[params->queue] = p; | 1344 | sdata->tx_conf[params->queue] = p; |
1262 | if (drv_conf_tx(local, params->queue, &p)) { | 1345 | if (drv_conf_tx(local, sdata, params->queue, &p)) { |
1263 | wiphy_debug(local->hw.wiphy, | 1346 | wiphy_debug(local->hw.wiphy, |
1264 | "failed to set TX queue parameters for queue %d\n", | 1347 | "failed to set TX queue parameters for queue %d\n", |
1265 | params->queue); | 1348 | params->queue); |
@@ -1821,7 +1904,7 @@ ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) | |||
1821 | * so in that case userspace will have to deal with it. | 1904 | * so in that case userspace will have to deal with it. |
1822 | */ | 1905 | */ |
1823 | 1906 | ||
1824 | if (wk->offchan_tx.wait && wk->offchan_tx.frame) | 1907 | if (wk->offchan_tx.wait && !wk->offchan_tx.status) |
1825 | cfg80211_mgmt_tx_status(wk->sdata->dev, | 1908 | cfg80211_mgmt_tx_status(wk->sdata->dev, |
1826 | (unsigned long) wk->offchan_tx.frame, | 1909 | (unsigned long) wk->offchan_tx.frame, |
1827 | wk->ie, wk->ie_len, false, GFP_KERNEL); | 1910 | wk->ie, wk->ie_len, false, GFP_KERNEL); |
@@ -1833,7 +1916,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1833 | struct ieee80211_channel *chan, bool offchan, | 1916 | struct ieee80211_channel *chan, bool offchan, |
1834 | enum nl80211_channel_type channel_type, | 1917 | enum nl80211_channel_type channel_type, |
1835 | bool channel_type_valid, unsigned int wait, | 1918 | bool channel_type_valid, unsigned int wait, |
1836 | const u8 *buf, size_t len, u64 *cookie) | 1919 | const u8 *buf, size_t len, bool no_cck, |
1920 | u64 *cookie) | ||
1837 | { | 1921 | { |
1838 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1922 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1839 | struct ieee80211_local *local = sdata->local; | 1923 | struct ieee80211_local *local = sdata->local; |
@@ -1860,6 +1944,9 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1860 | flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | 1944 | flags |= IEEE80211_TX_CTL_TX_OFFCHAN; |
1861 | } | 1945 | } |
1862 | 1946 | ||
1947 | if (no_cck) | ||
1948 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | ||
1949 | |||
1863 | if (is_offchan && !offchan) | 1950 | if (is_offchan && !offchan) |
1864 | return -EBUSY; | 1951 | return -EBUSY; |
1865 | 1952 | ||
@@ -1898,33 +1985,6 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1898 | 1985 | ||
1899 | *cookie = (unsigned long) skb; | 1986 | *cookie = (unsigned long) skb; |
1900 | 1987 | ||
1901 | if (is_offchan && local->ops->offchannel_tx) { | ||
1902 | int ret; | ||
1903 | |||
1904 | IEEE80211_SKB_CB(skb)->band = chan->band; | ||
1905 | |||
1906 | mutex_lock(&local->mtx); | ||
1907 | |||
1908 | if (local->hw_offchan_tx_cookie) { | ||
1909 | mutex_unlock(&local->mtx); | ||
1910 | return -EBUSY; | ||
1911 | } | ||
1912 | |||
1913 | /* TODO: bitrate control, TX processing? */ | ||
1914 | ret = drv_offchannel_tx(local, skb, chan, channel_type, wait); | ||
1915 | |||
1916 | if (ret == 0) | ||
1917 | local->hw_offchan_tx_cookie = *cookie; | ||
1918 | mutex_unlock(&local->mtx); | ||
1919 | |||
1920 | /* | ||
1921 | * Allow driver to return 1 to indicate it wants to have the | ||
1922 | * frame transmitted with a remain_on_channel + regular TX. | ||
1923 | */ | ||
1924 | if (ret != 1) | ||
1925 | return ret; | ||
1926 | } | ||
1927 | |||
1928 | if (is_offchan && local->ops->remain_on_channel) { | 1988 | if (is_offchan && local->ops->remain_on_channel) { |
1929 | unsigned int duration; | 1989 | unsigned int duration; |
1930 | int ret; | 1990 | int ret; |
@@ -2011,18 +2071,6 @@ static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | |||
2011 | 2071 | ||
2012 | mutex_lock(&local->mtx); | 2072 | mutex_lock(&local->mtx); |
2013 | 2073 | ||
2014 | if (local->ops->offchannel_tx_cancel_wait && | ||
2015 | local->hw_offchan_tx_cookie == cookie) { | ||
2016 | ret = drv_offchannel_tx_cancel_wait(local); | ||
2017 | |||
2018 | if (!ret) | ||
2019 | local->hw_offchan_tx_cookie = 0; | ||
2020 | |||
2021 | mutex_unlock(&local->mtx); | ||
2022 | |||
2023 | return ret; | ||
2024 | } | ||
2025 | |||
2026 | if (local->ops->cancel_remain_on_channel) { | 2074 | if (local->ops->cancel_remain_on_channel) { |
2027 | cookie ^= 2; | 2075 | cookie ^= 2; |
2028 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); | 2076 | ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); |
@@ -2123,6 +2171,323 @@ static int ieee80211_set_rekey_data(struct wiphy *wiphy, | |||
2123 | return 0; | 2171 | return 0; |
2124 | } | 2172 | } |
2125 | 2173 | ||
2174 | static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) | ||
2175 | { | ||
2176 | u8 *pos = (void *)skb_put(skb, 7); | ||
2177 | |||
2178 | *pos++ = WLAN_EID_EXT_CAPABILITY; | ||
2179 | *pos++ = 5; /* len */ | ||
2180 | *pos++ = 0x0; | ||
2181 | *pos++ = 0x0; | ||
2182 | *pos++ = 0x0; | ||
2183 | *pos++ = 0x0; | ||
2184 | *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; | ||
2185 | } | ||
2186 | |||
2187 | static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) | ||
2188 | { | ||
2189 | struct ieee80211_local *local = sdata->local; | ||
2190 | u16 capab; | ||
2191 | |||
2192 | capab = 0; | ||
2193 | if (local->oper_channel->band != IEEE80211_BAND_2GHZ) | ||
2194 | return capab; | ||
2195 | |||
2196 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | ||
2197 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; | ||
2198 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) | ||
2199 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
2200 | |||
2201 | return capab; | ||
2202 | } | ||
2203 | |||
2204 | static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, | ||
2205 | u8 *peer, u8 *bssid) | ||
2206 | { | ||
2207 | struct ieee80211_tdls_lnkie *lnkid; | ||
2208 | |||
2209 | lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); | ||
2210 | |||
2211 | lnkid->ie_type = WLAN_EID_LINK_ID; | ||
2212 | lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; | ||
2213 | |||
2214 | memcpy(lnkid->bssid, bssid, ETH_ALEN); | ||
2215 | memcpy(lnkid->init_sta, src_addr, ETH_ALEN); | ||
2216 | memcpy(lnkid->resp_sta, peer, ETH_ALEN); | ||
2217 | } | ||
2218 | |||
2219 | static int | ||
2220 | ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | ||
2221 | u8 *peer, u8 action_code, u8 dialog_token, | ||
2222 | u16 status_code, struct sk_buff *skb) | ||
2223 | { | ||
2224 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2225 | struct ieee80211_tdls_data *tf; | ||
2226 | |||
2227 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | ||
2228 | |||
2229 | memcpy(tf->da, peer, ETH_ALEN); | ||
2230 | memcpy(tf->sa, sdata->vif.addr, ETH_ALEN); | ||
2231 | tf->ether_type = cpu_to_be16(ETH_P_TDLS); | ||
2232 | tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; | ||
2233 | |||
2234 | switch (action_code) { | ||
2235 | case WLAN_TDLS_SETUP_REQUEST: | ||
2236 | tf->category = WLAN_CATEGORY_TDLS; | ||
2237 | tf->action_code = WLAN_TDLS_SETUP_REQUEST; | ||
2238 | |||
2239 | skb_put(skb, sizeof(tf->u.setup_req)); | ||
2240 | tf->u.setup_req.dialog_token = dialog_token; | ||
2241 | tf->u.setup_req.capability = | ||
2242 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | ||
2243 | |||
2244 | ieee80211_add_srates_ie(&sdata->vif, skb); | ||
2245 | ieee80211_add_ext_srates_ie(&sdata->vif, skb); | ||
2246 | ieee80211_tdls_add_ext_capab(skb); | ||
2247 | break; | ||
2248 | case WLAN_TDLS_SETUP_RESPONSE: | ||
2249 | tf->category = WLAN_CATEGORY_TDLS; | ||
2250 | tf->action_code = WLAN_TDLS_SETUP_RESPONSE; | ||
2251 | |||
2252 | skb_put(skb, sizeof(tf->u.setup_resp)); | ||
2253 | tf->u.setup_resp.status_code = cpu_to_le16(status_code); | ||
2254 | tf->u.setup_resp.dialog_token = dialog_token; | ||
2255 | tf->u.setup_resp.capability = | ||
2256 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | ||
2257 | |||
2258 | ieee80211_add_srates_ie(&sdata->vif, skb); | ||
2259 | ieee80211_add_ext_srates_ie(&sdata->vif, skb); | ||
2260 | ieee80211_tdls_add_ext_capab(skb); | ||
2261 | break; | ||
2262 | case WLAN_TDLS_SETUP_CONFIRM: | ||
2263 | tf->category = WLAN_CATEGORY_TDLS; | ||
2264 | tf->action_code = WLAN_TDLS_SETUP_CONFIRM; | ||
2265 | |||
2266 | skb_put(skb, sizeof(tf->u.setup_cfm)); | ||
2267 | tf->u.setup_cfm.status_code = cpu_to_le16(status_code); | ||
2268 | tf->u.setup_cfm.dialog_token = dialog_token; | ||
2269 | break; | ||
2270 | case WLAN_TDLS_TEARDOWN: | ||
2271 | tf->category = WLAN_CATEGORY_TDLS; | ||
2272 | tf->action_code = WLAN_TDLS_TEARDOWN; | ||
2273 | |||
2274 | skb_put(skb, sizeof(tf->u.teardown)); | ||
2275 | tf->u.teardown.reason_code = cpu_to_le16(status_code); | ||
2276 | break; | ||
2277 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
2278 | tf->category = WLAN_CATEGORY_TDLS; | ||
2279 | tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; | ||
2280 | |||
2281 | skb_put(skb, sizeof(tf->u.discover_req)); | ||
2282 | tf->u.discover_req.dialog_token = dialog_token; | ||
2283 | break; | ||
2284 | default: | ||
2285 | return -EINVAL; | ||
2286 | } | ||
2287 | |||
2288 | return 0; | ||
2289 | } | ||
2290 | |||
2291 | static int | ||
2292 | ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | ||
2293 | u8 *peer, u8 action_code, u8 dialog_token, | ||
2294 | u16 status_code, struct sk_buff *skb) | ||
2295 | { | ||
2296 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2297 | struct ieee80211_mgmt *mgmt; | ||
2298 | |||
2299 | mgmt = (void *)skb_put(skb, 24); | ||
2300 | memset(mgmt, 0, 24); | ||
2301 | memcpy(mgmt->da, peer, ETH_ALEN); | ||
2302 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
2303 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | ||
2304 | |||
2305 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
2306 | IEEE80211_STYPE_ACTION); | ||
2307 | |||
2308 | switch (action_code) { | ||
2309 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
2310 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); | ||
2311 | mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; | ||
2312 | mgmt->u.action.u.tdls_discover_resp.action_code = | ||
2313 | WLAN_PUB_ACTION_TDLS_DISCOVER_RES; | ||
2314 | mgmt->u.action.u.tdls_discover_resp.dialog_token = | ||
2315 | dialog_token; | ||
2316 | mgmt->u.action.u.tdls_discover_resp.capability = | ||
2317 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | ||
2318 | |||
2319 | ieee80211_add_srates_ie(&sdata->vif, skb); | ||
2320 | ieee80211_add_ext_srates_ie(&sdata->vif, skb); | ||
2321 | ieee80211_tdls_add_ext_capab(skb); | ||
2322 | break; | ||
2323 | default: | ||
2324 | return -EINVAL; | ||
2325 | } | ||
2326 | |||
2327 | return 0; | ||
2328 | } | ||
2329 | |||
2330 | static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | ||
2331 | u8 *peer, u8 action_code, u8 dialog_token, | ||
2332 | u16 status_code, const u8 *extra_ies, | ||
2333 | size_t extra_ies_len) | ||
2334 | { | ||
2335 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2336 | struct ieee80211_local *local = sdata->local; | ||
2337 | struct ieee80211_tx_info *info; | ||
2338 | struct sk_buff *skb = NULL; | ||
2339 | bool send_direct; | ||
2340 | int ret; | ||
2341 | |||
2342 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
2343 | return -ENOTSUPP; | ||
2344 | |||
2345 | /* make sure we are in managed mode, and associated */ | ||
2346 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | ||
2347 | !sdata->u.mgd.associated) | ||
2348 | return -EINVAL; | ||
2349 | |||
2350 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG | ||
2351 | printk(KERN_DEBUG "TDLS mgmt action %d peer %pM\n", action_code, peer); | ||
2352 | #endif | ||
2353 | |||
2354 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
2355 | max(sizeof(struct ieee80211_mgmt), | ||
2356 | sizeof(struct ieee80211_tdls_data)) + | ||
2357 | 50 + /* supported rates */ | ||
2358 | 7 + /* ext capab */ | ||
2359 | extra_ies_len + | ||
2360 | sizeof(struct ieee80211_tdls_lnkie)); | ||
2361 | if (!skb) | ||
2362 | return -ENOMEM; | ||
2363 | |||
2364 | info = IEEE80211_SKB_CB(skb); | ||
2365 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
2366 | |||
2367 | switch (action_code) { | ||
2368 | case WLAN_TDLS_SETUP_REQUEST: | ||
2369 | case WLAN_TDLS_SETUP_RESPONSE: | ||
2370 | case WLAN_TDLS_SETUP_CONFIRM: | ||
2371 | case WLAN_TDLS_TEARDOWN: | ||
2372 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
2373 | ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer, | ||
2374 | action_code, dialog_token, | ||
2375 | status_code, skb); | ||
2376 | send_direct = false; | ||
2377 | break; | ||
2378 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
2379 | ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code, | ||
2380 | dialog_token, status_code, | ||
2381 | skb); | ||
2382 | send_direct = true; | ||
2383 | break; | ||
2384 | default: | ||
2385 | ret = -ENOTSUPP; | ||
2386 | break; | ||
2387 | } | ||
2388 | |||
2389 | if (ret < 0) | ||
2390 | goto fail; | ||
2391 | |||
2392 | if (extra_ies_len) | ||
2393 | memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); | ||
2394 | |||
2395 | /* the TDLS link IE is always added last */ | ||
2396 | switch (action_code) { | ||
2397 | case WLAN_TDLS_SETUP_REQUEST: | ||
2398 | case WLAN_TDLS_SETUP_CONFIRM: | ||
2399 | case WLAN_TDLS_TEARDOWN: | ||
2400 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
2401 | /* we are the initiator */ | ||
2402 | ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer, | ||
2403 | sdata->u.mgd.bssid); | ||
2404 | break; | ||
2405 | case WLAN_TDLS_SETUP_RESPONSE: | ||
2406 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
2407 | /* we are the responder */ | ||
2408 | ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr, | ||
2409 | sdata->u.mgd.bssid); | ||
2410 | break; | ||
2411 | default: | ||
2412 | ret = -ENOTSUPP; | ||
2413 | goto fail; | ||
2414 | } | ||
2415 | |||
2416 | if (send_direct) { | ||
2417 | ieee80211_tx_skb(sdata, skb); | ||
2418 | return 0; | ||
2419 | } | ||
2420 | |||
2421 | /* | ||
2422 | * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise | ||
2423 | * we should default to AC_VI. | ||
2424 | */ | ||
2425 | switch (action_code) { | ||
2426 | case WLAN_TDLS_SETUP_REQUEST: | ||
2427 | case WLAN_TDLS_SETUP_RESPONSE: | ||
2428 | skb_set_queue_mapping(skb, IEEE80211_AC_BK); | ||
2429 | skb->priority = 2; | ||
2430 | break; | ||
2431 | default: | ||
2432 | skb_set_queue_mapping(skb, IEEE80211_AC_VI); | ||
2433 | skb->priority = 5; | ||
2434 | break; | ||
2435 | } | ||
2436 | |||
2437 | /* disable bottom halves when entering the Tx path */ | ||
2438 | local_bh_disable(); | ||
2439 | ret = ieee80211_subif_start_xmit(skb, dev); | ||
2440 | local_bh_enable(); | ||
2441 | |||
2442 | return ret; | ||
2443 | |||
2444 | fail: | ||
2445 | dev_kfree_skb(skb); | ||
2446 | return ret; | ||
2447 | } | ||
2448 | |||
2449 | static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | ||
2450 | u8 *peer, enum nl80211_tdls_operation oper) | ||
2451 | { | ||
2452 | struct sta_info *sta; | ||
2453 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2454 | |||
2455 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
2456 | return -ENOTSUPP; | ||
2457 | |||
2458 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
2459 | return -EINVAL; | ||
2460 | |||
2461 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG | ||
2462 | printk(KERN_DEBUG "TDLS oper %d peer %pM\n", oper, peer); | ||
2463 | #endif | ||
2464 | |||
2465 | switch (oper) { | ||
2466 | case NL80211_TDLS_ENABLE_LINK: | ||
2467 | rcu_read_lock(); | ||
2468 | sta = sta_info_get(sdata, peer); | ||
2469 | if (!sta) { | ||
2470 | rcu_read_unlock(); | ||
2471 | return -ENOLINK; | ||
2472 | } | ||
2473 | |||
2474 | set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); | ||
2475 | rcu_read_unlock(); | ||
2476 | break; | ||
2477 | case NL80211_TDLS_DISABLE_LINK: | ||
2478 | return sta_info_destroy_addr(sdata, peer); | ||
2479 | case NL80211_TDLS_TEARDOWN: | ||
2480 | case NL80211_TDLS_SETUP: | ||
2481 | case NL80211_TDLS_DISCOVERY_REQ: | ||
2482 | /* We don't support in-driver setup/teardown/discovery */ | ||
2483 | return -ENOTSUPP; | ||
2484 | default: | ||
2485 | return -ENOTSUPP; | ||
2486 | } | ||
2487 | |||
2488 | return 0; | ||
2489 | } | ||
2490 | |||
2126 | struct cfg80211_ops mac80211_config_ops = { | 2491 | struct cfg80211_ops mac80211_config_ops = { |
2127 | .add_virtual_intf = ieee80211_add_iface, | 2492 | .add_virtual_intf = ieee80211_add_iface, |
2128 | .del_virtual_intf = ieee80211_del_iface, | 2493 | .del_virtual_intf = ieee80211_del_iface, |
@@ -2186,4 +2551,6 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2186 | .set_ringparam = ieee80211_set_ringparam, | 2551 | .set_ringparam = ieee80211_set_ringparam, |
2187 | .get_ringparam = ieee80211_get_ringparam, | 2552 | .get_ringparam = ieee80211_get_ringparam, |
2188 | .set_rekey_data = ieee80211_set_rekey_data, | 2553 | .set_rekey_data = ieee80211_set_rekey_data, |
2554 | .tdls_oper = ieee80211_tdls_oper, | ||
2555 | .tdls_mgmt = ieee80211_tdls_mgmt, | ||
2189 | }; | 2556 | }; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 186e02f7cc32..883996b2f99f 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -78,57 +78,6 @@ DEBUGFS_READONLY_FILE(wep_iv, "%#08x", | |||
78 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", | 78 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", |
79 | local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); | 79 | local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); |
80 | 80 | ||
81 | static ssize_t tsf_read(struct file *file, char __user *user_buf, | ||
82 | size_t count, loff_t *ppos) | ||
83 | { | ||
84 | struct ieee80211_local *local = file->private_data; | ||
85 | u64 tsf; | ||
86 | |||
87 | tsf = drv_get_tsf(local); | ||
88 | |||
89 | return mac80211_format_buffer(user_buf, count, ppos, "0x%016llx\n", | ||
90 | (unsigned long long) tsf); | ||
91 | } | ||
92 | |||
93 | static ssize_t tsf_write(struct file *file, | ||
94 | const char __user *user_buf, | ||
95 | size_t count, loff_t *ppos) | ||
96 | { | ||
97 | struct ieee80211_local *local = file->private_data; | ||
98 | unsigned long long tsf; | ||
99 | char buf[100]; | ||
100 | size_t len; | ||
101 | |||
102 | len = min(count, sizeof(buf) - 1); | ||
103 | if (copy_from_user(buf, user_buf, len)) | ||
104 | return -EFAULT; | ||
105 | buf[len] = '\0'; | ||
106 | |||
107 | if (strncmp(buf, "reset", 5) == 0) { | ||
108 | if (local->ops->reset_tsf) { | ||
109 | drv_reset_tsf(local); | ||
110 | wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); | ||
111 | } | ||
112 | } else { | ||
113 | tsf = simple_strtoul(buf, NULL, 0); | ||
114 | if (local->ops->set_tsf) { | ||
115 | drv_set_tsf(local, tsf); | ||
116 | wiphy_info(local->hw.wiphy, | ||
117 | "debugfs set TSF to %#018llx\n", tsf); | ||
118 | |||
119 | } | ||
120 | } | ||
121 | |||
122 | return count; | ||
123 | } | ||
124 | |||
125 | static const struct file_operations tsf_ops = { | ||
126 | .read = tsf_read, | ||
127 | .write = tsf_write, | ||
128 | .open = mac80211_open_file_generic, | ||
129 | .llseek = default_llseek, | ||
130 | }; | ||
131 | |||
132 | static ssize_t reset_write(struct file *file, const char __user *user_buf, | 81 | static ssize_t reset_write(struct file *file, const char __user *user_buf, |
133 | size_t count, loff_t *ppos) | 82 | size_t count, loff_t *ppos) |
134 | { | 83 | { |
@@ -195,20 +144,12 @@ static ssize_t uapsd_queues_write(struct file *file, | |||
195 | size_t count, loff_t *ppos) | 144 | size_t count, loff_t *ppos) |
196 | { | 145 | { |
197 | struct ieee80211_local *local = file->private_data; | 146 | struct ieee80211_local *local = file->private_data; |
198 | unsigned long val; | 147 | u8 val; |
199 | char buf[10]; | ||
200 | size_t len; | ||
201 | int ret; | 148 | int ret; |
202 | 149 | ||
203 | len = min(count, sizeof(buf) - 1); | 150 | ret = kstrtou8_from_user(user_buf, count, 0, &val); |
204 | if (copy_from_user(buf, user_buf, len)) | ||
205 | return -EFAULT; | ||
206 | buf[len] = '\0'; | ||
207 | |||
208 | ret = strict_strtoul(buf, 0, &val); | ||
209 | |||
210 | if (ret) | 151 | if (ret) |
211 | return -EINVAL; | 152 | return ret; |
212 | 153 | ||
213 | if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) | 154 | if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) |
214 | return -ERANGE; | 155 | return -ERANGE; |
@@ -305,6 +246,9 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, | |||
305 | char *buf = kzalloc(mxln, GFP_KERNEL); | 246 | char *buf = kzalloc(mxln, GFP_KERNEL); |
306 | int sf = 0; /* how many written so far */ | 247 | int sf = 0; /* how many written so far */ |
307 | 248 | ||
249 | if (!buf) | ||
250 | return 0; | ||
251 | |||
308 | sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); | 252 | sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); |
309 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | 253 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) |
310 | sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); | 254 | sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); |
@@ -355,6 +299,8 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, | |||
355 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); | 299 | sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); |
356 | if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) | 300 | if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) |
357 | sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); | 301 | sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); |
302 | if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) | ||
303 | sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); | ||
358 | 304 | ||
359 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | 305 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); |
360 | kfree(buf); | 306 | kfree(buf); |
@@ -450,7 +396,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
450 | DEBUGFS_ADD(frequency); | 396 | DEBUGFS_ADD(frequency); |
451 | DEBUGFS_ADD(total_ps_buffered); | 397 | DEBUGFS_ADD(total_ps_buffered); |
452 | DEBUGFS_ADD(wep_iv); | 398 | DEBUGFS_ADD(wep_iv); |
453 | DEBUGFS_ADD(tsf); | ||
454 | DEBUGFS_ADD(queues); | 399 | DEBUGFS_ADD(queues); |
455 | DEBUGFS_ADD_MODE(reset, 0200); | 400 | DEBUGFS_ADD_MODE(reset, 0200); |
456 | DEBUGFS_ADD(noack); | 401 | DEBUGFS_ADD(noack); |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9ea7c0d0103f..9352819a986b 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "rate.h" | 21 | #include "rate.h" |
22 | #include "debugfs.h" | 22 | #include "debugfs.h" |
23 | #include "debugfs_netdev.h" | 23 | #include "debugfs_netdev.h" |
24 | #include "driver-ops.h" | ||
24 | 25 | ||
25 | static ssize_t ieee80211_if_read( | 26 | static ssize_t ieee80211_if_read( |
26 | struct ieee80211_sub_if_data *sdata, | 27 | struct ieee80211_sub_if_data *sdata, |
@@ -331,6 +332,46 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( | |||
331 | } | 332 | } |
332 | __IEEE80211_IF_FILE(num_buffered_multicast, NULL); | 333 | __IEEE80211_IF_FILE(num_buffered_multicast, NULL); |
333 | 334 | ||
335 | /* IBSS attributes */ | ||
336 | static ssize_t ieee80211_if_fmt_tsf( | ||
337 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | ||
338 | { | ||
339 | struct ieee80211_local *local = sdata->local; | ||
340 | u64 tsf; | ||
341 | |||
342 | tsf = drv_get_tsf(local, (struct ieee80211_sub_if_data *)sdata); | ||
343 | |||
344 | return scnprintf(buf, buflen, "0x%016llx\n", (unsigned long long) tsf); | ||
345 | } | ||
346 | |||
347 | static ssize_t ieee80211_if_parse_tsf( | ||
348 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) | ||
349 | { | ||
350 | struct ieee80211_local *local = sdata->local; | ||
351 | unsigned long long tsf; | ||
352 | int ret; | ||
353 | |||
354 | if (strncmp(buf, "reset", 5) == 0) { | ||
355 | if (local->ops->reset_tsf) { | ||
356 | drv_reset_tsf(local, sdata); | ||
357 | wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); | ||
358 | } | ||
359 | } else { | ||
360 | ret = kstrtoull(buf, 10, &tsf); | ||
361 | if (ret < 0) | ||
362 | return -EINVAL; | ||
363 | if (local->ops->set_tsf) { | ||
364 | drv_set_tsf(local, sdata, tsf); | ||
365 | wiphy_info(local->hw.wiphy, | ||
366 | "debugfs set TSF to %#018llx\n", tsf); | ||
367 | } | ||
368 | } | ||
369 | |||
370 | return buflen; | ||
371 | } | ||
372 | __IEEE80211_IF_FILE_W(tsf); | ||
373 | |||
374 | |||
334 | /* WDS attributes */ | 375 | /* WDS attributes */ |
335 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | 376 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); |
336 | 377 | ||
@@ -340,6 +381,8 @@ IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC); | |||
340 | IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC); | 381 | IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC); |
341 | IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); | 382 | IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); |
342 | IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); | 383 | IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); |
384 | IEEE80211_IF_FILE(dropped_frames_congestion, | ||
385 | u.mesh.mshstats.dropped_frames_congestion, DEC); | ||
343 | IEEE80211_IF_FILE(dropped_frames_no_route, | 386 | IEEE80211_IF_FILE(dropped_frames_no_route, |
344 | u.mesh.mshstats.dropped_frames_no_route, DEC); | 387 | u.mesh.mshstats.dropped_frames_no_route, DEC); |
345 | IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); | 388 | IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); |
@@ -372,6 +415,10 @@ IEEE80211_IF_FILE(min_discovery_timeout, | |||
372 | u.mesh.mshcfg.min_discovery_timeout, DEC); | 415 | u.mesh.mshcfg.min_discovery_timeout, DEC); |
373 | IEEE80211_IF_FILE(dot11MeshHWMPRootMode, | 416 | IEEE80211_IF_FILE(dot11MeshHWMPRootMode, |
374 | u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC); | 417 | u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC); |
418 | IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol, | ||
419 | u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC); | ||
420 | IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, | ||
421 | u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC); | ||
375 | #endif | 422 | #endif |
376 | 423 | ||
377 | 424 | ||
@@ -415,6 +462,11 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
415 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | 462 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); |
416 | } | 463 | } |
417 | 464 | ||
465 | static void add_ibss_files(struct ieee80211_sub_if_data *sdata) | ||
466 | { | ||
467 | DEBUGFS_ADD_MODE(tsf, 0600); | ||
468 | } | ||
469 | |||
418 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 470 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
419 | { | 471 | { |
420 | DEBUGFS_ADD(drop_unencrypted); | 472 | DEBUGFS_ADD(drop_unencrypted); |
@@ -459,6 +511,7 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) | |||
459 | MESHSTATS_ADD(fwded_frames); | 511 | MESHSTATS_ADD(fwded_frames); |
460 | MESHSTATS_ADD(dropped_frames_ttl); | 512 | MESHSTATS_ADD(dropped_frames_ttl); |
461 | MESHSTATS_ADD(dropped_frames_no_route); | 513 | MESHSTATS_ADD(dropped_frames_no_route); |
514 | MESHSTATS_ADD(dropped_frames_congestion); | ||
462 | MESHSTATS_ADD(estab_plinks); | 515 | MESHSTATS_ADD(estab_plinks); |
463 | #undef MESHSTATS_ADD | 516 | #undef MESHSTATS_ADD |
464 | } | 517 | } |
@@ -485,7 +538,9 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
485 | MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); | 538 | MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); |
486 | MESHPARAMS_ADD(path_refresh_time); | 539 | MESHPARAMS_ADD(path_refresh_time); |
487 | MESHPARAMS_ADD(min_discovery_timeout); | 540 | MESHPARAMS_ADD(min_discovery_timeout); |
488 | 541 | MESHPARAMS_ADD(dot11MeshHWMPRootMode); | |
542 | MESHPARAMS_ADD(dot11MeshHWMPRannInterval); | ||
543 | MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); | ||
489 | #undef MESHPARAMS_ADD | 544 | #undef MESHPARAMS_ADD |
490 | } | 545 | } |
491 | #endif | 546 | #endif |
@@ -506,7 +561,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
506 | add_sta_files(sdata); | 561 | add_sta_files(sdata); |
507 | break; | 562 | break; |
508 | case NL80211_IFTYPE_ADHOC: | 563 | case NL80211_IFTYPE_ADHOC: |
509 | /* XXX */ | 564 | add_ibss_files(sdata); |
510 | break; | 565 | break; |
511 | case NL80211_IFTYPE_AP: | 566 | case NL80211_IFTYPE_AP: |
512 | add_ap_files(sdata); | 567 | add_ap_files(sdata); |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index a01d2137fddc..c5f341798c16 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -56,19 +56,22 @@ STA_FILE(last_signal, last_signal, D); | |||
56 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | 56 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, |
57 | size_t count, loff_t *ppos) | 57 | size_t count, loff_t *ppos) |
58 | { | 58 | { |
59 | char buf[100]; | 59 | char buf[121]; |
60 | struct sta_info *sta = file->private_data; | 60 | struct sta_info *sta = file->private_data; |
61 | u32 staflags = get_sta_flags(sta); | 61 | |
62 | int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s", | 62 | #define TEST(flg) \ |
63 | staflags & WLAN_STA_AUTH ? "AUTH\n" : "", | 63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" |
64 | staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", | 64 | |
65 | staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "", | 65 | int res = scnprintf(buf, sizeof(buf), |
66 | staflags & WLAN_STA_PS_DRIVER ? "PS (driver)\n" : "", | 66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", |
67 | staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", | 67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), |
68 | staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", | 68 | TEST(PS_DRIVER), TEST(AUTHORIZED), |
69 | staflags & WLAN_STA_WME ? "WME\n" : "", | 69 | TEST(SHORT_PREAMBLE), TEST(ASSOC_AP), |
70 | staflags & WLAN_STA_WDS ? "WDS\n" : "", | 70 | TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), |
71 | staflags & WLAN_STA_MFP ? "MFP\n" : ""); | 71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), |
72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), | ||
73 | TEST(TDLS_PEER_AUTH)); | ||
74 | #undef TEST | ||
72 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 75 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
73 | } | 76 | } |
74 | STA_OPS(flags); | 77 | STA_OPS(flags); |
@@ -78,8 +81,14 @@ static ssize_t sta_num_ps_buf_frames_read(struct file *file, | |||
78 | size_t count, loff_t *ppos) | 81 | size_t count, loff_t *ppos) |
79 | { | 82 | { |
80 | struct sta_info *sta = file->private_data; | 83 | struct sta_info *sta = file->private_data; |
81 | return mac80211_format_buffer(userbuf, count, ppos, "%u\n", | 84 | char buf[17*IEEE80211_NUM_ACS], *p = buf; |
82 | skb_queue_len(&sta->ps_tx_buf)); | 85 | int ac; |
86 | |||
87 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
88 | p += scnprintf(p, sizeof(buf)+buf-p, "AC%d: %d\n", ac, | ||
89 | skb_queue_len(&sta->ps_tx_buf[ac]) + | ||
90 | skb_queue_len(&sta->tx_filtered[ac])); | ||
91 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | ||
83 | } | 92 | } |
84 | STA_OPS(num_ps_buf_frames); | 93 | STA_OPS(num_ps_buf_frames); |
85 | 94 | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 1425380983f7..5f165d7eb2db 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -413,50 +413,56 @@ static inline void drv_sta_remove(struct ieee80211_local *local, | |||
413 | trace_drv_return_void(local); | 413 | trace_drv_return_void(local); |
414 | } | 414 | } |
415 | 415 | ||
416 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | 416 | static inline int drv_conf_tx(struct ieee80211_local *local, |
417 | struct ieee80211_sub_if_data *sdata, u16 queue, | ||
417 | const struct ieee80211_tx_queue_params *params) | 418 | const struct ieee80211_tx_queue_params *params) |
418 | { | 419 | { |
419 | int ret = -EOPNOTSUPP; | 420 | int ret = -EOPNOTSUPP; |
420 | 421 | ||
421 | might_sleep(); | 422 | might_sleep(); |
422 | 423 | ||
423 | trace_drv_conf_tx(local, queue, params); | 424 | trace_drv_conf_tx(local, sdata, queue, params); |
424 | if (local->ops->conf_tx) | 425 | if (local->ops->conf_tx) |
425 | ret = local->ops->conf_tx(&local->hw, queue, params); | 426 | ret = local->ops->conf_tx(&local->hw, &sdata->vif, |
427 | queue, params); | ||
426 | trace_drv_return_int(local, ret); | 428 | trace_drv_return_int(local, ret); |
427 | return ret; | 429 | return ret; |
428 | } | 430 | } |
429 | 431 | ||
430 | static inline u64 drv_get_tsf(struct ieee80211_local *local) | 432 | static inline u64 drv_get_tsf(struct ieee80211_local *local, |
433 | struct ieee80211_sub_if_data *sdata) | ||
431 | { | 434 | { |
432 | u64 ret = -1ULL; | 435 | u64 ret = -1ULL; |
433 | 436 | ||
434 | might_sleep(); | 437 | might_sleep(); |
435 | 438 | ||
436 | trace_drv_get_tsf(local); | 439 | trace_drv_get_tsf(local, sdata); |
437 | if (local->ops->get_tsf) | 440 | if (local->ops->get_tsf) |
438 | ret = local->ops->get_tsf(&local->hw); | 441 | ret = local->ops->get_tsf(&local->hw, &sdata->vif); |
439 | trace_drv_return_u64(local, ret); | 442 | trace_drv_return_u64(local, ret); |
440 | return ret; | 443 | return ret; |
441 | } | 444 | } |
442 | 445 | ||
443 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | 446 | static inline void drv_set_tsf(struct ieee80211_local *local, |
447 | struct ieee80211_sub_if_data *sdata, | ||
448 | u64 tsf) | ||
444 | { | 449 | { |
445 | might_sleep(); | 450 | might_sleep(); |
446 | 451 | ||
447 | trace_drv_set_tsf(local, tsf); | 452 | trace_drv_set_tsf(local, sdata, tsf); |
448 | if (local->ops->set_tsf) | 453 | if (local->ops->set_tsf) |
449 | local->ops->set_tsf(&local->hw, tsf); | 454 | local->ops->set_tsf(&local->hw, &sdata->vif, tsf); |
450 | trace_drv_return_void(local); | 455 | trace_drv_return_void(local); |
451 | } | 456 | } |
452 | 457 | ||
453 | static inline void drv_reset_tsf(struct ieee80211_local *local) | 458 | static inline void drv_reset_tsf(struct ieee80211_local *local, |
459 | struct ieee80211_sub_if_data *sdata) | ||
454 | { | 460 | { |
455 | might_sleep(); | 461 | might_sleep(); |
456 | 462 | ||
457 | trace_drv_reset_tsf(local); | 463 | trace_drv_reset_tsf(local, sdata); |
458 | if (local->ops->reset_tsf) | 464 | if (local->ops->reset_tsf) |
459 | local->ops->reset_tsf(&local->hw); | 465 | local->ops->reset_tsf(&local->hw, &sdata->vif); |
460 | trace_drv_return_void(local); | 466 | trace_drv_return_void(local); |
461 | } | 467 | } |
462 | 468 | ||
@@ -590,37 +596,6 @@ static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local) | |||
590 | return ret; | 596 | return ret; |
591 | } | 597 | } |
592 | 598 | ||
593 | static inline int drv_offchannel_tx(struct ieee80211_local *local, | ||
594 | struct sk_buff *skb, | ||
595 | struct ieee80211_channel *chan, | ||
596 | enum nl80211_channel_type channel_type, | ||
597 | unsigned int wait) | ||
598 | { | ||
599 | int ret; | ||
600 | |||
601 | might_sleep(); | ||
602 | |||
603 | trace_drv_offchannel_tx(local, skb, chan, channel_type, wait); | ||
604 | ret = local->ops->offchannel_tx(&local->hw, skb, chan, | ||
605 | channel_type, wait); | ||
606 | trace_drv_return_int(local, ret); | ||
607 | |||
608 | return ret; | ||
609 | } | ||
610 | |||
611 | static inline int drv_offchannel_tx_cancel_wait(struct ieee80211_local *local) | ||
612 | { | ||
613 | int ret; | ||
614 | |||
615 | might_sleep(); | ||
616 | |||
617 | trace_drv_offchannel_tx_cancel_wait(local); | ||
618 | ret = local->ops->offchannel_tx_cancel_wait(&local->hw); | ||
619 | trace_drv_return_int(local, ret); | ||
620 | |||
621 | return ret; | ||
622 | } | ||
623 | |||
624 | static inline int drv_set_ringparam(struct ieee80211_local *local, | 599 | static inline int drv_set_ringparam(struct ieee80211_local *local, |
625 | u32 tx, u32 rx) | 600 | u32 tx, u32 rx) |
626 | { | 601 | { |
@@ -696,4 +671,34 @@ static inline void drv_rssi_callback(struct ieee80211_local *local, | |||
696 | local->ops->rssi_callback(&local->hw, event); | 671 | local->ops->rssi_callback(&local->hw, event); |
697 | trace_drv_return_void(local); | 672 | trace_drv_return_void(local); |
698 | } | 673 | } |
674 | |||
675 | static inline void | ||
676 | drv_release_buffered_frames(struct ieee80211_local *local, | ||
677 | struct sta_info *sta, u16 tids, int num_frames, | ||
678 | enum ieee80211_frame_release_type reason, | ||
679 | bool more_data) | ||
680 | { | ||
681 | trace_drv_release_buffered_frames(local, &sta->sta, tids, num_frames, | ||
682 | reason, more_data); | ||
683 | if (local->ops->release_buffered_frames) | ||
684 | local->ops->release_buffered_frames(&local->hw, &sta->sta, tids, | ||
685 | num_frames, reason, | ||
686 | more_data); | ||
687 | trace_drv_return_void(local); | ||
688 | } | ||
689 | |||
690 | static inline void | ||
691 | drv_allow_buffered_frames(struct ieee80211_local *local, | ||
692 | struct sta_info *sta, u16 tids, int num_frames, | ||
693 | enum ieee80211_frame_release_type reason, | ||
694 | bool more_data) | ||
695 | { | ||
696 | trace_drv_allow_buffered_frames(local, &sta->sta, tids, num_frames, | ||
697 | reason, more_data); | ||
698 | if (local->ops->allow_buffered_frames) | ||
699 | local->ops->allow_buffered_frames(&local->hw, &sta->sta, | ||
700 | tids, num_frames, reason, | ||
701 | more_data); | ||
702 | trace_drv_return_void(local); | ||
703 | } | ||
699 | #endif /* __MAC80211_DRIVER_OPS */ | 704 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index f47b00dc7afd..2af4fca55337 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -697,64 +697,76 @@ TRACE_EVENT(drv_sta_remove, | |||
697 | ); | 697 | ); |
698 | 698 | ||
699 | TRACE_EVENT(drv_conf_tx, | 699 | TRACE_EVENT(drv_conf_tx, |
700 | TP_PROTO(struct ieee80211_local *local, u16 queue, | 700 | TP_PROTO(struct ieee80211_local *local, |
701 | struct ieee80211_sub_if_data *sdata, | ||
702 | u16 queue, | ||
701 | const struct ieee80211_tx_queue_params *params), | 703 | const struct ieee80211_tx_queue_params *params), |
702 | 704 | ||
703 | TP_ARGS(local, queue, params), | 705 | TP_ARGS(local, sdata, queue, params), |
704 | 706 | ||
705 | TP_STRUCT__entry( | 707 | TP_STRUCT__entry( |
706 | LOCAL_ENTRY | 708 | LOCAL_ENTRY |
709 | VIF_ENTRY | ||
707 | __field(u16, queue) | 710 | __field(u16, queue) |
708 | __field(u16, txop) | 711 | __field(u16, txop) |
709 | __field(u16, cw_min) | 712 | __field(u16, cw_min) |
710 | __field(u16, cw_max) | 713 | __field(u16, cw_max) |
711 | __field(u8, aifs) | 714 | __field(u8, aifs) |
715 | __field(bool, uapsd) | ||
712 | ), | 716 | ), |
713 | 717 | ||
714 | TP_fast_assign( | 718 | TP_fast_assign( |
715 | LOCAL_ASSIGN; | 719 | LOCAL_ASSIGN; |
720 | VIF_ASSIGN; | ||
716 | __entry->queue = queue; | 721 | __entry->queue = queue; |
717 | __entry->txop = params->txop; | 722 | __entry->txop = params->txop; |
718 | __entry->cw_max = params->cw_max; | 723 | __entry->cw_max = params->cw_max; |
719 | __entry->cw_min = params->cw_min; | 724 | __entry->cw_min = params->cw_min; |
720 | __entry->aifs = params->aifs; | 725 | __entry->aifs = params->aifs; |
726 | __entry->uapsd = params->uapsd; | ||
721 | ), | 727 | ), |
722 | 728 | ||
723 | TP_printk( | 729 | TP_printk( |
724 | LOCAL_PR_FMT " queue:%d", | 730 | LOCAL_PR_FMT VIF_PR_FMT " queue:%d", |
725 | LOCAL_PR_ARG, __entry->queue | 731 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->queue |
726 | ) | 732 | ) |
727 | ); | 733 | ); |
728 | 734 | ||
729 | DEFINE_EVENT(local_only_evt, drv_get_tsf, | 735 | DEFINE_EVENT(local_sdata_evt, drv_get_tsf, |
730 | TP_PROTO(struct ieee80211_local *local), | 736 | TP_PROTO(struct ieee80211_local *local, |
731 | TP_ARGS(local) | 737 | struct ieee80211_sub_if_data *sdata), |
738 | TP_ARGS(local, sdata) | ||
732 | ); | 739 | ); |
733 | 740 | ||
734 | TRACE_EVENT(drv_set_tsf, | 741 | TRACE_EVENT(drv_set_tsf, |
735 | TP_PROTO(struct ieee80211_local *local, u64 tsf), | 742 | TP_PROTO(struct ieee80211_local *local, |
743 | struct ieee80211_sub_if_data *sdata, | ||
744 | u64 tsf), | ||
736 | 745 | ||
737 | TP_ARGS(local, tsf), | 746 | TP_ARGS(local, sdata, tsf), |
738 | 747 | ||
739 | TP_STRUCT__entry( | 748 | TP_STRUCT__entry( |
740 | LOCAL_ENTRY | 749 | LOCAL_ENTRY |
750 | VIF_ENTRY | ||
741 | __field(u64, tsf) | 751 | __field(u64, tsf) |
742 | ), | 752 | ), |
743 | 753 | ||
744 | TP_fast_assign( | 754 | TP_fast_assign( |
745 | LOCAL_ASSIGN; | 755 | LOCAL_ASSIGN; |
756 | VIF_ASSIGN; | ||
746 | __entry->tsf = tsf; | 757 | __entry->tsf = tsf; |
747 | ), | 758 | ), |
748 | 759 | ||
749 | TP_printk( | 760 | TP_printk( |
750 | LOCAL_PR_FMT " tsf:%llu", | 761 | LOCAL_PR_FMT VIF_PR_FMT " tsf:%llu", |
751 | LOCAL_PR_ARG, (unsigned long long)__entry->tsf | 762 | LOCAL_PR_ARG, VIF_PR_ARG, (unsigned long long)__entry->tsf |
752 | ) | 763 | ) |
753 | ); | 764 | ); |
754 | 765 | ||
755 | DEFINE_EVENT(local_only_evt, drv_reset_tsf, | 766 | DEFINE_EVENT(local_sdata_evt, drv_reset_tsf, |
756 | TP_PROTO(struct ieee80211_local *local), | 767 | TP_PROTO(struct ieee80211_local *local, |
757 | TP_ARGS(local) | 768 | struct ieee80211_sub_if_data *sdata), |
769 | TP_ARGS(local, sdata) | ||
758 | ); | 770 | ); |
759 | 771 | ||
760 | DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, | 772 | DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, |
@@ -1117,6 +1129,61 @@ TRACE_EVENT(drv_rssi_callback, | |||
1117 | ) | 1129 | ) |
1118 | ); | 1130 | ); |
1119 | 1131 | ||
1132 | DECLARE_EVENT_CLASS(release_evt, | ||
1133 | TP_PROTO(struct ieee80211_local *local, | ||
1134 | struct ieee80211_sta *sta, | ||
1135 | u16 tids, int num_frames, | ||
1136 | enum ieee80211_frame_release_type reason, | ||
1137 | bool more_data), | ||
1138 | |||
1139 | TP_ARGS(local, sta, tids, num_frames, reason, more_data), | ||
1140 | |||
1141 | TP_STRUCT__entry( | ||
1142 | LOCAL_ENTRY | ||
1143 | STA_ENTRY | ||
1144 | __field(u16, tids) | ||
1145 | __field(int, num_frames) | ||
1146 | __field(int, reason) | ||
1147 | __field(bool, more_data) | ||
1148 | ), | ||
1149 | |||
1150 | TP_fast_assign( | ||
1151 | LOCAL_ASSIGN; | ||
1152 | STA_ASSIGN; | ||
1153 | __entry->tids = tids; | ||
1154 | __entry->num_frames = num_frames; | ||
1155 | __entry->reason = reason; | ||
1156 | __entry->more_data = more_data; | ||
1157 | ), | ||
1158 | |||
1159 | TP_printk( | ||
1160 | LOCAL_PR_FMT STA_PR_FMT | ||
1161 | " TIDs:0x%.4x frames:%d reason:%d more:%d", | ||
1162 | LOCAL_PR_ARG, STA_PR_ARG, __entry->tids, __entry->num_frames, | ||
1163 | __entry->reason, __entry->more_data | ||
1164 | ) | ||
1165 | ); | ||
1166 | |||
1167 | DEFINE_EVENT(release_evt, drv_release_buffered_frames, | ||
1168 | TP_PROTO(struct ieee80211_local *local, | ||
1169 | struct ieee80211_sta *sta, | ||
1170 | u16 tids, int num_frames, | ||
1171 | enum ieee80211_frame_release_type reason, | ||
1172 | bool more_data), | ||
1173 | |||
1174 | TP_ARGS(local, sta, tids, num_frames, reason, more_data) | ||
1175 | ); | ||
1176 | |||
1177 | DEFINE_EVENT(release_evt, drv_allow_buffered_frames, | ||
1178 | TP_PROTO(struct ieee80211_local *local, | ||
1179 | struct ieee80211_sta *sta, | ||
1180 | u16 tids, int num_frames, | ||
1181 | enum ieee80211_frame_release_type reason, | ||
1182 | bool more_data), | ||
1183 | |||
1184 | TP_ARGS(local, sta, tids, num_frames, reason, more_data) | ||
1185 | ); | ||
1186 | |||
1120 | /* | 1187 | /* |
1121 | * Tracing for API calls that drivers call. | 1188 | * Tracing for API calls that drivers call. |
1122 | */ | 1189 | */ |
@@ -1431,6 +1498,28 @@ TRACE_EVENT(api_enable_rssi_reports, | |||
1431 | ) | 1498 | ) |
1432 | ); | 1499 | ); |
1433 | 1500 | ||
1501 | TRACE_EVENT(api_eosp, | ||
1502 | TP_PROTO(struct ieee80211_local *local, | ||
1503 | struct ieee80211_sta *sta), | ||
1504 | |||
1505 | TP_ARGS(local, sta), | ||
1506 | |||
1507 | TP_STRUCT__entry( | ||
1508 | LOCAL_ENTRY | ||
1509 | STA_ENTRY | ||
1510 | ), | ||
1511 | |||
1512 | TP_fast_assign( | ||
1513 | LOCAL_ASSIGN; | ||
1514 | STA_ASSIGN; | ||
1515 | ), | ||
1516 | |||
1517 | TP_printk( | ||
1518 | LOCAL_PR_FMT STA_PR_FMT, | ||
1519 | LOCAL_PR_ARG, STA_PR_FMT | ||
1520 | ) | ||
1521 | ); | ||
1522 | |||
1434 | /* | 1523 | /* |
1435 | * Tracing for internal functions | 1524 | * Tracing for internal functions |
1436 | * (which may also be called in response to driver calls) | 1525 | * (which may also be called in response to driver calls) |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 7cfc286946c0..f80a35c0d000 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -130,7 +130,7 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
130 | * down by the code that set the flag, so this | 130 | * down by the code that set the flag, so this |
131 | * need not run. | 131 | * need not run. |
132 | */ | 132 | */ |
133 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) | 133 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) |
134 | return; | 134 | return; |
135 | 135 | ||
136 | mutex_lock(&sta->ampdu_mlme.mtx); | 136 | mutex_lock(&sta->ampdu_mlme.mtx); |
@@ -186,12 +186,8 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
186 | u16 params; | 186 | u16 params; |
187 | 187 | ||
188 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | 188 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); |
189 | 189 | if (!skb) | |
190 | if (!skb) { | ||
191 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
192 | "for delba frame\n", sdata->name); | ||
193 | return; | 190 | return; |
194 | } | ||
195 | 191 | ||
196 | skb_reserve(skb, local->hw.extra_tx_headroom); | 192 | skb_reserve(skb, local->hw.extra_tx_headroom); |
197 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 193 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 56c24cabf26d..ede9a8b341ac 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -81,10 +81,10 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
81 | lockdep_assert_held(&ifibss->mtx); | 81 | lockdep_assert_held(&ifibss->mtx); |
82 | 82 | ||
83 | /* Reset own TSF to allow time synchronization work. */ | 83 | /* Reset own TSF to allow time synchronization work. */ |
84 | drv_reset_tsf(local); | 84 | drv_reset_tsf(local, sdata); |
85 | 85 | ||
86 | skb = ifibss->skb; | 86 | skb = ifibss->skb; |
87 | rcu_assign_pointer(ifibss->presp, NULL); | 87 | RCU_INIT_POINTER(ifibss->presp, NULL); |
88 | synchronize_rcu(); | 88 | synchronize_rcu(); |
89 | skb->data = skb->head; | 89 | skb->data = skb->head; |
90 | skb->len = 0; | 90 | skb->len = 0; |
@@ -184,7 +184,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
184 | *pos++ = 0; /* U-APSD no in use */ | 184 | *pos++ = 0; /* U-APSD no in use */ |
185 | } | 185 | } |
186 | 186 | ||
187 | rcu_assign_pointer(ifibss->presp, skb); | 187 | RCU_INIT_POINTER(ifibss->presp, skb); |
188 | 188 | ||
189 | sdata->vif.bss_conf.beacon_int = beacon_int; | 189 | sdata->vif.bss_conf.beacon_int = beacon_int; |
190 | sdata->vif.bss_conf.basic_rates = basic_rates; | 190 | sdata->vif.bss_conf.basic_rates = basic_rates; |
@@ -314,7 +314,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
314 | } | 314 | } |
315 | 315 | ||
316 | if (sta && elems->wmm_info) | 316 | if (sta && elems->wmm_info) |
317 | set_sta_flags(sta, WLAN_STA_WME); | 317 | set_sta_flag(sta, WLAN_STA_WME); |
318 | 318 | ||
319 | rcu_read_unlock(); | 319 | rcu_read_unlock(); |
320 | } | 320 | } |
@@ -382,7 +382,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
382 | * second best option: get current TSF | 382 | * second best option: get current TSF |
383 | * (will return -1 if not supported) | 383 | * (will return -1 if not supported) |
384 | */ | 384 | */ |
385 | rx_timestamp = drv_get_tsf(local); | 385 | rx_timestamp = drv_get_tsf(local, sdata); |
386 | } | 386 | } |
387 | 387 | ||
388 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 388 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
@@ -417,7 +417,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
417 | * must be callable in atomic context. | 417 | * must be callable in atomic context. |
418 | */ | 418 | */ |
419 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 419 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
420 | u8 *bssid,u8 *addr, u32 supp_rates, | 420 | u8 *bssid, u8 *addr, u32 supp_rates, |
421 | gfp_t gfp) | 421 | gfp_t gfp) |
422 | { | 422 | { |
423 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 423 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
@@ -452,7 +452,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
452 | return NULL; | 452 | return NULL; |
453 | 453 | ||
454 | sta->last_rx = jiffies; | 454 | sta->last_rx = jiffies; |
455 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | 455 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); |
456 | 456 | ||
457 | /* make sure mandatory rates are always added */ | 457 | /* make sure mandatory rates are always added */ |
458 | sta->sta.supp_rates[band] = supp_rates | | 458 | sta->sta.supp_rates[band] = supp_rates | |
@@ -995,7 +995,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
995 | kfree(sdata->u.ibss.ie); | 995 | kfree(sdata->u.ibss.ie); |
996 | skb = rcu_dereference_protected(sdata->u.ibss.presp, | 996 | skb = rcu_dereference_protected(sdata->u.ibss.presp, |
997 | lockdep_is_held(&sdata->u.ibss.mtx)); | 997 | lockdep_is_held(&sdata->u.ibss.mtx)); |
998 | rcu_assign_pointer(sdata->u.ibss.presp, NULL); | 998 | RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); |
999 | sdata->vif.bss_conf.ibss_joined = false; | 999 | sdata->vif.bss_conf.ibss_joined = false; |
1000 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | 1000 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | |
1001 | BSS_CHANGED_IBSS); | 1001 | BSS_CHANGED_IBSS); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 400c09bea639..4c3d1f591bec 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -136,7 +136,6 @@ typedef unsigned __bitwise__ ieee80211_tx_result; | |||
136 | #define TX_DROP ((__force ieee80211_tx_result) 1u) | 136 | #define TX_DROP ((__force ieee80211_tx_result) 1u) |
137 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) | 137 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) |
138 | 138 | ||
139 | #define IEEE80211_TX_FRAGMENTED BIT(0) | ||
140 | #define IEEE80211_TX_UNICAST BIT(1) | 139 | #define IEEE80211_TX_UNICAST BIT(1) |
141 | #define IEEE80211_TX_PS_BUFFERED BIT(2) | 140 | #define IEEE80211_TX_PS_BUFFERED BIT(2) |
142 | 141 | ||
@@ -149,7 +148,6 @@ struct ieee80211_tx_data { | |||
149 | 148 | ||
150 | struct ieee80211_channel *channel; | 149 | struct ieee80211_channel *channel; |
151 | 150 | ||
152 | u16 ethertype; | ||
153 | unsigned int flags; | 151 | unsigned int flags; |
154 | }; | 152 | }; |
155 | 153 | ||
@@ -261,6 +259,7 @@ struct mesh_stats { | |||
261 | __u32 fwded_frames; /* Mesh total forwarded frames */ | 259 | __u32 fwded_frames; /* Mesh total forwarded frames */ |
262 | __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ | 260 | __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ |
263 | __u32 dropped_frames_no_route; /* Not transmitted, no route found */ | 261 | __u32 dropped_frames_no_route; /* Not transmitted, no route found */ |
262 | __u32 dropped_frames_congestion;/* Not forwarded due to congestion */ | ||
264 | atomic_t estab_plinks; | 263 | atomic_t estab_plinks; |
265 | }; | 264 | }; |
266 | 265 | ||
@@ -345,6 +344,7 @@ struct ieee80211_work { | |||
345 | struct { | 344 | struct { |
346 | struct sk_buff *frame; | 345 | struct sk_buff *frame; |
347 | u32 wait; | 346 | u32 wait; |
347 | bool status; | ||
348 | } offchan_tx; | 348 | } offchan_tx; |
349 | }; | 349 | }; |
350 | 350 | ||
@@ -514,6 +514,7 @@ struct ieee80211_if_mesh { | |||
514 | struct mesh_config mshcfg; | 514 | struct mesh_config mshcfg; |
515 | u32 mesh_seqnum; | 515 | u32 mesh_seqnum; |
516 | bool accepting_plinks; | 516 | bool accepting_plinks; |
517 | int num_gates; | ||
517 | const u8 *ie; | 518 | const u8 *ie; |
518 | u8 ie_len; | 519 | u8 ie_len; |
519 | enum { | 520 | enum { |
@@ -607,6 +608,8 @@ struct ieee80211_sub_if_data { | |||
607 | __be16 control_port_protocol; | 608 | __be16 control_port_protocol; |
608 | bool control_port_no_encrypt; | 609 | bool control_port_no_encrypt; |
609 | 610 | ||
611 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; | ||
612 | |||
610 | struct work_struct work; | 613 | struct work_struct work; |
611 | struct sk_buff_head skb_queue; | 614 | struct sk_buff_head skb_queue; |
612 | 615 | ||
@@ -660,6 +663,11 @@ enum sdata_queue_type { | |||
660 | enum { | 663 | enum { |
661 | IEEE80211_RX_MSG = 1, | 664 | IEEE80211_RX_MSG = 1, |
662 | IEEE80211_TX_STATUS_MSG = 2, | 665 | IEEE80211_TX_STATUS_MSG = 2, |
666 | IEEE80211_EOSP_MSG = 3, | ||
667 | }; | ||
668 | |||
669 | struct skb_eosp_msg_data { | ||
670 | u8 sta[ETH_ALEN], iface[ETH_ALEN]; | ||
663 | }; | 671 | }; |
664 | 672 | ||
665 | enum queue_stop_reason { | 673 | enum queue_stop_reason { |
@@ -669,6 +677,7 @@ enum queue_stop_reason { | |||
669 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, | 677 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
670 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 678 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
671 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 679 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
680 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE, | ||
672 | }; | 681 | }; |
673 | 682 | ||
674 | #ifdef CONFIG_MAC80211_LEDS | 683 | #ifdef CONFIG_MAC80211_LEDS |
@@ -748,7 +757,6 @@ struct ieee80211_local { | |||
748 | struct workqueue_struct *workqueue; | 757 | struct workqueue_struct *workqueue; |
749 | 758 | ||
750 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; | 759 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; |
751 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; | ||
752 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ | 760 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ |
753 | spinlock_t queue_stop_reason_lock; | 761 | spinlock_t queue_stop_reason_lock; |
754 | 762 | ||
@@ -1002,7 +1010,6 @@ struct ieee80211_local { | |||
1002 | unsigned int hw_roc_duration; | 1010 | unsigned int hw_roc_duration; |
1003 | u32 hw_roc_cookie; | 1011 | u32 hw_roc_cookie; |
1004 | bool hw_roc_for_tx; | 1012 | bool hw_roc_for_tx; |
1005 | unsigned long hw_offchan_tx_cookie; | ||
1006 | 1013 | ||
1007 | /* dummy netdev for use w/ NAPI */ | 1014 | /* dummy netdev for use w/ NAPI */ |
1008 | struct net_device napi_dev; | 1015 | struct net_device napi_dev; |
@@ -1022,69 +1029,6 @@ struct ieee80211_ra_tid { | |||
1022 | u16 tid; | 1029 | u16 tid; |
1023 | }; | 1030 | }; |
1024 | 1031 | ||
1025 | /* Parsed Information Elements */ | ||
1026 | struct ieee802_11_elems { | ||
1027 | u8 *ie_start; | ||
1028 | size_t total_len; | ||
1029 | |||
1030 | /* pointers to IEs */ | ||
1031 | u8 *ssid; | ||
1032 | u8 *supp_rates; | ||
1033 | u8 *fh_params; | ||
1034 | u8 *ds_params; | ||
1035 | u8 *cf_params; | ||
1036 | struct ieee80211_tim_ie *tim; | ||
1037 | u8 *ibss_params; | ||
1038 | u8 *challenge; | ||
1039 | u8 *wpa; | ||
1040 | u8 *rsn; | ||
1041 | u8 *erp_info; | ||
1042 | u8 *ext_supp_rates; | ||
1043 | u8 *wmm_info; | ||
1044 | u8 *wmm_param; | ||
1045 | struct ieee80211_ht_cap *ht_cap_elem; | ||
1046 | struct ieee80211_ht_info *ht_info_elem; | ||
1047 | struct ieee80211_meshconf_ie *mesh_config; | ||
1048 | u8 *mesh_id; | ||
1049 | u8 *peer_link; | ||
1050 | u8 *preq; | ||
1051 | u8 *prep; | ||
1052 | u8 *perr; | ||
1053 | struct ieee80211_rann_ie *rann; | ||
1054 | u8 *ch_switch_elem; | ||
1055 | u8 *country_elem; | ||
1056 | u8 *pwr_constr_elem; | ||
1057 | u8 *quiet_elem; /* first quite element */ | ||
1058 | u8 *timeout_int; | ||
1059 | |||
1060 | /* length of them, respectively */ | ||
1061 | u8 ssid_len; | ||
1062 | u8 supp_rates_len; | ||
1063 | u8 fh_params_len; | ||
1064 | u8 ds_params_len; | ||
1065 | u8 cf_params_len; | ||
1066 | u8 tim_len; | ||
1067 | u8 ibss_params_len; | ||
1068 | u8 challenge_len; | ||
1069 | u8 wpa_len; | ||
1070 | u8 rsn_len; | ||
1071 | u8 erp_info_len; | ||
1072 | u8 ext_supp_rates_len; | ||
1073 | u8 wmm_info_len; | ||
1074 | u8 wmm_param_len; | ||
1075 | u8 mesh_id_len; | ||
1076 | u8 peer_link_len; | ||
1077 | u8 preq_len; | ||
1078 | u8 prep_len; | ||
1079 | u8 perr_len; | ||
1080 | u8 ch_switch_elem_len; | ||
1081 | u8 country_elem_len; | ||
1082 | u8 pwr_constr_elem_len; | ||
1083 | u8 quiet_elem_len; | ||
1084 | u8 num_of_quiet_elem; /* can be more the one */ | ||
1085 | u8 timeout_int_len; | ||
1086 | }; | ||
1087 | |||
1088 | static inline struct ieee80211_local *hw_to_local( | 1032 | static inline struct ieee80211_local *hw_to_local( |
1089 | struct ieee80211_hw *hw) | 1033 | struct ieee80211_hw *hw) |
1090 | { | 1034 | { |
@@ -1233,23 +1177,10 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1233 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | 1177 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, |
1234 | struct net_device *dev); | 1178 | struct net_device *dev); |
1235 | 1179 | ||
1236 | /* | ||
1237 | * radiotap header for status frames | ||
1238 | */ | ||
1239 | struct ieee80211_tx_status_rtap_hdr { | ||
1240 | struct ieee80211_radiotap_header hdr; | ||
1241 | u8 rate; | ||
1242 | u8 padding_for_rate; | ||
1243 | __le16 tx_flags; | ||
1244 | u8 data_retries; | ||
1245 | } __packed; | ||
1246 | |||
1247 | |||
1248 | /* HT */ | 1180 | /* HT */ |
1249 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 1181 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, |
1250 | struct ieee80211_ht_cap *ht_cap_ie, | 1182 | struct ieee80211_ht_cap *ht_cap_ie, |
1251 | struct ieee80211_sta_ht_cap *ht_cap); | 1183 | struct ieee80211_sta_ht_cap *ht_cap); |
1252 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); | ||
1253 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | 1184 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, |
1254 | const u8 *da, u16 tid, | 1185 | const u8 *da, u16 tid, |
1255 | u16 initiator, u16 reason_code); | 1186 | u16 initiator, u16 reason_code); |
@@ -1333,6 +1264,7 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke | |||
1333 | struct ieee80211_hdr *hdr, const u8 *tsc, | 1264 | struct ieee80211_hdr *hdr, const u8 *tsc, |
1334 | gfp_t gfp); | 1265 | gfp_t gfp); |
1335 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | 1266 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); |
1267 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | ||
1336 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 1268 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
1337 | void ieee802_11_parse_elems(u8 *start, size_t len, | 1269 | void ieee802_11_parse_elems(u8 *start, size_t len, |
1338 | struct ieee802_11_elems *elems); | 1270 | struct ieee802_11_elems *elems); |
@@ -1364,11 +1296,11 @@ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | |||
1364 | enum queue_stop_reason reason); | 1296 | enum queue_stop_reason reason); |
1365 | void ieee80211_add_pending_skb(struct ieee80211_local *local, | 1297 | void ieee80211_add_pending_skb(struct ieee80211_local *local, |
1366 | struct sk_buff *skb); | 1298 | struct sk_buff *skb); |
1367 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, | 1299 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, |
1368 | struct sk_buff_head *skbs); | 1300 | struct sk_buff_head *skbs); |
1369 | int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | 1301 | void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, |
1370 | struct sk_buff_head *skbs, | 1302 | struct sk_buff_head *skbs, |
1371 | void (*fn)(void *data), void *data); | 1303 | void (*fn)(void *data), void *data); |
1372 | 1304 | ||
1373 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1305 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1374 | u16 transaction, u16 auth_alg, | 1306 | u16 transaction, u16 auth_alg, |
@@ -1386,7 +1318,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1386 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1318 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1387 | const u8 *ssid, size_t ssid_len, | 1319 | const u8 *ssid, size_t ssid_len, |
1388 | const u8 *ie, size_t ie_len, | 1320 | const u8 *ie, size_t ie_len, |
1389 | u32 ratemask, bool directed); | 1321 | u32 ratemask, bool directed, bool no_cck); |
1390 | 1322 | ||
1391 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 1323 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
1392 | const size_t supp_rates_len, | 1324 | const size_t supp_rates_len, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 556e7e6ddf0a..30d73552e9ab 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -299,8 +299,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
299 | goto err_del_interface; | 299 | goto err_del_interface; |
300 | } | 300 | } |
301 | 301 | ||
302 | /* no locking required since STA is not live yet */ | 302 | /* no atomic bitop required since STA is not live yet */ |
303 | sta->flags |= WLAN_STA_AUTHORIZED; | 303 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); |
304 | 304 | ||
305 | res = sta_info_insert(sta); | 305 | res = sta_info_insert(sta); |
306 | if (res) { | 306 | if (res) { |
@@ -456,21 +456,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
456 | BSS_CHANGED_BEACON_ENABLED); | 456 | BSS_CHANGED_BEACON_ENABLED); |
457 | 457 | ||
458 | /* remove beacon */ | 458 | /* remove beacon */ |
459 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | 459 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
460 | synchronize_rcu(); | 460 | synchronize_rcu(); |
461 | kfree(old_beacon); | 461 | kfree(old_beacon); |
462 | 462 | ||
463 | /* free all potentially still buffered bcast frames */ | ||
464 | while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { | ||
465 | local->total_ps_buffered--; | ||
466 | dev_kfree_skb(skb); | ||
467 | } | ||
468 | |||
469 | /* down all dependent devices, that is VLANs */ | 463 | /* down all dependent devices, that is VLANs */ |
470 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 464 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
471 | u.vlan.list) | 465 | u.vlan.list) |
472 | dev_close(vlan->dev); | 466 | dev_close(vlan->dev); |
473 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | 467 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); |
468 | |||
469 | /* free all potentially still buffered bcast frames */ | ||
470 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf); | ||
471 | skb_queue_purge(&sdata->u.ap.ps_bc_buf); | ||
474 | } | 472 | } |
475 | 473 | ||
476 | if (going_down) | 474 | if (going_down) |
@@ -645,7 +643,7 @@ static const struct net_device_ops ieee80211_dataif_ops = { | |||
645 | .ndo_stop = ieee80211_stop, | 643 | .ndo_stop = ieee80211_stop, |
646 | .ndo_uninit = ieee80211_teardown_sdata, | 644 | .ndo_uninit = ieee80211_teardown_sdata, |
647 | .ndo_start_xmit = ieee80211_subif_start_xmit, | 645 | .ndo_start_xmit = ieee80211_subif_start_xmit, |
648 | .ndo_set_multicast_list = ieee80211_set_multicast_list, | 646 | .ndo_set_rx_mode = ieee80211_set_multicast_list, |
649 | .ndo_change_mtu = ieee80211_change_mtu, | 647 | .ndo_change_mtu = ieee80211_change_mtu, |
650 | .ndo_set_mac_address = ieee80211_change_mac, | 648 | .ndo_set_mac_address = ieee80211_change_mac, |
651 | .ndo_select_queue = ieee80211_netdev_select_queue, | 649 | .ndo_select_queue = ieee80211_netdev_select_queue, |
@@ -689,7 +687,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = { | |||
689 | .ndo_stop = ieee80211_stop, | 687 | .ndo_stop = ieee80211_stop, |
690 | .ndo_uninit = ieee80211_teardown_sdata, | 688 | .ndo_uninit = ieee80211_teardown_sdata, |
691 | .ndo_start_xmit = ieee80211_monitor_start_xmit, | 689 | .ndo_start_xmit = ieee80211_monitor_start_xmit, |
692 | .ndo_set_multicast_list = ieee80211_set_multicast_list, | 690 | .ndo_set_rx_mode = ieee80211_set_multicast_list, |
693 | .ndo_change_mtu = ieee80211_change_mtu, | 691 | .ndo_change_mtu = ieee80211_change_mtu, |
694 | .ndo_set_mac_address = eth_mac_addr, | 692 | .ndo_set_mac_address = eth_mac_addr, |
695 | .ndo_select_queue = ieee80211_monitor_select_queue, | 693 | .ndo_select_queue = ieee80211_monitor_select_queue, |
@@ -1214,6 +1212,9 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | |||
1214 | list_del_rcu(&sdata->list); | 1212 | list_del_rcu(&sdata->list); |
1215 | mutex_unlock(&sdata->local->iflist_mtx); | 1213 | mutex_unlock(&sdata->local->iflist_mtx); |
1216 | 1214 | ||
1215 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1216 | mesh_path_flush_by_iface(sdata); | ||
1217 | |||
1217 | synchronize_rcu(); | 1218 | synchronize_rcu(); |
1218 | unregister_netdevice(sdata->dev); | 1219 | unregister_netdevice(sdata->dev); |
1219 | } | 1220 | } |
@@ -1233,6 +1234,9 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1233 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | 1234 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { |
1234 | list_del(&sdata->list); | 1235 | list_del(&sdata->list); |
1235 | 1236 | ||
1237 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1238 | mesh_path_flush_by_iface(sdata); | ||
1239 | |||
1236 | unregister_netdevice_queue(sdata->dev, &unreg_list); | 1240 | unregister_netdevice_queue(sdata->dev, &unreg_list); |
1237 | } | 1241 | } |
1238 | mutex_unlock(&local->iflist_mtx); | 1242 | mutex_unlock(&local->iflist_mtx); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 5150c6d11b57..756b157c2edd 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -464,7 +464,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
464 | * some hardware cannot handle TKIP with QoS, so | 464 | * some hardware cannot handle TKIP with QoS, so |
465 | * we indicate whether QoS could be in use. | 465 | * we indicate whether QoS could be in use. |
466 | */ | 466 | */ |
467 | if (test_sta_flags(sta, WLAN_STA_WME)) | 467 | if (test_sta_flag(sta, WLAN_STA_WME)) |
468 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; | 468 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; |
469 | } else { | 469 | } else { |
470 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 470 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
@@ -478,7 +478,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
478 | /* same here, the AP could be using QoS */ | 478 | /* same here, the AP could be using QoS */ |
479 | ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); | 479 | ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); |
480 | if (ap) { | 480 | if (ap) { |
481 | if (test_sta_flags(ap, WLAN_STA_WME)) | 481 | if (test_sta_flag(ap, WLAN_STA_WME)) |
482 | key->conf.flags |= | 482 | key->conf.flags |= |
483 | IEEE80211_KEY_FLAG_WMM_STA; | 483 | IEEE80211_KEY_FLAG_WMM_STA; |
484 | } | 484 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index acb44230b251..d999bf3b84e1 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/if_arp.h> | 19 | #include <linux/if_arp.h> |
20 | #include <linux/rtnetlink.h> | 20 | #include <linux/rtnetlink.h> |
21 | #include <linux/bitmap.h> | 21 | #include <linux/bitmap.h> |
22 | #include <linux/pm_qos_params.h> | 22 | #include <linux/pm_qos.h> |
23 | #include <linux/inetdevice.h> | 23 | #include <linux/inetdevice.h> |
24 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
25 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
@@ -325,6 +325,8 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | |||
325 | static void ieee80211_tasklet_handler(unsigned long data) | 325 | static void ieee80211_tasklet_handler(unsigned long data) |
326 | { | 326 | { |
327 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 327 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
328 | struct sta_info *sta, *tmp; | ||
329 | struct skb_eosp_msg_data *eosp_data; | ||
328 | struct sk_buff *skb; | 330 | struct sk_buff *skb; |
329 | 331 | ||
330 | while ((skb = skb_dequeue(&local->skb_queue)) || | 332 | while ((skb = skb_dequeue(&local->skb_queue)) || |
@@ -340,6 +342,18 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
340 | skb->pkt_type = 0; | 342 | skb->pkt_type = 0; |
341 | ieee80211_tx_status(local_to_hw(local), skb); | 343 | ieee80211_tx_status(local_to_hw(local), skb); |
342 | break; | 344 | break; |
345 | case IEEE80211_EOSP_MSG: | ||
346 | eosp_data = (void *)skb->cb; | ||
347 | for_each_sta_info(local, eosp_data->sta, sta, tmp) { | ||
348 | /* skip wrong virtual interface */ | ||
349 | if (memcmp(eosp_data->iface, | ||
350 | sta->sdata->vif.addr, ETH_ALEN)) | ||
351 | continue; | ||
352 | clear_sta_flag(sta, WLAN_STA_SP); | ||
353 | break; | ||
354 | } | ||
355 | dev_kfree_skb(skb); | ||
356 | break; | ||
343 | default: | 357 | default: |
344 | WARN(1, "mac80211: Packet is of unknown type %d\n", | 358 | WARN(1, "mac80211: Packet is of unknown type %d\n", |
345 | skb->pkt_type); | 359 | skb->pkt_type); |
@@ -608,6 +622,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
608 | local->hw.max_rates = 1; | 622 | local->hw.max_rates = 1; |
609 | local->hw.max_report_rates = 0; | 623 | local->hw.max_report_rates = 0; |
610 | local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; | 624 | local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; |
625 | local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; | ||
611 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 626 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
612 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 627 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
613 | local->user_power_level = -1; | 628 | local->user_power_level = -1; |
@@ -862,6 +877,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
862 | if (local->ops->sched_scan_start) | 877 | if (local->ops->sched_scan_start) |
863 | local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | 878 | local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; |
864 | 879 | ||
880 | /* mac80211 based drivers don't support internal TDLS setup */ | ||
881 | if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) | ||
882 | local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; | ||
883 | |||
865 | result = wiphy_register(local->hw.wiphy); | 884 | result = wiphy_register(local->hw.wiphy); |
866 | if (result < 0) | 885 | if (result < 0) |
867 | goto fail_wiphy_register; | 886 | goto fail_wiphy_register; |
@@ -885,12 +904,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
885 | * and we need some headroom for passing the frame to monitor | 904 | * and we need some headroom for passing the frame to monitor |
886 | * interfaces, but never both at the same time. | 905 | * interfaces, but never both at the same time. |
887 | */ | 906 | */ |
888 | #ifndef __CHECKER__ | ||
889 | BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM != | ||
890 | sizeof(struct ieee80211_tx_status_rtap_hdr)); | ||
891 | #endif | ||
892 | local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, | 907 | local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, |
893 | sizeof(struct ieee80211_tx_status_rtap_hdr)); | 908 | IEEE80211_TX_STATUS_HEADROOM); |
894 | 909 | ||
895 | debugfs_hw_add(local); | 910 | debugfs_hw_add(local); |
896 | 911 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 29e9980c8e60..a7078fdba8ca 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -13,10 +13,6 @@ | |||
13 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
14 | #include "mesh.h" | 14 | #include "mesh.h" |
15 | 15 | ||
16 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | ||
17 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | ||
18 | #define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) | ||
19 | |||
20 | #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 | 16 | #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 |
21 | #define MESHCONF_CAPAB_FORWARDING 0x08 | 17 | #define MESHCONF_CAPAB_FORWARDING 0x08 |
22 | 18 | ||
@@ -27,6 +23,17 @@ | |||
27 | int mesh_allocated; | 23 | int mesh_allocated; |
28 | static struct kmem_cache *rm_cache; | 24 | static struct kmem_cache *rm_cache; |
29 | 25 | ||
26 | #ifdef CONFIG_MAC80211_MESH | ||
27 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) | ||
28 | { | ||
29 | return (mgmt->u.action.u.mesh_action.action_code == | ||
30 | WLAN_MESH_ACTION_HWMP_PATH_SELECTION); | ||
31 | } | ||
32 | #else | ||
33 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) | ||
34 | { return false; } | ||
35 | #endif | ||
36 | |||
30 | void ieee80211s_init(void) | 37 | void ieee80211s_init(void) |
31 | { | 38 | { |
32 | mesh_pathtbl_init(); | 39 | mesh_pathtbl_init(); |
@@ -193,10 +200,9 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
193 | } | 200 | } |
194 | 201 | ||
195 | p = kmem_cache_alloc(rm_cache, GFP_ATOMIC); | 202 | p = kmem_cache_alloc(rm_cache, GFP_ATOMIC); |
196 | if (!p) { | 203 | if (!p) |
197 | printk(KERN_DEBUG "o11s: could not allocate RMC entry\n"); | ||
198 | return 0; | 204 | return 0; |
199 | } | 205 | |
200 | p->seqnum = seqnum; | 206 | p->seqnum = seqnum; |
201 | p->exp_time = jiffies + RMC_TIMEOUT; | 207 | p->exp_time = jiffies + RMC_TIMEOUT; |
202 | memcpy(p->sa, sa, ETH_ALEN); | 208 | memcpy(p->sa, sa, ETH_ALEN); |
@@ -204,89 +210,136 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
204 | return 0; | 210 | return 0; |
205 | } | 211 | } |
206 | 212 | ||
207 | void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | 213 | int |
214 | mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | ||
208 | { | 215 | { |
209 | struct ieee80211_local *local = sdata->local; | 216 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
210 | struct ieee80211_supported_band *sband; | 217 | u8 *pos, neighbors; |
211 | u8 *pos; | 218 | u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie); |
212 | int len, i, rate; | ||
213 | u8 neighbors; | ||
214 | |||
215 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
216 | len = sband->n_bitrates; | ||
217 | if (len > 8) | ||
218 | len = 8; | ||
219 | pos = skb_put(skb, len + 2); | ||
220 | *pos++ = WLAN_EID_SUPP_RATES; | ||
221 | *pos++ = len; | ||
222 | for (i = 0; i < len; i++) { | ||
223 | rate = sband->bitrates[i].bitrate; | ||
224 | *pos++ = (u8) (rate / 5); | ||
225 | } | ||
226 | |||
227 | if (sband->n_bitrates > len) { | ||
228 | pos = skb_put(skb, sband->n_bitrates - len + 2); | ||
229 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
230 | *pos++ = sband->n_bitrates - len; | ||
231 | for (i = len; i < sband->n_bitrates; i++) { | ||
232 | rate = sband->bitrates[i].bitrate; | ||
233 | *pos++ = (u8) (rate / 5); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | if (sband->band == IEEE80211_BAND_2GHZ) { | ||
238 | pos = skb_put(skb, 2 + 1); | ||
239 | *pos++ = WLAN_EID_DS_PARAMS; | ||
240 | *pos++ = 1; | ||
241 | *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq); | ||
242 | } | ||
243 | 219 | ||
244 | pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); | 220 | if (skb_tailroom(skb) < 2 + meshconf_len) |
245 | *pos++ = WLAN_EID_MESH_ID; | 221 | return -ENOMEM; |
246 | *pos++ = sdata->u.mesh.mesh_id_len; | ||
247 | if (sdata->u.mesh.mesh_id_len) | ||
248 | memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); | ||
249 | 222 | ||
250 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_meshconf_ie)); | 223 | pos = skb_put(skb, 2 + meshconf_len); |
251 | *pos++ = WLAN_EID_MESH_CONFIG; | 224 | *pos++ = WLAN_EID_MESH_CONFIG; |
252 | *pos++ = sizeof(struct ieee80211_meshconf_ie); | 225 | *pos++ = meshconf_len; |
253 | 226 | ||
254 | /* Active path selection protocol ID */ | 227 | /* Active path selection protocol ID */ |
255 | *pos++ = sdata->u.mesh.mesh_pp_id; | 228 | *pos++ = ifmsh->mesh_pp_id; |
256 | |||
257 | /* Active path selection metric ID */ | 229 | /* Active path selection metric ID */ |
258 | *pos++ = sdata->u.mesh.mesh_pm_id; | 230 | *pos++ = ifmsh->mesh_pm_id; |
259 | |||
260 | /* Congestion control mode identifier */ | 231 | /* Congestion control mode identifier */ |
261 | *pos++ = sdata->u.mesh.mesh_cc_id; | 232 | *pos++ = ifmsh->mesh_cc_id; |
262 | |||
263 | /* Synchronization protocol identifier */ | 233 | /* Synchronization protocol identifier */ |
264 | *pos++ = sdata->u.mesh.mesh_sp_id; | 234 | *pos++ = ifmsh->mesh_sp_id; |
265 | |||
266 | /* Authentication Protocol identifier */ | 235 | /* Authentication Protocol identifier */ |
267 | *pos++ = sdata->u.mesh.mesh_auth_id; | 236 | *pos++ = ifmsh->mesh_auth_id; |
268 | |||
269 | /* Mesh Formation Info - number of neighbors */ | 237 | /* Mesh Formation Info - number of neighbors */ |
270 | neighbors = atomic_read(&sdata->u.mesh.mshstats.estab_plinks); | 238 | neighbors = atomic_read(&ifmsh->mshstats.estab_plinks); |
271 | /* Number of neighbor mesh STAs or 15 whichever is smaller */ | 239 | /* Number of neighbor mesh STAs or 15 whichever is smaller */ |
272 | neighbors = (neighbors > 15) ? 15 : neighbors; | 240 | neighbors = (neighbors > 15) ? 15 : neighbors; |
273 | *pos++ = neighbors << 1; | 241 | *pos++ = neighbors << 1; |
274 | |||
275 | /* Mesh capability */ | 242 | /* Mesh capability */ |
276 | sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); | 243 | ifmsh->accepting_plinks = mesh_plink_availables(sdata); |
277 | *pos = MESHCONF_CAPAB_FORWARDING; | 244 | *pos = MESHCONF_CAPAB_FORWARDING; |
278 | *pos++ |= sdata->u.mesh.accepting_plinks ? | 245 | *pos++ |= ifmsh->accepting_plinks ? |
279 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 246 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
280 | *pos++ = 0x00; | 247 | *pos++ = 0x00; |
281 | 248 | ||
282 | if (sdata->u.mesh.ie) { | 249 | return 0; |
283 | int len = sdata->u.mesh.ie_len; | 250 | } |
284 | const u8 *data = sdata->u.mesh.ie; | 251 | |
285 | if (skb_tailroom(skb) > len) | 252 | int |
286 | memcpy(skb_put(skb, len), data, len); | 253 | mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) |
254 | { | ||
255 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
256 | u8 *pos; | ||
257 | |||
258 | if (skb_tailroom(skb) < 2 + ifmsh->mesh_id_len) | ||
259 | return -ENOMEM; | ||
260 | |||
261 | pos = skb_put(skb, 2 + ifmsh->mesh_id_len); | ||
262 | *pos++ = WLAN_EID_MESH_ID; | ||
263 | *pos++ = ifmsh->mesh_id_len; | ||
264 | if (ifmsh->mesh_id_len) | ||
265 | memcpy(pos, ifmsh->mesh_id, ifmsh->mesh_id_len); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | int | ||
271 | mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | ||
272 | { | ||
273 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
274 | u8 offset, len; | ||
275 | const u8 *data; | ||
276 | |||
277 | if (!ifmsh->ie || !ifmsh->ie_len) | ||
278 | return 0; | ||
279 | |||
280 | /* fast-forward to vendor IEs */ | ||
281 | offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0); | ||
282 | |||
283 | if (offset) { | ||
284 | len = ifmsh->ie_len - offset; | ||
285 | data = ifmsh->ie + offset; | ||
286 | if (skb_tailroom(skb) < len) | ||
287 | return -ENOMEM; | ||
288 | memcpy(skb_put(skb, len), data, len); | ||
287 | } | 289 | } |
290 | |||
291 | return 0; | ||
288 | } | 292 | } |
289 | 293 | ||
294 | int | ||
295 | mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | ||
296 | { | ||
297 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
298 | u8 len = 0; | ||
299 | const u8 *data; | ||
300 | |||
301 | if (!ifmsh->ie || !ifmsh->ie_len) | ||
302 | return 0; | ||
303 | |||
304 | /* find RSN IE */ | ||
305 | data = ifmsh->ie; | ||
306 | while (data < ifmsh->ie + ifmsh->ie_len) { | ||
307 | if (*data == WLAN_EID_RSN) { | ||
308 | len = data[1] + 2; | ||
309 | break; | ||
310 | } | ||
311 | data++; | ||
312 | } | ||
313 | |||
314 | if (len) { | ||
315 | if (skb_tailroom(skb) < len) | ||
316 | return -ENOMEM; | ||
317 | memcpy(skb_put(skb, len), data, len); | ||
318 | } | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | int mesh_add_ds_params_ie(struct sk_buff *skb, | ||
324 | struct ieee80211_sub_if_data *sdata) | ||
325 | { | ||
326 | struct ieee80211_local *local = sdata->local; | ||
327 | struct ieee80211_supported_band *sband; | ||
328 | u8 *pos; | ||
329 | |||
330 | if (skb_tailroom(skb) < 3) | ||
331 | return -ENOMEM; | ||
332 | |||
333 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
334 | if (sband->band == IEEE80211_BAND_2GHZ) { | ||
335 | pos = skb_put(skb, 2 + 1); | ||
336 | *pos++ = WLAN_EID_DS_PARAMS; | ||
337 | *pos++ = 1; | ||
338 | *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq); | ||
339 | } | ||
340 | |||
341 | return 0; | ||
342 | } | ||
290 | 343 | ||
291 | static void ieee80211_mesh_path_timer(unsigned long data) | 344 | static void ieee80211_mesh_path_timer(unsigned long data) |
292 | { | 345 | { |
@@ -352,8 +405,7 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | |||
352 | memcpy(hdr->addr3, meshsa, ETH_ALEN); | 405 | memcpy(hdr->addr3, meshsa, ETH_ALEN); |
353 | return 24; | 406 | return 24; |
354 | } else { | 407 | } else { |
355 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | | 408 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
356 | IEEE80211_FCTL_TODS); | ||
357 | /* RA TA DA SA */ | 409 | /* RA TA DA SA */ |
358 | memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */ | 410 | memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */ |
359 | memcpy(hdr->addr2, meshsa, ETH_ALEN); | 411 | memcpy(hdr->addr2, meshsa, ETH_ALEN); |
@@ -425,7 +477,8 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) | |||
425 | 477 | ||
426 | mesh_path_tx_root_frame(sdata); | 478 | mesh_path_tx_root_frame(sdata); |
427 | mod_timer(&ifmsh->mesh_path_root_timer, | 479 | mod_timer(&ifmsh->mesh_path_root_timer, |
428 | round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL)); | 480 | round_jiffies(TU_TO_EXP_TIME( |
481 | ifmsh->mshcfg.dot11MeshHWMPRannInterval))); | ||
429 | } | 482 | } |
430 | 483 | ||
431 | #ifdef CONFIG_PM | 484 | #ifdef CONFIG_PM |
@@ -433,7 +486,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | |||
433 | { | 486 | { |
434 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 487 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
435 | 488 | ||
436 | /* use atomic bitops in case both timers fire at the same time */ | 489 | /* use atomic bitops in case all timers fire at the same time */ |
437 | 490 | ||
438 | if (del_timer_sync(&ifmsh->housekeeping_timer)) | 491 | if (del_timer_sync(&ifmsh->housekeeping_timer)) |
439 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | 492 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); |
@@ -557,11 +610,18 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | |||
557 | struct ieee80211_rx_status *rx_status) | 610 | struct ieee80211_rx_status *rx_status) |
558 | { | 611 | { |
559 | switch (mgmt->u.action.category) { | 612 | switch (mgmt->u.action.category) { |
560 | case WLAN_CATEGORY_MESH_ACTION: | 613 | case WLAN_CATEGORY_SELF_PROTECTED: |
561 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | 614 | switch (mgmt->u.action.u.self_prot.action_code) { |
615 | case WLAN_SP_MESH_PEERING_OPEN: | ||
616 | case WLAN_SP_MESH_PEERING_CLOSE: | ||
617 | case WLAN_SP_MESH_PEERING_CONFIRM: | ||
618 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | ||
619 | break; | ||
620 | } | ||
562 | break; | 621 | break; |
563 | case WLAN_CATEGORY_MESH_PATH_SEL: | 622 | case WLAN_CATEGORY_MESH_ACTION: |
564 | mesh_rx_path_sel_frame(sdata, mgmt, len); | 623 | if (mesh_action_is_path_sel(mgmt)) |
624 | mesh_rx_path_sel_frame(sdata, mgmt, len); | ||
565 | break; | 625 | break; |
566 | } | 626 | } |
567 | } | 627 | } |
@@ -633,6 +693,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
633 | ifmsh->accepting_plinks = true; | 693 | ifmsh->accepting_plinks = true; |
634 | ifmsh->preq_id = 0; | 694 | ifmsh->preq_id = 0; |
635 | ifmsh->sn = 0; | 695 | ifmsh->sn = 0; |
696 | ifmsh->num_gates = 0; | ||
636 | atomic_set(&ifmsh->mpaths, 0); | 697 | atomic_set(&ifmsh->mpaths, 0); |
637 | mesh_rmc_init(sdata); | 698 | mesh_rmc_init(sdata); |
638 | ifmsh->last_preq = jiffies; | 699 | ifmsh->last_preq = jiffies; |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 249e733362e7..8c00e2d1d636 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -80,7 +80,10 @@ enum mesh_deferred_task_flags { | |||
80 | * retry | 80 | * retry |
81 | * @discovery_retries: number of discovery retries | 81 | * @discovery_retries: number of discovery retries |
82 | * @flags: mesh path flags, as specified on &enum mesh_path_flags | 82 | * @flags: mesh path flags, as specified on &enum mesh_path_flags |
83 | * @state_lock: mesh path state lock | 83 | * @state_lock: mesh path state lock used to protect changes to the |
84 | * mpath itself. No need to take this lock when adding or removing | ||
85 | * an mpath to a hash bucket on a path table. | ||
86 | * @is_gate: the destination station of this path is a mesh gate | ||
84 | * | 87 | * |
85 | * | 88 | * |
86 | * The combination of dst and sdata is unique in the mesh path table. Since the | 89 | * The combination of dst and sdata is unique in the mesh path table. Since the |
@@ -104,6 +107,7 @@ struct mesh_path { | |||
104 | u8 discovery_retries; | 107 | u8 discovery_retries; |
105 | enum mesh_path_flags flags; | 108 | enum mesh_path_flags flags; |
106 | spinlock_t state_lock; | 109 | spinlock_t state_lock; |
110 | bool is_gate; | ||
107 | }; | 111 | }; |
108 | 112 | ||
109 | /** | 113 | /** |
@@ -120,6 +124,9 @@ struct mesh_path { | |||
120 | * buckets | 124 | * buckets |
121 | * @mean_chain_len: maximum average length for the hash buckets' list, if it is | 125 | * @mean_chain_len: maximum average length for the hash buckets' list, if it is |
122 | * reached, the table will grow | 126 | * reached, the table will grow |
127 | * @known_gates: list of known mesh gates and their mpaths by the station. The | ||
128 | * gate's mpath may or may not be resolved and active. | ||
129 | * | ||
123 | * rcu_head: RCU head to free the table | 130 | * rcu_head: RCU head to free the table |
124 | */ | 131 | */ |
125 | struct mesh_table { | 132 | struct mesh_table { |
@@ -133,6 +140,8 @@ struct mesh_table { | |||
133 | int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); | 140 | int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); |
134 | int size_order; | 141 | int size_order; |
135 | int mean_chain_len; | 142 | int mean_chain_len; |
143 | struct hlist_head *known_gates; | ||
144 | spinlock_t gates_lock; | ||
136 | 145 | ||
137 | struct rcu_head rcu_head; | 146 | struct rcu_head rcu_head; |
138 | }; | 147 | }; |
@@ -166,6 +175,8 @@ struct mesh_rmc { | |||
166 | u32 idx_mask; | 175 | u32 idx_mask; |
167 | }; | 176 | }; |
168 | 177 | ||
178 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | ||
179 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | ||
169 | 180 | ||
170 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ | 181 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ |
171 | 182 | ||
@@ -177,14 +188,6 @@ struct mesh_rmc { | |||
177 | /* Maximum number of paths per interface */ | 188 | /* Maximum number of paths per interface */ |
178 | #define MESH_MAX_MPATHS 1024 | 189 | #define MESH_MAX_MPATHS 1024 |
179 | 190 | ||
180 | /* Pending ANA approval */ | ||
181 | #define MESH_PATH_SEL_ACTION 0 | ||
182 | |||
183 | /* PERR reason codes */ | ||
184 | #define PEER_RCODE_UNSPECIFIED 11 | ||
185 | #define PERR_RCODE_NO_ROUTE 12 | ||
186 | #define PERR_RCODE_DEST_UNREACH 13 | ||
187 | |||
188 | /* Public interfaces */ | 191 | /* Public interfaces */ |
189 | /* Various */ | 192 | /* Various */ |
190 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 193 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
@@ -199,6 +202,16 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, | |||
199 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); | 202 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
200 | void mesh_mgmt_ies_add(struct sk_buff *skb, | 203 | void mesh_mgmt_ies_add(struct sk_buff *skb, |
201 | struct ieee80211_sub_if_data *sdata); | 204 | struct ieee80211_sub_if_data *sdata); |
205 | int mesh_add_meshconf_ie(struct sk_buff *skb, | ||
206 | struct ieee80211_sub_if_data *sdata); | ||
207 | int mesh_add_meshid_ie(struct sk_buff *skb, | ||
208 | struct ieee80211_sub_if_data *sdata); | ||
209 | int mesh_add_rsn_ie(struct sk_buff *skb, | ||
210 | struct ieee80211_sub_if_data *sdata); | ||
211 | int mesh_add_vendor_ies(struct sk_buff *skb, | ||
212 | struct ieee80211_sub_if_data *sdata); | ||
213 | int mesh_add_ds_params_ie(struct sk_buff *skb, | ||
214 | struct ieee80211_sub_if_data *sdata); | ||
202 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | 215 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); |
203 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | 216 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); |
204 | void ieee80211s_init(void); | 217 | void ieee80211s_init(void); |
@@ -223,10 +236,13 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, | |||
223 | struct ieee80211_sub_if_data *sdata); | 236 | struct ieee80211_sub_if_data *sdata); |
224 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); | 237 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); |
225 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); | 238 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); |
226 | void mesh_path_flush(struct ieee80211_sub_if_data *sdata); | ||
227 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | 239 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
228 | struct ieee80211_mgmt *mgmt, size_t len); | 240 | struct ieee80211_mgmt *mgmt, size_t len); |
229 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); | 241 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); |
242 | |||
243 | int mesh_path_add_gate(struct mesh_path *mpath); | ||
244 | int mesh_path_send_to_gates(struct mesh_path *mpath); | ||
245 | int mesh_gate_num(struct ieee80211_sub_if_data *sdata); | ||
230 | /* Mesh plinks */ | 246 | /* Mesh plinks */ |
231 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, | 247 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, |
232 | struct ieee80211_sub_if_data *sdata, | 248 | struct ieee80211_sub_if_data *sdata, |
@@ -256,12 +272,14 @@ void mesh_pathtbl_unregister(void); | |||
256 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); | 272 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); |
257 | void mesh_path_timer(unsigned long data); | 273 | void mesh_path_timer(unsigned long data); |
258 | void mesh_path_flush_by_nexthop(struct sta_info *sta); | 274 | void mesh_path_flush_by_nexthop(struct sta_info *sta); |
275 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); | ||
259 | void mesh_path_discard_frame(struct sk_buff *skb, | 276 | void mesh_path_discard_frame(struct sk_buff *skb, |
260 | struct ieee80211_sub_if_data *sdata); | 277 | struct ieee80211_sub_if_data *sdata); |
261 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); | 278 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); |
262 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); | 279 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); |
263 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); | 280 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); |
264 | 281 | ||
282 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); | ||
265 | extern int mesh_paths_generation; | 283 | extern int mesh_paths_generation; |
266 | 284 | ||
267 | #ifdef CONFIG_MAC80211_MESH | 285 | #ifdef CONFIG_MAC80211_MESH |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 3460108810d5..174040a42887 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -8,10 +8,12 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include "wme.h" | ||
11 | #include "mesh.h" | 12 | #include "mesh.h" |
12 | 13 | ||
13 | #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG | 14 | #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG |
14 | #define mhwmp_dbg(fmt, args...) printk(KERN_DEBUG "Mesh HWMP: " fmt, ##args) | 15 | #define mhwmp_dbg(fmt, args...) \ |
16 | printk(KERN_DEBUG "Mesh HWMP (%s): " fmt "\n", sdata->name, ##args) | ||
15 | #else | 17 | #else |
16 | #define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) | 18 | #define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0) |
17 | #endif | 19 | #endif |
@@ -68,12 +70,12 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae) | |||
68 | #define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) | 70 | #define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) |
69 | #define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) | 71 | #define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) |
70 | #define PREP_IE_TTL(x) PREQ_IE_TTL(x) | 72 | #define PREP_IE_TTL(x) PREQ_IE_TTL(x) |
71 | #define PREP_IE_ORIG_ADDR(x) (x + 3) | 73 | #define PREP_IE_ORIG_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) |
72 | #define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0) | 74 | #define PREP_IE_ORIG_SN(x) u32_field_get(x, 27, AE_F_SET(x)) |
73 | #define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)) | 75 | #define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)) |
74 | #define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)) | 76 | #define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)) |
75 | #define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) | 77 | #define PREP_IE_TARGET_ADDR(x) (x + 3) |
76 | #define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x)) | 78 | #define PREP_IE_TARGET_SN(x) u32_field_get(x, 9, 0) |
77 | 79 | ||
78 | #define PERR_IE_TTL(x) (*(x)) | 80 | #define PERR_IE_TTL(x) (*(x)) |
79 | #define PERR_IE_TARGET_FLAGS(x) (*(x + 2)) | 81 | #define PERR_IE_TARGET_FLAGS(x) (*(x + 2)) |
@@ -132,24 +134,25 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
132 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 134 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
133 | /* BSSID == SA */ | 135 | /* BSSID == SA */ |
134 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 136 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
135 | mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; | 137 | mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; |
136 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 138 | mgmt->u.action.u.mesh_action.action_code = |
139 | WLAN_MESH_ACTION_HWMP_PATH_SELECTION; | ||
137 | 140 | ||
138 | switch (action) { | 141 | switch (action) { |
139 | case MPATH_PREQ: | 142 | case MPATH_PREQ: |
140 | mhwmp_dbg("sending PREQ to %pM\n", target); | 143 | mhwmp_dbg("sending PREQ to %pM", target); |
141 | ie_len = 37; | 144 | ie_len = 37; |
142 | pos = skb_put(skb, 2 + ie_len); | 145 | pos = skb_put(skb, 2 + ie_len); |
143 | *pos++ = WLAN_EID_PREQ; | 146 | *pos++ = WLAN_EID_PREQ; |
144 | break; | 147 | break; |
145 | case MPATH_PREP: | 148 | case MPATH_PREP: |
146 | mhwmp_dbg("sending PREP to %pM\n", target); | 149 | mhwmp_dbg("sending PREP to %pM", target); |
147 | ie_len = 31; | 150 | ie_len = 31; |
148 | pos = skb_put(skb, 2 + ie_len); | 151 | pos = skb_put(skb, 2 + ie_len); |
149 | *pos++ = WLAN_EID_PREP; | 152 | *pos++ = WLAN_EID_PREP; |
150 | break; | 153 | break; |
151 | case MPATH_RANN: | 154 | case MPATH_RANN: |
152 | mhwmp_dbg("sending RANN from %pM\n", orig_addr); | 155 | mhwmp_dbg("sending RANN from %pM", orig_addr); |
153 | ie_len = sizeof(struct ieee80211_rann_ie); | 156 | ie_len = sizeof(struct ieee80211_rann_ie); |
154 | pos = skb_put(skb, 2 + ie_len); | 157 | pos = skb_put(skb, 2 + ie_len); |
155 | *pos++ = WLAN_EID_RANN; | 158 | *pos++ = WLAN_EID_RANN; |
@@ -163,35 +166,63 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
163 | *pos++ = flags; | 166 | *pos++ = flags; |
164 | *pos++ = hop_count; | 167 | *pos++ = hop_count; |
165 | *pos++ = ttl; | 168 | *pos++ = ttl; |
166 | if (action == MPATH_PREQ) { | 169 | if (action == MPATH_PREP) { |
167 | memcpy(pos, &preq_id, 4); | 170 | memcpy(pos, target, ETH_ALEN); |
171 | pos += ETH_ALEN; | ||
172 | memcpy(pos, &target_sn, 4); | ||
168 | pos += 4; | 173 | pos += 4; |
169 | } | 174 | } else { |
170 | memcpy(pos, orig_addr, ETH_ALEN); | 175 | if (action == MPATH_PREQ) { |
171 | pos += ETH_ALEN; | 176 | memcpy(pos, &preq_id, 4); |
172 | memcpy(pos, &orig_sn, 4); | 177 | pos += 4; |
173 | pos += 4; | 178 | } |
174 | if (action != MPATH_RANN) { | 179 | memcpy(pos, orig_addr, ETH_ALEN); |
175 | memcpy(pos, &lifetime, 4); | 180 | pos += ETH_ALEN; |
181 | memcpy(pos, &orig_sn, 4); | ||
176 | pos += 4; | 182 | pos += 4; |
177 | } | 183 | } |
184 | memcpy(pos, &lifetime, 4); /* interval for RANN */ | ||
185 | pos += 4; | ||
178 | memcpy(pos, &metric, 4); | 186 | memcpy(pos, &metric, 4); |
179 | pos += 4; | 187 | pos += 4; |
180 | if (action == MPATH_PREQ) { | 188 | if (action == MPATH_PREQ) { |
181 | /* destination count */ | 189 | *pos++ = 1; /* destination count */ |
182 | *pos++ = 1; | ||
183 | *pos++ = target_flags; | 190 | *pos++ = target_flags; |
184 | } | ||
185 | if (action != MPATH_RANN) { | ||
186 | memcpy(pos, target, ETH_ALEN); | 191 | memcpy(pos, target, ETH_ALEN); |
187 | pos += ETH_ALEN; | 192 | pos += ETH_ALEN; |
188 | memcpy(pos, &target_sn, 4); | 193 | memcpy(pos, &target_sn, 4); |
194 | pos += 4; | ||
195 | } else if (action == MPATH_PREP) { | ||
196 | memcpy(pos, orig_addr, ETH_ALEN); | ||
197 | pos += ETH_ALEN; | ||
198 | memcpy(pos, &orig_sn, 4); | ||
199 | pos += 4; | ||
189 | } | 200 | } |
190 | 201 | ||
191 | ieee80211_tx_skb(sdata, skb); | 202 | ieee80211_tx_skb(sdata, skb); |
192 | return 0; | 203 | return 0; |
193 | } | 204 | } |
194 | 205 | ||
206 | |||
207 | /* Headroom is not adjusted. Caller should ensure that skb has sufficient | ||
208 | * headroom in case the frame is encrypted. */ | ||
209 | static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, | ||
210 | struct sk_buff *skb) | ||
211 | { | ||
212 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
213 | |||
214 | skb_set_mac_header(skb, 0); | ||
215 | skb_set_network_header(skb, 0); | ||
216 | skb_set_transport_header(skb, 0); | ||
217 | |||
218 | /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ | ||
219 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | ||
220 | skb->priority = 7; | ||
221 | |||
222 | info->control.vif = &sdata->vif; | ||
223 | ieee80211_set_qos_hdr(sdata, skb); | ||
224 | } | ||
225 | |||
195 | /** | 226 | /** |
196 | * mesh_send_path error - Sends a PERR mesh management frame | 227 | * mesh_send_path error - Sends a PERR mesh management frame |
197 | * | 228 | * |
@@ -199,6 +230,10 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
199 | * @target_sn: SN of the broken destination | 230 | * @target_sn: SN of the broken destination |
200 | * @target_rcode: reason code for this PERR | 231 | * @target_rcode: reason code for this PERR |
201 | * @ra: node this frame is addressed to | 232 | * @ra: node this frame is addressed to |
233 | * | ||
234 | * Note: This function may be called with driver locks taken that the driver | ||
235 | * also acquires in the TX path. To avoid a deadlock we don't transmit the | ||
236 | * frame directly but add it to the pending queue instead. | ||
202 | */ | 237 | */ |
203 | int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | 238 | int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, |
204 | __le16 target_rcode, const u8 *ra, | 239 | __le16 target_rcode, const u8 *ra, |
@@ -212,7 +247,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
212 | 247 | ||
213 | if (!skb) | 248 | if (!skb) |
214 | return -1; | 249 | return -1; |
215 | skb_reserve(skb, local->hw.extra_tx_headroom); | 250 | skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom); |
216 | /* 25 is the size of the common mgmt part (24) plus the size of the | 251 | /* 25 is the size of the common mgmt part (24) plus the size of the |
217 | * common action part (1) | 252 | * common action part (1) |
218 | */ | 253 | */ |
@@ -224,9 +259,11 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
224 | 259 | ||
225 | memcpy(mgmt->da, ra, ETH_ALEN); | 260 | memcpy(mgmt->da, ra, ETH_ALEN); |
226 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 261 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
227 | /* BSSID is left zeroed, wildcard value */ | 262 | /* BSSID == SA */ |
228 | mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; | 263 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
229 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 264 | mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; |
265 | mgmt->u.action.u.mesh_action.action_code = | ||
266 | WLAN_MESH_ACTION_HWMP_PATH_SELECTION; | ||
230 | ie_len = 15; | 267 | ie_len = 15; |
231 | pos = skb_put(skb, 2 + ie_len); | 268 | pos = skb_put(skb, 2 + ie_len); |
232 | *pos++ = WLAN_EID_PERR; | 269 | *pos++ = WLAN_EID_PERR; |
@@ -251,7 +288,9 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
251 | pos += 4; | 288 | pos += 4; |
252 | memcpy(pos, &target_rcode, 2); | 289 | memcpy(pos, &target_rcode, 2); |
253 | 290 | ||
254 | ieee80211_tx_skb(sdata, skb); | 291 | /* see note in function header */ |
292 | prepare_frame_for_deferred_tx(sdata, skb); | ||
293 | ieee80211_add_pending_skb(local, skb); | ||
255 | return 0; | 294 | return 0; |
256 | } | 295 | } |
257 | 296 | ||
@@ -449,7 +488,6 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
449 | 488 | ||
450 | if (fresh_info) { | 489 | if (fresh_info) { |
451 | mesh_path_assign_nexthop(mpath, sta); | 490 | mesh_path_assign_nexthop(mpath, sta); |
452 | mpath->flags &= ~MESH_PATH_SN_VALID; | ||
453 | mpath->metric = last_hop_metric; | 491 | mpath->metric = last_hop_metric; |
454 | mpath->exp_time = time_after(mpath->exp_time, exp_time) | 492 | mpath->exp_time = time_after(mpath->exp_time, exp_time) |
455 | ? mpath->exp_time : exp_time; | 493 | ? mpath->exp_time : exp_time; |
@@ -484,10 +522,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
484 | orig_sn = PREQ_IE_ORIG_SN(preq_elem); | 522 | orig_sn = PREQ_IE_ORIG_SN(preq_elem); |
485 | target_flags = PREQ_IE_TARGET_F(preq_elem); | 523 | target_flags = PREQ_IE_TARGET_F(preq_elem); |
486 | 524 | ||
487 | mhwmp_dbg("received PREQ from %pM\n", orig_addr); | 525 | mhwmp_dbg("received PREQ from %pM", orig_addr); |
488 | 526 | ||
489 | if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { | 527 | if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { |
490 | mhwmp_dbg("PREQ is for us\n"); | 528 | mhwmp_dbg("PREQ is for us"); |
491 | forward = false; | 529 | forward = false; |
492 | reply = true; | 530 | reply = true; |
493 | metric = 0; | 531 | metric = 0; |
@@ -523,7 +561,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
523 | lifetime = PREQ_IE_LIFETIME(preq_elem); | 561 | lifetime = PREQ_IE_LIFETIME(preq_elem); |
524 | ttl = ifmsh->mshcfg.element_ttl; | 562 | ttl = ifmsh->mshcfg.element_ttl; |
525 | if (ttl != 0) { | 563 | if (ttl != 0) { |
526 | mhwmp_dbg("replying to the PREQ\n"); | 564 | mhwmp_dbg("replying to the PREQ"); |
527 | mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, | 565 | mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, |
528 | cpu_to_le32(target_sn), 0, orig_addr, | 566 | cpu_to_le32(target_sn), 0, orig_addr, |
529 | cpu_to_le32(orig_sn), mgmt->sa, 0, ttl, | 567 | cpu_to_le32(orig_sn), mgmt->sa, 0, ttl, |
@@ -543,7 +581,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
543 | ifmsh->mshstats.dropped_frames_ttl++; | 581 | ifmsh->mshstats.dropped_frames_ttl++; |
544 | return; | 582 | return; |
545 | } | 583 | } |
546 | mhwmp_dbg("forwarding the PREQ from %pM\n", orig_addr); | 584 | mhwmp_dbg("forwarding the PREQ from %pM", orig_addr); |
547 | --ttl; | 585 | --ttl; |
548 | flags = PREQ_IE_FLAGS(preq_elem); | 586 | flags = PREQ_IE_FLAGS(preq_elem); |
549 | preq_id = PREQ_IE_PREQ_ID(preq_elem); | 587 | preq_id = PREQ_IE_PREQ_ID(preq_elem); |
@@ -578,7 +616,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
578 | u8 next_hop[ETH_ALEN]; | 616 | u8 next_hop[ETH_ALEN]; |
579 | u32 target_sn, orig_sn, lifetime; | 617 | u32 target_sn, orig_sn, lifetime; |
580 | 618 | ||
581 | mhwmp_dbg("received PREP from %pM\n", PREP_IE_ORIG_ADDR(prep_elem)); | 619 | mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem)); |
582 | 620 | ||
583 | /* Note that we divert from the draft nomenclature and denominate | 621 | /* Note that we divert from the draft nomenclature and denominate |
584 | * destination to what the draft refers to as origininator. So in this | 622 | * destination to what the draft refers to as origininator. So in this |
@@ -684,6 +722,8 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
684 | u8 ttl, flags, hopcount; | 722 | u8 ttl, flags, hopcount; |
685 | u8 *orig_addr; | 723 | u8 *orig_addr; |
686 | u32 orig_sn, metric; | 724 | u32 orig_sn, metric; |
725 | u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; | ||
726 | bool root_is_gate; | ||
687 | 727 | ||
688 | ttl = rann->rann_ttl; | 728 | ttl = rann->rann_ttl; |
689 | if (ttl <= 1) { | 729 | if (ttl <= 1) { |
@@ -692,12 +732,19 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
692 | } | 732 | } |
693 | ttl--; | 733 | ttl--; |
694 | flags = rann->rann_flags; | 734 | flags = rann->rann_flags; |
735 | root_is_gate = !!(flags & RANN_FLAG_IS_GATE); | ||
695 | orig_addr = rann->rann_addr; | 736 | orig_addr = rann->rann_addr; |
696 | orig_sn = rann->rann_seq; | 737 | orig_sn = rann->rann_seq; |
697 | hopcount = rann->rann_hopcount; | 738 | hopcount = rann->rann_hopcount; |
698 | hopcount++; | 739 | hopcount++; |
699 | metric = rann->rann_metric; | 740 | metric = rann->rann_metric; |
700 | mhwmp_dbg("received RANN from %pM\n", orig_addr); | 741 | |
742 | /* Ignore our own RANNs */ | ||
743 | if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) | ||
744 | return; | ||
745 | |||
746 | mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr, | ||
747 | root_is_gate); | ||
701 | 748 | ||
702 | rcu_read_lock(); | 749 | rcu_read_lock(); |
703 | mpath = mesh_path_lookup(orig_addr, sdata); | 750 | mpath = mesh_path_lookup(orig_addr, sdata); |
@@ -709,18 +756,28 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
709 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 756 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
710 | return; | 757 | return; |
711 | } | 758 | } |
712 | mesh_queue_preq(mpath, | ||
713 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); | ||
714 | } | 759 | } |
760 | |||
761 | if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) || | ||
762 | time_after(jiffies, mpath->exp_time - 1*HZ)) && | ||
763 | !(mpath->flags & MESH_PATH_FIXED)) { | ||
764 | mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name, | ||
765 | orig_addr); | ||
766 | mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); | ||
767 | } | ||
768 | |||
715 | if (mpath->sn < orig_sn) { | 769 | if (mpath->sn < orig_sn) { |
716 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, | 770 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, |
717 | cpu_to_le32(orig_sn), | 771 | cpu_to_le32(orig_sn), |
718 | 0, NULL, 0, broadcast_addr, | 772 | 0, NULL, 0, broadcast_addr, |
719 | hopcount, ttl, 0, | 773 | hopcount, ttl, cpu_to_le32(interval), |
720 | cpu_to_le32(metric + mpath->metric), | 774 | cpu_to_le32(metric + mpath->metric), |
721 | 0, sdata); | 775 | 0, sdata); |
722 | mpath->sn = orig_sn; | 776 | mpath->sn = orig_sn; |
723 | } | 777 | } |
778 | if (root_is_gate) | ||
779 | mesh_path_add_gate(mpath); | ||
780 | |||
724 | rcu_read_unlock(); | 781 | rcu_read_unlock(); |
725 | } | 782 | } |
726 | 783 | ||
@@ -732,11 +789,20 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | |||
732 | struct ieee802_11_elems elems; | 789 | struct ieee802_11_elems elems; |
733 | size_t baselen; | 790 | size_t baselen; |
734 | u32 last_hop_metric; | 791 | u32 last_hop_metric; |
792 | struct sta_info *sta; | ||
735 | 793 | ||
736 | /* need action_code */ | 794 | /* need action_code */ |
737 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 795 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) |
738 | return; | 796 | return; |
739 | 797 | ||
798 | rcu_read_lock(); | ||
799 | sta = sta_info_get(sdata, mgmt->sa); | ||
800 | if (!sta || sta->plink_state != NL80211_PLINK_ESTAB) { | ||
801 | rcu_read_unlock(); | ||
802 | return; | ||
803 | } | ||
804 | rcu_read_unlock(); | ||
805 | |||
740 | baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; | 806 | baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; |
741 | ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, | 807 | ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, |
742 | len - baselen, &elems); | 808 | len - baselen, &elems); |
@@ -788,16 +854,16 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
788 | 854 | ||
789 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); | 855 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); |
790 | if (!preq_node) { | 856 | if (!preq_node) { |
791 | mhwmp_dbg("could not allocate PREQ node\n"); | 857 | mhwmp_dbg("could not allocate PREQ node"); |
792 | return; | 858 | return; |
793 | } | 859 | } |
794 | 860 | ||
795 | spin_lock(&ifmsh->mesh_preq_queue_lock); | 861 | spin_lock_bh(&ifmsh->mesh_preq_queue_lock); |
796 | if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) { | 862 | if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) { |
797 | spin_unlock(&ifmsh->mesh_preq_queue_lock); | 863 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); |
798 | kfree(preq_node); | 864 | kfree(preq_node); |
799 | if (printk_ratelimit()) | 865 | if (printk_ratelimit()) |
800 | mhwmp_dbg("PREQ node queue full\n"); | 866 | mhwmp_dbg("PREQ node queue full"); |
801 | return; | 867 | return; |
802 | } | 868 | } |
803 | 869 | ||
@@ -806,7 +872,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
806 | 872 | ||
807 | list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); | 873 | list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); |
808 | ++ifmsh->preq_queue_len; | 874 | ++ifmsh->preq_queue_len; |
809 | spin_unlock(&ifmsh->mesh_preq_queue_lock); | 875 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); |
810 | 876 | ||
811 | if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) | 877 | if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) |
812 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 878 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
@@ -982,35 +1048,46 @@ void mesh_path_timer(unsigned long data) | |||
982 | { | 1048 | { |
983 | struct mesh_path *mpath = (void *) data; | 1049 | struct mesh_path *mpath = (void *) data; |
984 | struct ieee80211_sub_if_data *sdata = mpath->sdata; | 1050 | struct ieee80211_sub_if_data *sdata = mpath->sdata; |
1051 | int ret; | ||
985 | 1052 | ||
986 | if (sdata->local->quiescing) | 1053 | if (sdata->local->quiescing) |
987 | return; | 1054 | return; |
988 | 1055 | ||
989 | spin_lock_bh(&mpath->state_lock); | 1056 | spin_lock_bh(&mpath->state_lock); |
990 | if (mpath->flags & MESH_PATH_RESOLVED || | 1057 | if (mpath->flags & MESH_PATH_RESOLVED || |
991 | (!(mpath->flags & MESH_PATH_RESOLVING))) | 1058 | (!(mpath->flags & MESH_PATH_RESOLVING))) { |
992 | mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); | 1059 | mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); |
993 | else if (mpath->discovery_retries < max_preq_retries(sdata)) { | 1060 | spin_unlock_bh(&mpath->state_lock); |
1061 | } else if (mpath->discovery_retries < max_preq_retries(sdata)) { | ||
994 | ++mpath->discovery_retries; | 1062 | ++mpath->discovery_retries; |
995 | mpath->discovery_timeout *= 2; | 1063 | mpath->discovery_timeout *= 2; |
1064 | spin_unlock_bh(&mpath->state_lock); | ||
996 | mesh_queue_preq(mpath, 0); | 1065 | mesh_queue_preq(mpath, 0); |
997 | } else { | 1066 | } else { |
998 | mpath->flags = 0; | 1067 | mpath->flags = 0; |
999 | mpath->exp_time = jiffies; | 1068 | mpath->exp_time = jiffies; |
1000 | mesh_path_flush_pending(mpath); | 1069 | spin_unlock_bh(&mpath->state_lock); |
1070 | if (!mpath->is_gate && mesh_gate_num(sdata) > 0) { | ||
1071 | ret = mesh_path_send_to_gates(mpath); | ||
1072 | if (ret) | ||
1073 | mhwmp_dbg("no gate was reachable"); | ||
1074 | } else | ||
1075 | mesh_path_flush_pending(mpath); | ||
1001 | } | 1076 | } |
1002 | |||
1003 | spin_unlock_bh(&mpath->state_lock); | ||
1004 | } | 1077 | } |
1005 | 1078 | ||
1006 | void | 1079 | void |
1007 | mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | 1080 | mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) |
1008 | { | 1081 | { |
1009 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1082 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1083 | u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; | ||
1084 | u8 flags; | ||
1010 | 1085 | ||
1011 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, | 1086 | flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol) |
1087 | ? RANN_FLAG_IS_GATE : 0; | ||
1088 | mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr, | ||
1012 | cpu_to_le32(++ifmsh->sn), | 1089 | cpu_to_le32(++ifmsh->sn), |
1013 | 0, NULL, 0, broadcast_addr, | 1090 | 0, NULL, 0, broadcast_addr, |
1014 | 0, sdata->u.mesh.mshcfg.element_ttl, | 1091 | 0, sdata->u.mesh.mshcfg.element_ttl, |
1015 | 0, 0, 0, sdata); | 1092 | cpu_to_le32(interval), 0, 0, sdata); |
1016 | } | 1093 | } |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 068ee6518254..7f54c5042235 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -14,9 +14,16 @@ | |||
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <net/mac80211.h> | 16 | #include <net/mac80211.h> |
17 | #include "wme.h" | ||
17 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
18 | #include "mesh.h" | 19 | #include "mesh.h" |
19 | 20 | ||
21 | #ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG | ||
22 | #define mpath_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args) | ||
23 | #else | ||
24 | #define mpath_dbg(fmt, args...) do { (void)(0); } while (0) | ||
25 | #endif | ||
26 | |||
20 | /* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */ | 27 | /* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */ |
21 | #define INIT_PATHS_SIZE_ORDER 2 | 28 | #define INIT_PATHS_SIZE_ORDER 2 |
22 | 29 | ||
@@ -42,8 +49,10 @@ static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */ | |||
42 | int mesh_paths_generation; | 49 | int mesh_paths_generation; |
43 | 50 | ||
44 | /* This lock will have the grow table function as writer and add / delete nodes | 51 | /* This lock will have the grow table function as writer and add / delete nodes |
45 | * as readers. When reading the table (i.e. doing lookups) we are well protected | 52 | * as readers. RCU provides sufficient protection only when reading the table |
46 | * by RCU | 53 | * (i.e. doing lookups). Adding or adding or removing nodes requires we take |
54 | * the read lock or we risk operating on an old table. The write lock is only | ||
55 | * needed when modifying the number of buckets a table. | ||
47 | */ | 56 | */ |
48 | static DEFINE_RWLOCK(pathtbl_resize_lock); | 57 | static DEFINE_RWLOCK(pathtbl_resize_lock); |
49 | 58 | ||
@@ -60,6 +69,8 @@ static inline struct mesh_table *resize_dereference_mpp_paths(void) | |||
60 | lockdep_is_held(&pathtbl_resize_lock)); | 69 | lockdep_is_held(&pathtbl_resize_lock)); |
61 | } | 70 | } |
62 | 71 | ||
72 | static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath); | ||
73 | |||
63 | /* | 74 | /* |
64 | * CAREFUL -- "tbl" must not be an expression, | 75 | * CAREFUL -- "tbl" must not be an expression, |
65 | * in particular not an rcu_dereference(), since | 76 | * in particular not an rcu_dereference(), since |
@@ -103,6 +114,7 @@ static struct mesh_table *mesh_table_alloc(int size_order) | |||
103 | sizeof(newtbl->hash_rnd)); | 114 | sizeof(newtbl->hash_rnd)); |
104 | for (i = 0; i <= newtbl->hash_mask; i++) | 115 | for (i = 0; i <= newtbl->hash_mask; i++) |
105 | spin_lock_init(&newtbl->hashwlock[i]); | 116 | spin_lock_init(&newtbl->hashwlock[i]); |
117 | spin_lock_init(&newtbl->gates_lock); | ||
106 | 118 | ||
107 | return newtbl; | 119 | return newtbl; |
108 | } | 120 | } |
@@ -118,6 +130,7 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) | |||
118 | { | 130 | { |
119 | struct hlist_head *mesh_hash; | 131 | struct hlist_head *mesh_hash; |
120 | struct hlist_node *p, *q; | 132 | struct hlist_node *p, *q; |
133 | struct mpath_node *gate; | ||
121 | int i; | 134 | int i; |
122 | 135 | ||
123 | mesh_hash = tbl->hash_buckets; | 136 | mesh_hash = tbl->hash_buckets; |
@@ -129,6 +142,17 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) | |||
129 | } | 142 | } |
130 | spin_unlock_bh(&tbl->hashwlock[i]); | 143 | spin_unlock_bh(&tbl->hashwlock[i]); |
131 | } | 144 | } |
145 | if (free_leafs) { | ||
146 | spin_lock_bh(&tbl->gates_lock); | ||
147 | hlist_for_each_entry_safe(gate, p, q, | ||
148 | tbl->known_gates, list) { | ||
149 | hlist_del(&gate->list); | ||
150 | kfree(gate); | ||
151 | } | ||
152 | kfree(tbl->known_gates); | ||
153 | spin_unlock_bh(&tbl->gates_lock); | ||
154 | } | ||
155 | |||
132 | __mesh_table_free(tbl); | 156 | __mesh_table_free(tbl); |
133 | } | 157 | } |
134 | 158 | ||
@@ -146,6 +170,7 @@ static int mesh_table_grow(struct mesh_table *oldtbl, | |||
146 | newtbl->free_node = oldtbl->free_node; | 170 | newtbl->free_node = oldtbl->free_node; |
147 | newtbl->mean_chain_len = oldtbl->mean_chain_len; | 171 | newtbl->mean_chain_len = oldtbl->mean_chain_len; |
148 | newtbl->copy_node = oldtbl->copy_node; | 172 | newtbl->copy_node = oldtbl->copy_node; |
173 | newtbl->known_gates = oldtbl->known_gates; | ||
149 | atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries)); | 174 | atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries)); |
150 | 175 | ||
151 | oldhash = oldtbl->hash_buckets; | 176 | oldhash = oldtbl->hash_buckets; |
@@ -188,6 +213,7 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | |||
188 | struct ieee80211_hdr *hdr; | 213 | struct ieee80211_hdr *hdr; |
189 | struct sk_buff_head tmpq; | 214 | struct sk_buff_head tmpq; |
190 | unsigned long flags; | 215 | unsigned long flags; |
216 | struct ieee80211_sub_if_data *sdata = mpath->sdata; | ||
191 | 217 | ||
192 | rcu_assign_pointer(mpath->next_hop, sta); | 218 | rcu_assign_pointer(mpath->next_hop, sta); |
193 | 219 | ||
@@ -198,6 +224,8 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | |||
198 | while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { | 224 | while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { |
199 | hdr = (struct ieee80211_hdr *) skb->data; | 225 | hdr = (struct ieee80211_hdr *) skb->data; |
200 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); | 226 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); |
227 | skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb)); | ||
228 | ieee80211_set_qos_hdr(sdata, skb); | ||
201 | __skb_queue_tail(&tmpq, skb); | 229 | __skb_queue_tail(&tmpq, skb); |
202 | } | 230 | } |
203 | 231 | ||
@@ -205,62 +233,128 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | |||
205 | spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); | 233 | spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); |
206 | } | 234 | } |
207 | 235 | ||
236 | static void prepare_for_gate(struct sk_buff *skb, char *dst_addr, | ||
237 | struct mesh_path *gate_mpath) | ||
238 | { | ||
239 | struct ieee80211_hdr *hdr; | ||
240 | struct ieee80211s_hdr *mshdr; | ||
241 | int mesh_hdrlen, hdrlen; | ||
242 | char *next_hop; | ||
243 | |||
244 | hdr = (struct ieee80211_hdr *) skb->data; | ||
245 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
246 | mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | ||
247 | |||
248 | if (!(mshdr->flags & MESH_FLAGS_AE)) { | ||
249 | /* size of the fixed part of the mesh header */ | ||
250 | mesh_hdrlen = 6; | ||
251 | |||
252 | /* make room for the two extended addresses */ | ||
253 | skb_push(skb, 2 * ETH_ALEN); | ||
254 | memmove(skb->data, hdr, hdrlen + mesh_hdrlen); | ||
255 | |||
256 | hdr = (struct ieee80211_hdr *) skb->data; | ||
257 | |||
258 | /* we preserve the previous mesh header and only add | ||
259 | * the new addreses */ | ||
260 | mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | ||
261 | mshdr->flags = MESH_FLAGS_AE_A5_A6; | ||
262 | memcpy(mshdr->eaddr1, hdr->addr3, ETH_ALEN); | ||
263 | memcpy(mshdr->eaddr2, hdr->addr4, ETH_ALEN); | ||
264 | } | ||
265 | |||
266 | /* update next hop */ | ||
267 | hdr = (struct ieee80211_hdr *) skb->data; | ||
268 | rcu_read_lock(); | ||
269 | next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr; | ||
270 | memcpy(hdr->addr1, next_hop, ETH_ALEN); | ||
271 | rcu_read_unlock(); | ||
272 | memcpy(hdr->addr3, dst_addr, ETH_ALEN); | ||
273 | } | ||
208 | 274 | ||
209 | /** | 275 | /** |
210 | * mesh_path_lookup - look up a path in the mesh path table | ||
211 | * @dst: hardware address (ETH_ALEN length) of destination | ||
212 | * @sdata: local subif | ||
213 | * | 276 | * |
214 | * Returns: pointer to the mesh path structure, or NULL if not found | 277 | * mesh_path_move_to_queue - Move or copy frames from one mpath queue to another |
215 | * | 278 | * |
216 | * Locking: must be called within a read rcu section. | 279 | * This function is used to transfer or copy frames from an unresolved mpath to |
280 | * a gate mpath. The function also adds the Address Extension field and | ||
281 | * updates the next hop. | ||
282 | * | ||
283 | * If a frame already has an Address Extension field, only the next hop and | ||
284 | * destination addresses are updated. | ||
285 | * | ||
286 | * The gate mpath must be an active mpath with a valid mpath->next_hop. | ||
287 | * | ||
288 | * @mpath: An active mpath the frames will be sent to (i.e. the gate) | ||
289 | * @from_mpath: The failed mpath | ||
290 | * @copy: When true, copy all the frames to the new mpath queue. When false, | ||
291 | * move them. | ||
217 | */ | 292 | */ |
218 | struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | 293 | static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, |
294 | struct mesh_path *from_mpath, | ||
295 | bool copy) | ||
219 | { | 296 | { |
220 | struct mesh_path *mpath; | 297 | struct sk_buff *skb, *cp_skb = NULL; |
221 | struct hlist_node *n; | 298 | struct sk_buff_head gateq, failq; |
222 | struct hlist_head *bucket; | 299 | unsigned long flags; |
223 | struct mesh_table *tbl; | 300 | int num_skbs; |
224 | struct mpath_node *node; | ||
225 | 301 | ||
226 | tbl = rcu_dereference(mesh_paths); | 302 | BUG_ON(gate_mpath == from_mpath); |
303 | BUG_ON(!gate_mpath->next_hop); | ||
227 | 304 | ||
228 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; | 305 | __skb_queue_head_init(&gateq); |
229 | hlist_for_each_entry_rcu(node, n, bucket, list) { | 306 | __skb_queue_head_init(&failq); |
230 | mpath = node->mpath; | 307 | |
231 | if (mpath->sdata == sdata && | 308 | spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); |
232 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { | 309 | skb_queue_splice_init(&from_mpath->frame_queue, &failq); |
233 | if (MPATH_EXPIRED(mpath)) { | 310 | spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); |
234 | spin_lock_bh(&mpath->state_lock); | 311 | |
235 | if (MPATH_EXPIRED(mpath)) | 312 | num_skbs = skb_queue_len(&failq); |
236 | mpath->flags &= ~MESH_PATH_ACTIVE; | 313 | |
237 | spin_unlock_bh(&mpath->state_lock); | 314 | while (num_skbs--) { |
238 | } | 315 | skb = __skb_dequeue(&failq); |
239 | return mpath; | 316 | if (copy) { |
317 | cp_skb = skb_copy(skb, GFP_ATOMIC); | ||
318 | if (cp_skb) | ||
319 | __skb_queue_tail(&failq, cp_skb); | ||
240 | } | 320 | } |
321 | |||
322 | prepare_for_gate(skb, gate_mpath->dst, gate_mpath); | ||
323 | __skb_queue_tail(&gateq, skb); | ||
241 | } | 324 | } |
242 | return NULL; | 325 | |
326 | spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags); | ||
327 | skb_queue_splice(&gateq, &gate_mpath->frame_queue); | ||
328 | mpath_dbg("Mpath queue for gate %pM has %d frames\n", | ||
329 | gate_mpath->dst, | ||
330 | skb_queue_len(&gate_mpath->frame_queue)); | ||
331 | spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags); | ||
332 | |||
333 | if (!copy) | ||
334 | return; | ||
335 | |||
336 | spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); | ||
337 | skb_queue_splice(&failq, &from_mpath->frame_queue); | ||
338 | spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); | ||
243 | } | 339 | } |
244 | 340 | ||
245 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | 341 | |
342 | static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst, | ||
343 | struct ieee80211_sub_if_data *sdata) | ||
246 | { | 344 | { |
247 | struct mesh_path *mpath; | 345 | struct mesh_path *mpath; |
248 | struct hlist_node *n; | 346 | struct hlist_node *n; |
249 | struct hlist_head *bucket; | 347 | struct hlist_head *bucket; |
250 | struct mesh_table *tbl; | ||
251 | struct mpath_node *node; | 348 | struct mpath_node *node; |
252 | 349 | ||
253 | tbl = rcu_dereference(mpp_paths); | ||
254 | |||
255 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; | 350 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; |
256 | hlist_for_each_entry_rcu(node, n, bucket, list) { | 351 | hlist_for_each_entry_rcu(node, n, bucket, list) { |
257 | mpath = node->mpath; | 352 | mpath = node->mpath; |
258 | if (mpath->sdata == sdata && | 353 | if (mpath->sdata == sdata && |
259 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { | 354 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { |
260 | if (MPATH_EXPIRED(mpath)) { | 355 | if (MPATH_EXPIRED(mpath)) { |
261 | spin_lock_bh(&mpath->state_lock); | 356 | spin_lock_bh(&mpath->state_lock); |
262 | if (MPATH_EXPIRED(mpath)) | 357 | mpath->flags &= ~MESH_PATH_ACTIVE; |
263 | mpath->flags &= ~MESH_PATH_ACTIVE; | ||
264 | spin_unlock_bh(&mpath->state_lock); | 358 | spin_unlock_bh(&mpath->state_lock); |
265 | } | 359 | } |
266 | return mpath; | 360 | return mpath; |
@@ -269,6 +363,25 @@ struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
269 | return NULL; | 363 | return NULL; |
270 | } | 364 | } |
271 | 365 | ||
366 | /** | ||
367 | * mesh_path_lookup - look up a path in the mesh path table | ||
368 | * @dst: hardware address (ETH_ALEN length) of destination | ||
369 | * @sdata: local subif | ||
370 | * | ||
371 | * Returns: pointer to the mesh path structure, or NULL if not found | ||
372 | * | ||
373 | * Locking: must be called within a read rcu section. | ||
374 | */ | ||
375 | struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | ||
376 | { | ||
377 | return path_lookup(rcu_dereference(mesh_paths), dst, sdata); | ||
378 | } | ||
379 | |||
380 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | ||
381 | { | ||
382 | return path_lookup(rcu_dereference(mpp_paths), dst, sdata); | ||
383 | } | ||
384 | |||
272 | 385 | ||
273 | /** | 386 | /** |
274 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index | 387 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index |
@@ -293,8 +406,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data | |||
293 | if (j++ == idx) { | 406 | if (j++ == idx) { |
294 | if (MPATH_EXPIRED(node->mpath)) { | 407 | if (MPATH_EXPIRED(node->mpath)) { |
295 | spin_lock_bh(&node->mpath->state_lock); | 408 | spin_lock_bh(&node->mpath->state_lock); |
296 | if (MPATH_EXPIRED(node->mpath)) | 409 | node->mpath->flags &= ~MESH_PATH_ACTIVE; |
297 | node->mpath->flags &= ~MESH_PATH_ACTIVE; | ||
298 | spin_unlock_bh(&node->mpath->state_lock); | 410 | spin_unlock_bh(&node->mpath->state_lock); |
299 | } | 411 | } |
300 | return node->mpath; | 412 | return node->mpath; |
@@ -304,6 +416,109 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data | |||
304 | return NULL; | 416 | return NULL; |
305 | } | 417 | } |
306 | 418 | ||
419 | static void mesh_gate_node_reclaim(struct rcu_head *rp) | ||
420 | { | ||
421 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); | ||
422 | kfree(node); | ||
423 | } | ||
424 | |||
425 | /** | ||
426 | * mesh_gate_add - mark mpath as path to a mesh gate and add to known_gates | ||
427 | * @mesh_tbl: table which contains known_gates list | ||
428 | * @mpath: mpath to known mesh gate | ||
429 | * | ||
430 | * Returns: 0 on success | ||
431 | * | ||
432 | */ | ||
433 | static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath) | ||
434 | { | ||
435 | struct mpath_node *gate, *new_gate; | ||
436 | struct hlist_node *n; | ||
437 | int err; | ||
438 | |||
439 | rcu_read_lock(); | ||
440 | tbl = rcu_dereference(tbl); | ||
441 | |||
442 | hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list) | ||
443 | if (gate->mpath == mpath) { | ||
444 | err = -EEXIST; | ||
445 | goto err_rcu; | ||
446 | } | ||
447 | |||
448 | new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC); | ||
449 | if (!new_gate) { | ||
450 | err = -ENOMEM; | ||
451 | goto err_rcu; | ||
452 | } | ||
453 | |||
454 | mpath->is_gate = true; | ||
455 | mpath->sdata->u.mesh.num_gates++; | ||
456 | new_gate->mpath = mpath; | ||
457 | spin_lock_bh(&tbl->gates_lock); | ||
458 | hlist_add_head_rcu(&new_gate->list, tbl->known_gates); | ||
459 | spin_unlock_bh(&tbl->gates_lock); | ||
460 | rcu_read_unlock(); | ||
461 | mpath_dbg("Mesh path (%s): Recorded new gate: %pM. %d known gates\n", | ||
462 | mpath->sdata->name, mpath->dst, | ||
463 | mpath->sdata->u.mesh.num_gates); | ||
464 | return 0; | ||
465 | err_rcu: | ||
466 | rcu_read_unlock(); | ||
467 | return err; | ||
468 | } | ||
469 | |||
470 | /** | ||
471 | * mesh_gate_del - remove a mesh gate from the list of known gates | ||
472 | * @tbl: table which holds our list of known gates | ||
473 | * @mpath: gate mpath | ||
474 | * | ||
475 | * Returns: 0 on success | ||
476 | * | ||
477 | * Locking: must be called inside rcu_read_lock() section | ||
478 | */ | ||
479 | static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) | ||
480 | { | ||
481 | struct mpath_node *gate; | ||
482 | struct hlist_node *p, *q; | ||
483 | |||
484 | tbl = rcu_dereference(tbl); | ||
485 | |||
486 | hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) | ||
487 | if (gate->mpath == mpath) { | ||
488 | spin_lock_bh(&tbl->gates_lock); | ||
489 | hlist_del_rcu(&gate->list); | ||
490 | call_rcu(&gate->rcu, mesh_gate_node_reclaim); | ||
491 | spin_unlock_bh(&tbl->gates_lock); | ||
492 | mpath->sdata->u.mesh.num_gates--; | ||
493 | mpath->is_gate = false; | ||
494 | mpath_dbg("Mesh path (%s): Deleted gate: %pM. " | ||
495 | "%d known gates\n", mpath->sdata->name, | ||
496 | mpath->dst, mpath->sdata->u.mesh.num_gates); | ||
497 | break; | ||
498 | } | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | /** | ||
504 | * | ||
505 | * mesh_path_add_gate - add the given mpath to a mesh gate to our path table | ||
506 | * @mpath: gate path to add to table | ||
507 | */ | ||
508 | int mesh_path_add_gate(struct mesh_path *mpath) | ||
509 | { | ||
510 | return mesh_gate_add(mesh_paths, mpath); | ||
511 | } | ||
512 | |||
513 | /** | ||
514 | * mesh_gate_num - number of gates known to this interface | ||
515 | * @sdata: subif data | ||
516 | */ | ||
517 | int mesh_gate_num(struct ieee80211_sub_if_data *sdata) | ||
518 | { | ||
519 | return sdata->u.mesh.num_gates; | ||
520 | } | ||
521 | |||
307 | /** | 522 | /** |
308 | * mesh_path_add - allocate and add a new path to the mesh path table | 523 | * mesh_path_add - allocate and add a new path to the mesh path table |
309 | * @addr: destination address of the path (ETH_ALEN length) | 524 | * @addr: destination address of the path (ETH_ALEN length) |
@@ -481,6 +696,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
481 | new_mpath->flags = 0; | 696 | new_mpath->flags = 0; |
482 | skb_queue_head_init(&new_mpath->frame_queue); | 697 | skb_queue_head_init(&new_mpath->frame_queue); |
483 | new_node->mpath = new_mpath; | 698 | new_node->mpath = new_mpath; |
699 | init_timer(&new_mpath->timer); | ||
484 | new_mpath->exp_time = jiffies; | 700 | new_mpath->exp_time = jiffies; |
485 | spin_lock_init(&new_mpath->state_lock); | 701 | spin_lock_init(&new_mpath->state_lock); |
486 | 702 | ||
@@ -539,28 +755,53 @@ void mesh_plink_broken(struct sta_info *sta) | |||
539 | struct hlist_node *p; | 755 | struct hlist_node *p; |
540 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 756 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
541 | int i; | 757 | int i; |
758 | __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE); | ||
542 | 759 | ||
543 | rcu_read_lock(); | 760 | rcu_read_lock(); |
544 | tbl = rcu_dereference(mesh_paths); | 761 | tbl = rcu_dereference(mesh_paths); |
545 | for_each_mesh_entry(tbl, p, node, i) { | 762 | for_each_mesh_entry(tbl, p, node, i) { |
546 | mpath = node->mpath; | 763 | mpath = node->mpath; |
547 | spin_lock_bh(&mpath->state_lock); | ||
548 | if (rcu_dereference(mpath->next_hop) == sta && | 764 | if (rcu_dereference(mpath->next_hop) == sta && |
549 | mpath->flags & MESH_PATH_ACTIVE && | 765 | mpath->flags & MESH_PATH_ACTIVE && |
550 | !(mpath->flags & MESH_PATH_FIXED)) { | 766 | !(mpath->flags & MESH_PATH_FIXED)) { |
767 | spin_lock_bh(&mpath->state_lock); | ||
551 | mpath->flags &= ~MESH_PATH_ACTIVE; | 768 | mpath->flags &= ~MESH_PATH_ACTIVE; |
552 | ++mpath->sn; | 769 | ++mpath->sn; |
553 | spin_unlock_bh(&mpath->state_lock); | 770 | spin_unlock_bh(&mpath->state_lock); |
554 | mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, | 771 | mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, |
555 | mpath->dst, cpu_to_le32(mpath->sn), | 772 | mpath->dst, cpu_to_le32(mpath->sn), |
556 | cpu_to_le16(PERR_RCODE_DEST_UNREACH), | 773 | reason, bcast, sdata); |
557 | bcast, sdata); | 774 | } |
558 | } else | ||
559 | spin_unlock_bh(&mpath->state_lock); | ||
560 | } | 775 | } |
561 | rcu_read_unlock(); | 776 | rcu_read_unlock(); |
562 | } | 777 | } |
563 | 778 | ||
779 | static void mesh_path_node_reclaim(struct rcu_head *rp) | ||
780 | { | ||
781 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); | ||
782 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; | ||
783 | |||
784 | del_timer_sync(&node->mpath->timer); | ||
785 | atomic_dec(&sdata->u.mesh.mpaths); | ||
786 | kfree(node->mpath); | ||
787 | kfree(node); | ||
788 | } | ||
789 | |||
790 | /* needs to be called with the corresponding hashwlock taken */ | ||
791 | static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) | ||
792 | { | ||
793 | struct mesh_path *mpath; | ||
794 | mpath = node->mpath; | ||
795 | spin_lock(&mpath->state_lock); | ||
796 | mpath->flags |= MESH_PATH_RESOLVING; | ||
797 | if (mpath->is_gate) | ||
798 | mesh_gate_del(tbl, mpath); | ||
799 | hlist_del_rcu(&node->list); | ||
800 | call_rcu(&node->rcu, mesh_path_node_reclaim); | ||
801 | spin_unlock(&mpath->state_lock); | ||
802 | atomic_dec(&tbl->entries); | ||
803 | } | ||
804 | |||
564 | /** | 805 | /** |
565 | * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches | 806 | * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches |
566 | * | 807 | * |
@@ -581,42 +822,59 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) | |||
581 | int i; | 822 | int i; |
582 | 823 | ||
583 | rcu_read_lock(); | 824 | rcu_read_lock(); |
584 | tbl = rcu_dereference(mesh_paths); | 825 | read_lock_bh(&pathtbl_resize_lock); |
826 | tbl = resize_dereference_mesh_paths(); | ||
585 | for_each_mesh_entry(tbl, p, node, i) { | 827 | for_each_mesh_entry(tbl, p, node, i) { |
586 | mpath = node->mpath; | 828 | mpath = node->mpath; |
587 | if (rcu_dereference(mpath->next_hop) == sta) | 829 | if (rcu_dereference(mpath->next_hop) == sta) { |
588 | mesh_path_del(mpath->dst, mpath->sdata); | 830 | spin_lock_bh(&tbl->hashwlock[i]); |
831 | __mesh_path_del(tbl, node); | ||
832 | spin_unlock_bh(&tbl->hashwlock[i]); | ||
833 | } | ||
589 | } | 834 | } |
835 | read_unlock_bh(&pathtbl_resize_lock); | ||
590 | rcu_read_unlock(); | 836 | rcu_read_unlock(); |
591 | } | 837 | } |
592 | 838 | ||
593 | void mesh_path_flush(struct ieee80211_sub_if_data *sdata) | 839 | static void table_flush_by_iface(struct mesh_table *tbl, |
840 | struct ieee80211_sub_if_data *sdata) | ||
594 | { | 841 | { |
595 | struct mesh_table *tbl; | ||
596 | struct mesh_path *mpath; | 842 | struct mesh_path *mpath; |
597 | struct mpath_node *node; | 843 | struct mpath_node *node; |
598 | struct hlist_node *p; | 844 | struct hlist_node *p; |
599 | int i; | 845 | int i; |
600 | 846 | ||
601 | rcu_read_lock(); | 847 | WARN_ON(!rcu_read_lock_held()); |
602 | tbl = rcu_dereference(mesh_paths); | ||
603 | for_each_mesh_entry(tbl, p, node, i) { | 848 | for_each_mesh_entry(tbl, p, node, i) { |
604 | mpath = node->mpath; | 849 | mpath = node->mpath; |
605 | if (mpath->sdata == sdata) | 850 | if (mpath->sdata != sdata) |
606 | mesh_path_del(mpath->dst, mpath->sdata); | 851 | continue; |
852 | spin_lock_bh(&tbl->hashwlock[i]); | ||
853 | __mesh_path_del(tbl, node); | ||
854 | spin_unlock_bh(&tbl->hashwlock[i]); | ||
607 | } | 855 | } |
608 | rcu_read_unlock(); | ||
609 | } | 856 | } |
610 | 857 | ||
611 | static void mesh_path_node_reclaim(struct rcu_head *rp) | 858 | /** |
859 | * mesh_path_flush_by_iface - Deletes all mesh paths associated with a given iface | ||
860 | * | ||
861 | * This function deletes both mesh paths as well as mesh portal paths. | ||
862 | * | ||
863 | * @sdata - interface data to match | ||
864 | * | ||
865 | */ | ||
866 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) | ||
612 | { | 867 | { |
613 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); | 868 | struct mesh_table *tbl; |
614 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; | ||
615 | 869 | ||
616 | del_timer_sync(&node->mpath->timer); | 870 | rcu_read_lock(); |
617 | atomic_dec(&sdata->u.mesh.mpaths); | 871 | read_lock_bh(&pathtbl_resize_lock); |
618 | kfree(node->mpath); | 872 | tbl = resize_dereference_mesh_paths(); |
619 | kfree(node); | 873 | table_flush_by_iface(tbl, sdata); |
874 | tbl = resize_dereference_mpp_paths(); | ||
875 | table_flush_by_iface(tbl, sdata); | ||
876 | read_unlock_bh(&pathtbl_resize_lock); | ||
877 | rcu_read_unlock(); | ||
620 | } | 878 | } |
621 | 879 | ||
622 | /** | 880 | /** |
@@ -647,12 +905,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) | |||
647 | mpath = node->mpath; | 905 | mpath = node->mpath; |
648 | if (mpath->sdata == sdata && | 906 | if (mpath->sdata == sdata && |
649 | memcmp(addr, mpath->dst, ETH_ALEN) == 0) { | 907 | memcmp(addr, mpath->dst, ETH_ALEN) == 0) { |
650 | spin_lock(&mpath->state_lock); | 908 | __mesh_path_del(tbl, node); |
651 | mpath->flags |= MESH_PATH_RESOLVING; | ||
652 | hlist_del_rcu(&node->list); | ||
653 | call_rcu(&node->rcu, mesh_path_node_reclaim); | ||
654 | atomic_dec(&tbl->entries); | ||
655 | spin_unlock(&mpath->state_lock); | ||
656 | goto enddel; | 909 | goto enddel; |
657 | } | 910 | } |
658 | } | 911 | } |
@@ -681,6 +934,58 @@ void mesh_path_tx_pending(struct mesh_path *mpath) | |||
681 | } | 934 | } |
682 | 935 | ||
683 | /** | 936 | /** |
937 | * mesh_path_send_to_gates - sends pending frames to all known mesh gates | ||
938 | * | ||
939 | * @mpath: mesh path whose queue will be emptied | ||
940 | * | ||
941 | * If there is only one gate, the frames are transferred from the failed mpath | ||
942 | * queue to that gate's queue. If there are more than one gates, the frames | ||
943 | * are copied from each gate to the next. After frames are copied, the | ||
944 | * mpath queues are emptied onto the transmission queue. | ||
945 | */ | ||
946 | int mesh_path_send_to_gates(struct mesh_path *mpath) | ||
947 | { | ||
948 | struct ieee80211_sub_if_data *sdata = mpath->sdata; | ||
949 | struct hlist_node *n; | ||
950 | struct mesh_table *tbl; | ||
951 | struct mesh_path *from_mpath = mpath; | ||
952 | struct mpath_node *gate = NULL; | ||
953 | bool copy = false; | ||
954 | struct hlist_head *known_gates; | ||
955 | |||
956 | rcu_read_lock(); | ||
957 | tbl = rcu_dereference(mesh_paths); | ||
958 | known_gates = tbl->known_gates; | ||
959 | rcu_read_unlock(); | ||
960 | |||
961 | if (!known_gates) | ||
962 | return -EHOSTUNREACH; | ||
963 | |||
964 | hlist_for_each_entry_rcu(gate, n, known_gates, list) { | ||
965 | if (gate->mpath->sdata != sdata) | ||
966 | continue; | ||
967 | |||
968 | if (gate->mpath->flags & MESH_PATH_ACTIVE) { | ||
969 | mpath_dbg("Forwarding to %pM\n", gate->mpath->dst); | ||
970 | mesh_path_move_to_queue(gate->mpath, from_mpath, copy); | ||
971 | from_mpath = gate->mpath; | ||
972 | copy = true; | ||
973 | } else { | ||
974 | mpath_dbg("Not forwarding %p\n", gate->mpath); | ||
975 | mpath_dbg("flags %x\n", gate->mpath->flags); | ||
976 | } | ||
977 | } | ||
978 | |||
979 | hlist_for_each_entry_rcu(gate, n, known_gates, list) | ||
980 | if (gate->mpath->sdata == sdata) { | ||
981 | mpath_dbg("Sending to %pM\n", gate->mpath->dst); | ||
982 | mesh_path_tx_pending(gate->mpath); | ||
983 | } | ||
984 | |||
985 | return (from_mpath == mpath) ? -EHOSTUNREACH : 0; | ||
986 | } | ||
987 | |||
988 | /** | ||
684 | * mesh_path_discard_frame - discard a frame whose path could not be resolved | 989 | * mesh_path_discard_frame - discard a frame whose path could not be resolved |
685 | * | 990 | * |
686 | * @skb: frame to discard | 991 | * @skb: frame to discard |
@@ -699,18 +1004,23 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
699 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1004 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
700 | struct mesh_path *mpath; | 1005 | struct mesh_path *mpath; |
701 | u32 sn = 0; | 1006 | u32 sn = 0; |
1007 | __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); | ||
702 | 1008 | ||
703 | if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { | 1009 | if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { |
704 | u8 *ra, *da; | 1010 | u8 *ra, *da; |
705 | 1011 | ||
706 | da = hdr->addr3; | 1012 | da = hdr->addr3; |
707 | ra = hdr->addr1; | 1013 | ra = hdr->addr1; |
1014 | rcu_read_lock(); | ||
708 | mpath = mesh_path_lookup(da, sdata); | 1015 | mpath = mesh_path_lookup(da, sdata); |
709 | if (mpath) | 1016 | if (mpath) { |
1017 | spin_lock_bh(&mpath->state_lock); | ||
710 | sn = ++mpath->sn; | 1018 | sn = ++mpath->sn; |
1019 | spin_unlock_bh(&mpath->state_lock); | ||
1020 | } | ||
1021 | rcu_read_unlock(); | ||
711 | mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data, | 1022 | mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data, |
712 | cpu_to_le32(sn), | 1023 | cpu_to_le32(sn), reason, ra, sdata); |
713 | cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata); | ||
714 | } | 1024 | } |
715 | 1025 | ||
716 | kfree_skb(skb); | 1026 | kfree_skb(skb); |
@@ -728,8 +1038,7 @@ void mesh_path_flush_pending(struct mesh_path *mpath) | |||
728 | { | 1038 | { |
729 | struct sk_buff *skb; | 1039 | struct sk_buff *skb; |
730 | 1040 | ||
731 | while ((skb = skb_dequeue(&mpath->frame_queue)) && | 1041 | while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL) |
732 | (mpath->flags & MESH_PATH_ACTIVE)) | ||
733 | mesh_path_discard_frame(skb, mpath->sdata); | 1042 | mesh_path_discard_frame(skb, mpath->sdata); |
734 | } | 1043 | } |
735 | 1044 | ||
@@ -790,6 +1099,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | |||
790 | int mesh_pathtbl_init(void) | 1099 | int mesh_pathtbl_init(void) |
791 | { | 1100 | { |
792 | struct mesh_table *tbl_path, *tbl_mpp; | 1101 | struct mesh_table *tbl_path, *tbl_mpp; |
1102 | int ret; | ||
793 | 1103 | ||
794 | tbl_path = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | 1104 | tbl_path = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); |
795 | if (!tbl_path) | 1105 | if (!tbl_path) |
@@ -797,21 +1107,40 @@ int mesh_pathtbl_init(void) | |||
797 | tbl_path->free_node = &mesh_path_node_free; | 1107 | tbl_path->free_node = &mesh_path_node_free; |
798 | tbl_path->copy_node = &mesh_path_node_copy; | 1108 | tbl_path->copy_node = &mesh_path_node_copy; |
799 | tbl_path->mean_chain_len = MEAN_CHAIN_LEN; | 1109 | tbl_path->mean_chain_len = MEAN_CHAIN_LEN; |
1110 | tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); | ||
1111 | if (!tbl_path->known_gates) { | ||
1112 | ret = -ENOMEM; | ||
1113 | goto free_path; | ||
1114 | } | ||
1115 | INIT_HLIST_HEAD(tbl_path->known_gates); | ||
1116 | |||
800 | 1117 | ||
801 | tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | 1118 | tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); |
802 | if (!tbl_mpp) { | 1119 | if (!tbl_mpp) { |
803 | mesh_table_free(tbl_path, true); | 1120 | ret = -ENOMEM; |
804 | return -ENOMEM; | 1121 | goto free_path; |
805 | } | 1122 | } |
806 | tbl_mpp->free_node = &mesh_path_node_free; | 1123 | tbl_mpp->free_node = &mesh_path_node_free; |
807 | tbl_mpp->copy_node = &mesh_path_node_copy; | 1124 | tbl_mpp->copy_node = &mesh_path_node_copy; |
808 | tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN; | 1125 | tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN; |
1126 | tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); | ||
1127 | if (!tbl_mpp->known_gates) { | ||
1128 | ret = -ENOMEM; | ||
1129 | goto free_mpp; | ||
1130 | } | ||
1131 | INIT_HLIST_HEAD(tbl_mpp->known_gates); | ||
809 | 1132 | ||
810 | /* Need no locking since this is during init */ | 1133 | /* Need no locking since this is during init */ |
811 | RCU_INIT_POINTER(mesh_paths, tbl_path); | 1134 | RCU_INIT_POINTER(mesh_paths, tbl_path); |
812 | RCU_INIT_POINTER(mpp_paths, tbl_mpp); | 1135 | RCU_INIT_POINTER(mpp_paths, tbl_mpp); |
813 | 1136 | ||
814 | return 0; | 1137 | return 0; |
1138 | |||
1139 | free_mpp: | ||
1140 | mesh_table_free(tbl_mpp, true); | ||
1141 | free_path: | ||
1142 | mesh_table_free(tbl_path, true); | ||
1143 | return ret; | ||
815 | } | 1144 | } |
816 | 1145 | ||
817 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | 1146 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata) |
@@ -828,14 +1157,10 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | |||
828 | if (node->mpath->sdata != sdata) | 1157 | if (node->mpath->sdata != sdata) |
829 | continue; | 1158 | continue; |
830 | mpath = node->mpath; | 1159 | mpath = node->mpath; |
831 | spin_lock_bh(&mpath->state_lock); | ||
832 | if ((!(mpath->flags & MESH_PATH_RESOLVING)) && | 1160 | if ((!(mpath->flags & MESH_PATH_RESOLVING)) && |
833 | (!(mpath->flags & MESH_PATH_FIXED)) && | 1161 | (!(mpath->flags & MESH_PATH_FIXED)) && |
834 | time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) { | 1162 | time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) |
835 | spin_unlock_bh(&mpath->state_lock); | ||
836 | mesh_path_del(mpath->dst, mpath->sdata); | 1163 | mesh_path_del(mpath->dst, mpath->sdata); |
837 | } else | ||
838 | spin_unlock_bh(&mpath->state_lock); | ||
839 | } | 1164 | } |
840 | rcu_read_unlock(); | 1165 | rcu_read_unlock(); |
841 | } | 1166 | } |
@@ -843,6 +1168,6 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | |||
843 | void mesh_pathtbl_unregister(void) | 1168 | void mesh_pathtbl_unregister(void) |
844 | { | 1169 | { |
845 | /* no need for locking during exit path */ | 1170 | /* no need for locking during exit path */ |
846 | mesh_table_free(rcu_dereference_raw(mesh_paths), true); | 1171 | mesh_table_free(rcu_dereference_protected(mesh_paths, 1), true); |
847 | mesh_table_free(rcu_dereference_raw(mpp_paths), true); | 1172 | mesh_table_free(rcu_dereference_protected(mpp_paths, 1), true); |
848 | } | 1173 | } |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index f4adc0917888..7e57f5d07f66 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -19,35 +19,18 @@ | |||
19 | #define mpl_dbg(fmt, args...) do { (void)(0); } while (0) | 19 | #define mpl_dbg(fmt, args...) do { (void)(0); } while (0) |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #define PLINK_GET_LLID(p) (p + 4) | 22 | #define PLINK_GET_LLID(p) (p + 2) |
23 | #define PLINK_GET_PLID(p) (p + 6) | 23 | #define PLINK_GET_PLID(p) (p + 4) |
24 | 24 | ||
25 | #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ | 25 | #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ |
26 | jiffies + HZ * t / 1000)) | 26 | jiffies + HZ * t / 1000)) |
27 | 27 | ||
28 | /* Peer link cancel reasons, all subject to ANA approval */ | ||
29 | #define MESH_LINK_CANCELLED 2 | ||
30 | #define MESH_MAX_NEIGHBORS 3 | ||
31 | #define MESH_CAPABILITY_POLICY_VIOLATION 4 | ||
32 | #define MESH_CLOSE_RCVD 5 | ||
33 | #define MESH_MAX_RETRIES 6 | ||
34 | #define MESH_CONFIRM_TIMEOUT 7 | ||
35 | #define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS 8 | ||
36 | #define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 | ||
37 | #define MESH_SECURITY_FAILED_VERIFICATION 10 | ||
38 | |||
39 | #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) | 28 | #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) |
40 | #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) | 29 | #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) |
41 | #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) | 30 | #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) |
42 | #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) | 31 | #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) |
43 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) | 32 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) |
44 | 33 | ||
45 | enum plink_frame_type { | ||
46 | PLINK_OPEN = 1, | ||
47 | PLINK_CONFIRM, | ||
48 | PLINK_CLOSE | ||
49 | }; | ||
50 | |||
51 | enum plink_event { | 34 | enum plink_event { |
52 | PLINK_UNDEFINED, | 35 | PLINK_UNDEFINED, |
53 | OPN_ACPT, | 36 | OPN_ACPT, |
@@ -60,6 +43,10 @@ enum plink_event { | |||
60 | CLS_IGNR | 43 | CLS_IGNR |
61 | }; | 44 | }; |
62 | 45 | ||
46 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | ||
47 | enum ieee80211_self_protected_actioncode action, | ||
48 | u8 *da, __le16 llid, __le16 plid, __le16 reason); | ||
49 | |||
63 | static inline | 50 | static inline |
64 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | 51 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) |
65 | { | 52 | { |
@@ -105,7 +92,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
105 | if (!sta) | 92 | if (!sta) |
106 | return NULL; | 93 | return NULL; |
107 | 94 | ||
108 | sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH; | 95 | set_sta_flag(sta, WLAN_STA_AUTH); |
96 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); | ||
97 | set_sta_flag(sta, WLAN_STA_WME); | ||
109 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 98 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
110 | rate_control_rate_init(sta); | 99 | rate_control_rate_init(sta); |
111 | 100 | ||
@@ -150,6 +139,10 @@ void mesh_plink_deactivate(struct sta_info *sta) | |||
150 | 139 | ||
151 | spin_lock_bh(&sta->lock); | 140 | spin_lock_bh(&sta->lock); |
152 | deactivated = __mesh_plink_deactivate(sta); | 141 | deactivated = __mesh_plink_deactivate(sta); |
142 | sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); | ||
143 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | ||
144 | sta->sta.addr, sta->llid, sta->plid, | ||
145 | sta->reason); | ||
153 | spin_unlock_bh(&sta->lock); | 146 | spin_unlock_bh(&sta->lock); |
154 | 147 | ||
155 | if (deactivated) | 148 | if (deactivated) |
@@ -157,16 +150,16 @@ void mesh_plink_deactivate(struct sta_info *sta) | |||
157 | } | 150 | } |
158 | 151 | ||
159 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 152 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
160 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, | 153 | enum ieee80211_self_protected_actioncode action, |
161 | __le16 reason) { | 154 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { |
162 | struct ieee80211_local *local = sdata->local; | 155 | struct ieee80211_local *local = sdata->local; |
163 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + | 156 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + |
164 | sdata->u.mesh.ie_len); | 157 | sdata->u.mesh.ie_len); |
165 | struct ieee80211_mgmt *mgmt; | 158 | struct ieee80211_mgmt *mgmt; |
166 | bool include_plid = false; | 159 | bool include_plid = false; |
167 | static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; | 160 | int ie_len = 4; |
161 | u16 peering_proto = 0; | ||
168 | u8 *pos; | 162 | u8 *pos; |
169 | int ie_len; | ||
170 | 163 | ||
171 | if (!skb) | 164 | if (!skb) |
172 | return -1; | 165 | return -1; |
@@ -175,63 +168,75 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
175 | * common action part (1) | 168 | * common action part (1) |
176 | */ | 169 | */ |
177 | mgmt = (struct ieee80211_mgmt *) | 170 | mgmt = (struct ieee80211_mgmt *) |
178 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); | 171 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot)); |
179 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); | 172 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot)); |
180 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 173 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
181 | IEEE80211_STYPE_ACTION); | 174 | IEEE80211_STYPE_ACTION); |
182 | memcpy(mgmt->da, da, ETH_ALEN); | 175 | memcpy(mgmt->da, da, ETH_ALEN); |
183 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 176 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
184 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 177 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
185 | mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; | 178 | mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED; |
186 | mgmt->u.action.u.plink_action.action_code = action; | 179 | mgmt->u.action.u.self_prot.action_code = action; |
187 | 180 | ||
188 | if (action == PLINK_CLOSE) | 181 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { |
189 | mgmt->u.action.u.plink_action.aux = reason; | 182 | /* capability info */ |
190 | else { | 183 | pos = skb_put(skb, 2); |
191 | mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0); | 184 | memset(pos, 0, 2); |
192 | if (action == PLINK_CONFIRM) { | 185 | if (action == WLAN_SP_MESH_PEERING_CONFIRM) { |
193 | pos = skb_put(skb, 4); | 186 | /* AID */ |
194 | /* two-byte status code followed by two-byte AID */ | 187 | pos = skb_put(skb, 2); |
195 | memset(pos, 0, 2); | ||
196 | memcpy(pos + 2, &plid, 2); | 188 | memcpy(pos + 2, &plid, 2); |
197 | } | 189 | } |
198 | mesh_mgmt_ies_add(skb, sdata); | 190 | if (ieee80211_add_srates_ie(&sdata->vif, skb) || |
191 | ieee80211_add_ext_srates_ie(&sdata->vif, skb) || | ||
192 | mesh_add_rsn_ie(skb, sdata) || | ||
193 | mesh_add_meshid_ie(skb, sdata) || | ||
194 | mesh_add_meshconf_ie(skb, sdata)) | ||
195 | return -1; | ||
196 | } else { /* WLAN_SP_MESH_PEERING_CLOSE */ | ||
197 | if (mesh_add_meshid_ie(skb, sdata)) | ||
198 | return -1; | ||
199 | } | 199 | } |
200 | 200 | ||
201 | /* Add Peer Link Management element */ | 201 | /* Add Mesh Peering Management element */ |
202 | switch (action) { | 202 | switch (action) { |
203 | case PLINK_OPEN: | 203 | case WLAN_SP_MESH_PEERING_OPEN: |
204 | ie_len = 6; | ||
205 | break; | 204 | break; |
206 | case PLINK_CONFIRM: | 205 | case WLAN_SP_MESH_PEERING_CONFIRM: |
207 | ie_len = 8; | 206 | ie_len += 2; |
208 | include_plid = true; | 207 | include_plid = true; |
209 | break; | 208 | break; |
210 | case PLINK_CLOSE: | 209 | case WLAN_SP_MESH_PEERING_CLOSE: |
211 | default: | 210 | if (plid) { |
212 | if (!plid) | 211 | ie_len += 2; |
213 | ie_len = 8; | ||
214 | else { | ||
215 | ie_len = 10; | ||
216 | include_plid = true; | 212 | include_plid = true; |
217 | } | 213 | } |
214 | ie_len += 2; /* reason code */ | ||
218 | break; | 215 | break; |
216 | default: | ||
217 | return -EINVAL; | ||
219 | } | 218 | } |
220 | 219 | ||
220 | if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) | ||
221 | return -ENOMEM; | ||
222 | |||
221 | pos = skb_put(skb, 2 + ie_len); | 223 | pos = skb_put(skb, 2 + ie_len); |
222 | *pos++ = WLAN_EID_PEER_LINK; | 224 | *pos++ = WLAN_EID_PEER_MGMT; |
223 | *pos++ = ie_len; | 225 | *pos++ = ie_len; |
224 | memcpy(pos, meshpeeringproto, sizeof(meshpeeringproto)); | 226 | memcpy(pos, &peering_proto, 2); |
225 | pos += 4; | 227 | pos += 2; |
226 | memcpy(pos, &llid, 2); | 228 | memcpy(pos, &llid, 2); |
229 | pos += 2; | ||
227 | if (include_plid) { | 230 | if (include_plid) { |
228 | pos += 2; | ||
229 | memcpy(pos, &plid, 2); | 231 | memcpy(pos, &plid, 2); |
230 | } | ||
231 | if (action == PLINK_CLOSE) { | ||
232 | pos += 2; | 232 | pos += 2; |
233 | } | ||
234 | if (action == WLAN_SP_MESH_PEERING_CLOSE) { | ||
233 | memcpy(pos, &reason, 2); | 235 | memcpy(pos, &reason, 2); |
236 | pos += 2; | ||
234 | } | 237 | } |
238 | if (mesh_add_vendor_ies(skb, sdata)) | ||
239 | return -1; | ||
235 | 240 | ||
236 | ieee80211_tx_skb(sdata, skb); | 241 | ieee80211_tx_skb(sdata, skb); |
237 | return 0; | 242 | return 0; |
@@ -322,21 +327,21 @@ static void mesh_plink_timer(unsigned long data) | |||
322 | ++sta->plink_retries; | 327 | ++sta->plink_retries; |
323 | mod_plink_timer(sta, sta->plink_timeout); | 328 | mod_plink_timer(sta, sta->plink_timeout); |
324 | spin_unlock_bh(&sta->lock); | 329 | spin_unlock_bh(&sta->lock); |
325 | mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, | 330 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, |
326 | 0, 0); | 331 | sta->sta.addr, llid, 0, 0); |
327 | break; | 332 | break; |
328 | } | 333 | } |
329 | reason = cpu_to_le16(MESH_MAX_RETRIES); | 334 | reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES); |
330 | /* fall through on else */ | 335 | /* fall through on else */ |
331 | case NL80211_PLINK_CNF_RCVD: | 336 | case NL80211_PLINK_CNF_RCVD: |
332 | /* confirm timer */ | 337 | /* confirm timer */ |
333 | if (!reason) | 338 | if (!reason) |
334 | reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); | 339 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); |
335 | sta->plink_state = NL80211_PLINK_HOLDING; | 340 | sta->plink_state = NL80211_PLINK_HOLDING; |
336 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 341 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
337 | spin_unlock_bh(&sta->lock); | 342 | spin_unlock_bh(&sta->lock); |
338 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, | 343 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
339 | reason); | 344 | sta->sta.addr, llid, plid, reason); |
340 | break; | 345 | break; |
341 | case NL80211_PLINK_HOLDING: | 346 | case NL80211_PLINK_HOLDING: |
342 | /* holding timer */ | 347 | /* holding timer */ |
@@ -380,7 +385,7 @@ int mesh_plink_open(struct sta_info *sta) | |||
380 | __le16 llid; | 385 | __le16 llid; |
381 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 386 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
382 | 387 | ||
383 | if (!test_sta_flags(sta, WLAN_STA_AUTH)) | 388 | if (!test_sta_flag(sta, WLAN_STA_AUTH)) |
384 | return -EPERM; | 389 | return -EPERM; |
385 | 390 | ||
386 | spin_lock_bh(&sta->lock); | 391 | spin_lock_bh(&sta->lock); |
@@ -396,7 +401,7 @@ int mesh_plink_open(struct sta_info *sta) | |||
396 | mpl_dbg("Mesh plink: starting establishment with %pM\n", | 401 | mpl_dbg("Mesh plink: starting establishment with %pM\n", |
397 | sta->sta.addr); | 402 | sta->sta.addr); |
398 | 403 | ||
399 | return mesh_plink_frame_tx(sdata, PLINK_OPEN, | 404 | return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, |
400 | sta->sta.addr, llid, 0, 0); | 405 | sta->sta.addr, llid, 0, 0); |
401 | } | 406 | } |
402 | 407 | ||
@@ -422,7 +427,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
422 | struct ieee802_11_elems elems; | 427 | struct ieee802_11_elems elems; |
423 | struct sta_info *sta; | 428 | struct sta_info *sta; |
424 | enum plink_event event; | 429 | enum plink_event event; |
425 | enum plink_frame_type ftype; | 430 | enum ieee80211_self_protected_actioncode ftype; |
426 | size_t baselen; | 431 | size_t baselen; |
427 | bool deactivated, matches_local = true; | 432 | bool deactivated, matches_local = true; |
428 | u8 ie_len; | 433 | u8 ie_len; |
@@ -449,14 +454,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
449 | return; | 454 | return; |
450 | } | 455 | } |
451 | 456 | ||
452 | baseaddr = mgmt->u.action.u.plink_action.variable; | 457 | baseaddr = mgmt->u.action.u.self_prot.variable; |
453 | baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt; | 458 | baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt; |
454 | if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) { | 459 | if (mgmt->u.action.u.self_prot.action_code == |
460 | WLAN_SP_MESH_PEERING_CONFIRM) { | ||
455 | baseaddr += 4; | 461 | baseaddr += 4; |
456 | baselen += 4; | 462 | baselen += 4; |
457 | } | 463 | } |
458 | ieee802_11_parse_elems(baseaddr, len - baselen, &elems); | 464 | ieee802_11_parse_elems(baseaddr, len - baselen, &elems); |
459 | if (!elems.peer_link) { | 465 | if (!elems.peering) { |
460 | mpl_dbg("Mesh plink: missing necessary peer link ie\n"); | 466 | mpl_dbg("Mesh plink: missing necessary peer link ie\n"); |
461 | return; | 467 | return; |
462 | } | 468 | } |
@@ -466,37 +472,40 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
466 | return; | 472 | return; |
467 | } | 473 | } |
468 | 474 | ||
469 | ftype = mgmt->u.action.u.plink_action.action_code; | 475 | ftype = mgmt->u.action.u.self_prot.action_code; |
470 | ie_len = elems.peer_link_len; | 476 | ie_len = elems.peering_len; |
471 | if ((ftype == PLINK_OPEN && ie_len != 6) || | 477 | if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || |
472 | (ftype == PLINK_CONFIRM && ie_len != 8) || | 478 | (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || |
473 | (ftype == PLINK_CLOSE && ie_len != 8 && ie_len != 10)) { | 479 | (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 |
480 | && ie_len != 8)) { | ||
474 | mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n", | 481 | mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n", |
475 | ftype, ie_len); | 482 | ftype, ie_len); |
476 | return; | 483 | return; |
477 | } | 484 | } |
478 | 485 | ||
479 | if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) { | 486 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && |
487 | (!elems.mesh_id || !elems.mesh_config)) { | ||
480 | mpl_dbg("Mesh plink: missing necessary ie\n"); | 488 | mpl_dbg("Mesh plink: missing necessary ie\n"); |
481 | return; | 489 | return; |
482 | } | 490 | } |
483 | /* Note the lines below are correct, the llid in the frame is the plid | 491 | /* Note the lines below are correct, the llid in the frame is the plid |
484 | * from the point of view of this host. | 492 | * from the point of view of this host. |
485 | */ | 493 | */ |
486 | memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2); | 494 | memcpy(&plid, PLINK_GET_LLID(elems.peering), 2); |
487 | if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 10)) | 495 | if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || |
488 | memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2); | 496 | (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) |
497 | memcpy(&llid, PLINK_GET_PLID(elems.peering), 2); | ||
489 | 498 | ||
490 | rcu_read_lock(); | 499 | rcu_read_lock(); |
491 | 500 | ||
492 | sta = sta_info_get(sdata, mgmt->sa); | 501 | sta = sta_info_get(sdata, mgmt->sa); |
493 | if (!sta && ftype != PLINK_OPEN) { | 502 | if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) { |
494 | mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); | 503 | mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); |
495 | rcu_read_unlock(); | 504 | rcu_read_unlock(); |
496 | return; | 505 | return; |
497 | } | 506 | } |
498 | 507 | ||
499 | if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) { | 508 | if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) { |
500 | mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); | 509 | mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); |
501 | rcu_read_unlock(); | 510 | rcu_read_unlock(); |
502 | return; | 511 | return; |
@@ -509,30 +518,30 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
509 | 518 | ||
510 | /* Now we will figure out the appropriate event... */ | 519 | /* Now we will figure out the appropriate event... */ |
511 | event = PLINK_UNDEFINED; | 520 | event = PLINK_UNDEFINED; |
512 | if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { | 521 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && |
522 | (!mesh_matches_local(&elems, sdata))) { | ||
513 | matches_local = false; | 523 | matches_local = false; |
514 | switch (ftype) { | 524 | switch (ftype) { |
515 | case PLINK_OPEN: | 525 | case WLAN_SP_MESH_PEERING_OPEN: |
516 | event = OPN_RJCT; | 526 | event = OPN_RJCT; |
517 | break; | 527 | break; |
518 | case PLINK_CONFIRM: | 528 | case WLAN_SP_MESH_PEERING_CONFIRM: |
519 | event = CNF_RJCT; | 529 | event = CNF_RJCT; |
520 | break; | 530 | break; |
521 | case PLINK_CLOSE: | 531 | default: |
522 | /* avoid warning */ | ||
523 | break; | 532 | break; |
524 | } | 533 | } |
525 | } | 534 | } |
526 | 535 | ||
527 | if (!sta && !matches_local) { | 536 | if (!sta && !matches_local) { |
528 | rcu_read_unlock(); | 537 | rcu_read_unlock(); |
529 | reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); | 538 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); |
530 | llid = 0; | 539 | llid = 0; |
531 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid, | 540 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
532 | plid, reason); | 541 | mgmt->sa, llid, plid, reason); |
533 | return; | 542 | return; |
534 | } else if (!sta) { | 543 | } else if (!sta) { |
535 | /* ftype == PLINK_OPEN */ | 544 | /* ftype == WLAN_SP_MESH_PEERING_OPEN */ |
536 | u32 rates; | 545 | u32 rates; |
537 | 546 | ||
538 | rcu_read_unlock(); | 547 | rcu_read_unlock(); |
@@ -557,21 +566,21 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
557 | } else if (matches_local) { | 566 | } else if (matches_local) { |
558 | spin_lock_bh(&sta->lock); | 567 | spin_lock_bh(&sta->lock); |
559 | switch (ftype) { | 568 | switch (ftype) { |
560 | case PLINK_OPEN: | 569 | case WLAN_SP_MESH_PEERING_OPEN: |
561 | if (!mesh_plink_free_count(sdata) || | 570 | if (!mesh_plink_free_count(sdata) || |
562 | (sta->plid && sta->plid != plid)) | 571 | (sta->plid && sta->plid != plid)) |
563 | event = OPN_IGNR; | 572 | event = OPN_IGNR; |
564 | else | 573 | else |
565 | event = OPN_ACPT; | 574 | event = OPN_ACPT; |
566 | break; | 575 | break; |
567 | case PLINK_CONFIRM: | 576 | case WLAN_SP_MESH_PEERING_CONFIRM: |
568 | if (!mesh_plink_free_count(sdata) || | 577 | if (!mesh_plink_free_count(sdata) || |
569 | (sta->llid != llid || sta->plid != plid)) | 578 | (sta->llid != llid || sta->plid != plid)) |
570 | event = CNF_IGNR; | 579 | event = CNF_IGNR; |
571 | else | 580 | else |
572 | event = CNF_ACPT; | 581 | event = CNF_ACPT; |
573 | break; | 582 | break; |
574 | case PLINK_CLOSE: | 583 | case WLAN_SP_MESH_PEERING_CLOSE: |
575 | if (sta->plink_state == NL80211_PLINK_ESTAB) | 584 | if (sta->plink_state == NL80211_PLINK_ESTAB) |
576 | /* Do not check for llid or plid. This does not | 585 | /* Do not check for llid or plid. This does not |
577 | * follow the standard but since multiple plinks | 586 | * follow the standard but since multiple plinks |
@@ -620,10 +629,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
620 | sta->llid = llid; | 629 | sta->llid = llid; |
621 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 630 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
622 | spin_unlock_bh(&sta->lock); | 631 | spin_unlock_bh(&sta->lock); |
623 | mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, | 632 | mesh_plink_frame_tx(sdata, |
624 | 0, 0); | 633 | WLAN_SP_MESH_PEERING_OPEN, |
625 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, | 634 | sta->sta.addr, llid, 0, 0); |
626 | llid, plid, 0); | 635 | mesh_plink_frame_tx(sdata, |
636 | WLAN_SP_MESH_PEERING_CONFIRM, | ||
637 | sta->sta.addr, llid, plid, 0); | ||
627 | break; | 638 | break; |
628 | default: | 639 | default: |
629 | spin_unlock_bh(&sta->lock); | 640 | spin_unlock_bh(&sta->lock); |
@@ -635,10 +646,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
635 | switch (event) { | 646 | switch (event) { |
636 | case OPN_RJCT: | 647 | case OPN_RJCT: |
637 | case CNF_RJCT: | 648 | case CNF_RJCT: |
638 | reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); | 649 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); |
639 | case CLS_ACPT: | 650 | case CLS_ACPT: |
640 | if (!reason) | 651 | if (!reason) |
641 | reason = cpu_to_le16(MESH_CLOSE_RCVD); | 652 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); |
642 | sta->reason = reason; | 653 | sta->reason = reason; |
643 | sta->plink_state = NL80211_PLINK_HOLDING; | 654 | sta->plink_state = NL80211_PLINK_HOLDING; |
644 | if (!mod_plink_timer(sta, | 655 | if (!mod_plink_timer(sta, |
@@ -647,8 +658,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
647 | 658 | ||
648 | llid = sta->llid; | 659 | llid = sta->llid; |
649 | spin_unlock_bh(&sta->lock); | 660 | spin_unlock_bh(&sta->lock); |
650 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, | 661 | mesh_plink_frame_tx(sdata, |
651 | plid, reason); | 662 | WLAN_SP_MESH_PEERING_CLOSE, |
663 | sta->sta.addr, llid, plid, reason); | ||
652 | break; | 664 | break; |
653 | case OPN_ACPT: | 665 | case OPN_ACPT: |
654 | /* retry timer is left untouched */ | 666 | /* retry timer is left untouched */ |
@@ -656,8 +668,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
656 | sta->plid = plid; | 668 | sta->plid = plid; |
657 | llid = sta->llid; | 669 | llid = sta->llid; |
658 | spin_unlock_bh(&sta->lock); | 670 | spin_unlock_bh(&sta->lock); |
659 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, | 671 | mesh_plink_frame_tx(sdata, |
660 | plid, 0); | 672 | WLAN_SP_MESH_PEERING_CONFIRM, |
673 | sta->sta.addr, llid, plid, 0); | ||
661 | break; | 674 | break; |
662 | case CNF_ACPT: | 675 | case CNF_ACPT: |
663 | sta->plink_state = NL80211_PLINK_CNF_RCVD; | 676 | sta->plink_state = NL80211_PLINK_CNF_RCVD; |
@@ -677,10 +690,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
677 | switch (event) { | 690 | switch (event) { |
678 | case OPN_RJCT: | 691 | case OPN_RJCT: |
679 | case CNF_RJCT: | 692 | case CNF_RJCT: |
680 | reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); | 693 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); |
681 | case CLS_ACPT: | 694 | case CLS_ACPT: |
682 | if (!reason) | 695 | if (!reason) |
683 | reason = cpu_to_le16(MESH_CLOSE_RCVD); | 696 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); |
684 | sta->reason = reason; | 697 | sta->reason = reason; |
685 | sta->plink_state = NL80211_PLINK_HOLDING; | 698 | sta->plink_state = NL80211_PLINK_HOLDING; |
686 | if (!mod_plink_timer(sta, | 699 | if (!mod_plink_timer(sta, |
@@ -689,14 +702,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
689 | 702 | ||
690 | llid = sta->llid; | 703 | llid = sta->llid; |
691 | spin_unlock_bh(&sta->lock); | 704 | spin_unlock_bh(&sta->lock); |
692 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, | 705 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
693 | plid, reason); | 706 | sta->sta.addr, llid, plid, reason); |
694 | break; | 707 | break; |
695 | case OPN_ACPT: | 708 | case OPN_ACPT: |
696 | llid = sta->llid; | 709 | llid = sta->llid; |
697 | spin_unlock_bh(&sta->lock); | 710 | spin_unlock_bh(&sta->lock); |
698 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, | 711 | mesh_plink_frame_tx(sdata, |
699 | plid, 0); | 712 | WLAN_SP_MESH_PEERING_CONFIRM, |
713 | sta->sta.addr, llid, plid, 0); | ||
700 | break; | 714 | break; |
701 | case CNF_ACPT: | 715 | case CNF_ACPT: |
702 | del_timer(&sta->plink_timer); | 716 | del_timer(&sta->plink_timer); |
@@ -717,10 +731,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
717 | switch (event) { | 731 | switch (event) { |
718 | case OPN_RJCT: | 732 | case OPN_RJCT: |
719 | case CNF_RJCT: | 733 | case CNF_RJCT: |
720 | reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); | 734 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG); |
721 | case CLS_ACPT: | 735 | case CLS_ACPT: |
722 | if (!reason) | 736 | if (!reason) |
723 | reason = cpu_to_le16(MESH_CLOSE_RCVD); | 737 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); |
724 | sta->reason = reason; | 738 | sta->reason = reason; |
725 | sta->plink_state = NL80211_PLINK_HOLDING; | 739 | sta->plink_state = NL80211_PLINK_HOLDING; |
726 | if (!mod_plink_timer(sta, | 740 | if (!mod_plink_timer(sta, |
@@ -729,8 +743,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
729 | 743 | ||
730 | llid = sta->llid; | 744 | llid = sta->llid; |
731 | spin_unlock_bh(&sta->lock); | 745 | spin_unlock_bh(&sta->lock); |
732 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, | 746 | mesh_plink_frame_tx(sdata, |
733 | plid, reason); | 747 | WLAN_SP_MESH_PEERING_CLOSE, |
748 | sta->sta.addr, llid, plid, reason); | ||
734 | break; | 749 | break; |
735 | case OPN_ACPT: | 750 | case OPN_ACPT: |
736 | del_timer(&sta->plink_timer); | 751 | del_timer(&sta->plink_timer); |
@@ -740,8 +755,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
740 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 755 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); |
741 | mpl_dbg("Mesh plink with %pM ESTABLISHED\n", | 756 | mpl_dbg("Mesh plink with %pM ESTABLISHED\n", |
742 | sta->sta.addr); | 757 | sta->sta.addr); |
743 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, | 758 | mesh_plink_frame_tx(sdata, |
744 | plid, 0); | 759 | WLAN_SP_MESH_PEERING_CONFIRM, |
760 | sta->sta.addr, llid, plid, 0); | ||
745 | break; | 761 | break; |
746 | default: | 762 | default: |
747 | spin_unlock_bh(&sta->lock); | 763 | spin_unlock_bh(&sta->lock); |
@@ -752,7 +768,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
752 | case NL80211_PLINK_ESTAB: | 768 | case NL80211_PLINK_ESTAB: |
753 | switch (event) { | 769 | switch (event) { |
754 | case CLS_ACPT: | 770 | case CLS_ACPT: |
755 | reason = cpu_to_le16(MESH_CLOSE_RCVD); | 771 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); |
756 | sta->reason = reason; | 772 | sta->reason = reason; |
757 | deactivated = __mesh_plink_deactivate(sta); | 773 | deactivated = __mesh_plink_deactivate(sta); |
758 | sta->plink_state = NL80211_PLINK_HOLDING; | 774 | sta->plink_state = NL80211_PLINK_HOLDING; |
@@ -761,14 +777,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
761 | spin_unlock_bh(&sta->lock); | 777 | spin_unlock_bh(&sta->lock); |
762 | if (deactivated) | 778 | if (deactivated) |
763 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 779 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); |
764 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, | 780 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
765 | plid, reason); | 781 | sta->sta.addr, llid, plid, reason); |
766 | break; | 782 | break; |
767 | case OPN_ACPT: | 783 | case OPN_ACPT: |
768 | llid = sta->llid; | 784 | llid = sta->llid; |
769 | spin_unlock_bh(&sta->lock); | 785 | spin_unlock_bh(&sta->lock); |
770 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, | 786 | mesh_plink_frame_tx(sdata, |
771 | plid, 0); | 787 | WLAN_SP_MESH_PEERING_CONFIRM, |
788 | sta->sta.addr, llid, plid, 0); | ||
772 | break; | 789 | break; |
773 | default: | 790 | default: |
774 | spin_unlock_bh(&sta->lock); | 791 | spin_unlock_bh(&sta->lock); |
@@ -790,8 +807,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
790 | llid = sta->llid; | 807 | llid = sta->llid; |
791 | reason = sta->reason; | 808 | reason = sta->reason; |
792 | spin_unlock_bh(&sta->lock); | 809 | spin_unlock_bh(&sta->lock); |
793 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, | 810 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
794 | llid, plid, reason); | 811 | sta->sta.addr, llid, plid, reason); |
795 | break; | 812 | break; |
796 | default: | 813 | default: |
797 | spin_unlock_bh(&sta->lock); | 814 | spin_unlock_bh(&sta->lock); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d6470c7fd6ce..ba2da11a997b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/if_arp.h> | 17 | #include <linux/if_arp.h> |
18 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
19 | #include <linux/rtnetlink.h> | 19 | #include <linux/rtnetlink.h> |
20 | #include <linux/pm_qos_params.h> | 20 | #include <linux/pm_qos.h> |
21 | #include <linux/crc32.h> | 21 | #include <linux/crc32.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <net/mac80211.h> | 23 | #include <net/mac80211.h> |
@@ -160,7 +160,8 @@ static int ecw2cw(int ecw) | |||
160 | */ | 160 | */ |
161 | static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | 161 | static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, |
162 | struct ieee80211_ht_info *hti, | 162 | struct ieee80211_ht_info *hti, |
163 | const u8 *bssid, u16 ap_ht_cap_flags) | 163 | const u8 *bssid, u16 ap_ht_cap_flags, |
164 | bool beacon_htcap_ie) | ||
164 | { | 165 | { |
165 | struct ieee80211_local *local = sdata->local; | 166 | struct ieee80211_local *local = sdata->local; |
166 | struct ieee80211_supported_band *sband; | 167 | struct ieee80211_supported_band *sband; |
@@ -232,6 +233,21 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
232 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); | 233 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); |
233 | } | 234 | } |
234 | 235 | ||
236 | if (beacon_htcap_ie && (prev_chantype != channel_type)) { | ||
237 | /* | ||
238 | * Whenever the AP announces the HT mode change that can be | ||
239 | * 40MHz intolerant or etc., it would be safer to stop tx | ||
240 | * queues before doing hw config to avoid buffer overflow. | ||
241 | */ | ||
242 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
243 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
244 | |||
245 | /* flush out all packets */ | ||
246 | synchronize_net(); | ||
247 | |||
248 | drv_flush(local, false); | ||
249 | } | ||
250 | |||
235 | /* channel_type change automatically detected */ | 251 | /* channel_type change automatically detected */ |
236 | ieee80211_hw_config(local, 0); | 252 | ieee80211_hw_config(local, 0); |
237 | 253 | ||
@@ -243,6 +259,10 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
243 | IEEE80211_RC_HT_CHANGED, | 259 | IEEE80211_RC_HT_CHANGED, |
244 | channel_type); | 260 | channel_type); |
245 | rcu_read_unlock(); | 261 | rcu_read_unlock(); |
262 | |||
263 | if (beacon_htcap_ie) | ||
264 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | ||
265 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
246 | } | 266 | } |
247 | 267 | ||
248 | ht_opmode = le16_to_cpu(hti->operation_mode); | 268 | ht_opmode = le16_to_cpu(hti->operation_mode); |
@@ -271,11 +291,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
271 | struct ieee80211_mgmt *mgmt; | 291 | struct ieee80211_mgmt *mgmt; |
272 | 292 | ||
273 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 293 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); |
274 | if (!skb) { | 294 | if (!skb) |
275 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | ||
276 | "deauth/disassoc frame\n", sdata->name); | ||
277 | return; | 295 | return; |
278 | } | 296 | |
279 | skb_reserve(skb, local->hw.extra_tx_headroom); | 297 | skb_reserve(skb, local->hw.extra_tx_headroom); |
280 | 298 | ||
281 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 299 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
@@ -330,6 +348,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
330 | { | 348 | { |
331 | struct sk_buff *skb; | 349 | struct sk_buff *skb; |
332 | struct ieee80211_hdr_3addr *nullfunc; | 350 | struct ieee80211_hdr_3addr *nullfunc; |
351 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
333 | 352 | ||
334 | skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif); | 353 | skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif); |
335 | if (!skb) | 354 | if (!skb) |
@@ -340,6 +359,10 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
340 | nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); | 359 | nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
341 | 360 | ||
342 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 361 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
362 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | ||
363 | IEEE80211_STA_CONNECTION_POLL)) | ||
364 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; | ||
365 | |||
343 | ieee80211_tx_skb(sdata, skb); | 366 | ieee80211_tx_skb(sdata, skb); |
344 | } | 367 | } |
345 | 368 | ||
@@ -354,11 +377,9 @@ static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, | |||
354 | return; | 377 | return; |
355 | 378 | ||
356 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); | 379 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); |
357 | if (!skb) { | 380 | if (!skb) |
358 | printk(KERN_DEBUG "%s: failed to allocate buffer for 4addr " | ||
359 | "nullfunc frame\n", sdata->name); | ||
360 | return; | 381 | return; |
361 | } | 382 | |
362 | skb_reserve(skb, local->hw.extra_tx_headroom); | 383 | skb_reserve(skb, local->hw.extra_tx_headroom); |
363 | 384 | ||
364 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30); | 385 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30); |
@@ -394,6 +415,9 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
394 | /* call "hw_config" only if doing sw channel switch */ | 415 | /* call "hw_config" only if doing sw channel switch */ |
395 | ieee80211_hw_config(sdata->local, | 416 | ieee80211_hw_config(sdata->local, |
396 | IEEE80211_CONF_CHANGE_CHANNEL); | 417 | IEEE80211_CONF_CHANGE_CHANNEL); |
418 | } else { | ||
419 | /* update the device channel directly */ | ||
420 | sdata->local->hw.conf.channel = sdata->local->oper_channel; | ||
397 | } | 421 | } |
398 | 422 | ||
399 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 423 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
@@ -608,7 +632,7 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) | |||
608 | { | 632 | { |
609 | struct ieee80211_if_managed *mgd = &sdata->u.mgd; | 633 | struct ieee80211_if_managed *mgd = &sdata->u.mgd; |
610 | struct sta_info *sta = NULL; | 634 | struct sta_info *sta = NULL; |
611 | u32 sta_flags = 0; | 635 | bool authorized = false; |
612 | 636 | ||
613 | if (!mgd->powersave) | 637 | if (!mgd->powersave) |
614 | return false; | 638 | return false; |
@@ -626,13 +650,10 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) | |||
626 | rcu_read_lock(); | 650 | rcu_read_lock(); |
627 | sta = sta_info_get(sdata, mgd->bssid); | 651 | sta = sta_info_get(sdata, mgd->bssid); |
628 | if (sta) | 652 | if (sta) |
629 | sta_flags = get_sta_flags(sta); | 653 | authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); |
630 | rcu_read_unlock(); | 654 | rcu_read_unlock(); |
631 | 655 | ||
632 | if (!(sta_flags & WLAN_STA_AUTHORIZED)) | 656 | return authorized; |
633 | return false; | ||
634 | |||
635 | return true; | ||
636 | } | 657 | } |
637 | 658 | ||
638 | /* need to hold RTNL or interface lock */ | 659 | /* need to hold RTNL or interface lock */ |
@@ -917,8 +938,8 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
917 | params.aifs, params.cw_min, params.cw_max, | 938 | params.aifs, params.cw_min, params.cw_max, |
918 | params.txop, params.uapsd); | 939 | params.txop, params.uapsd); |
919 | #endif | 940 | #endif |
920 | local->tx_conf[queue] = params; | 941 | sdata->tx_conf[queue] = params; |
921 | if (drv_conf_tx(local, queue, ¶ms)) | 942 | if (drv_conf_tx(local, sdata, queue, ¶ms)) |
922 | wiphy_debug(local->hw.wiphy, | 943 | wiphy_debug(local->hw.wiphy, |
923 | "failed to set TX queue parameters for queue %d\n", | 944 | "failed to set TX queue parameters for queue %d\n", |
924 | queue); | 945 | queue); |
@@ -1076,7 +1097,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1076 | mutex_lock(&local->sta_mtx); | 1097 | mutex_lock(&local->sta_mtx); |
1077 | sta = sta_info_get(sdata, bssid); | 1098 | sta = sta_info_get(sdata, bssid); |
1078 | if (sta) { | 1099 | if (sta) { |
1079 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 1100 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
1080 | ieee80211_sta_tear_down_BA_sessions(sta, tx); | 1101 | ieee80211_sta_tear_down_BA_sessions(sta, tx); |
1081 | } | 1102 | } |
1082 | mutex_unlock(&local->sta_mtx); | 1103 | mutex_unlock(&local->sta_mtx); |
@@ -1118,8 +1139,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1118 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; | 1139 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; |
1119 | ieee80211_bss_info_change_notify(sdata, changed); | 1140 | ieee80211_bss_info_change_notify(sdata, changed); |
1120 | 1141 | ||
1142 | /* remove AP and TDLS peers */ | ||
1121 | if (remove_sta) | 1143 | if (remove_sta) |
1122 | sta_info_destroy_addr(sdata, bssid); | 1144 | sta_info_flush(local, sdata); |
1123 | 1145 | ||
1124 | del_timer_sync(&sdata->u.mgd.conn_mon_timer); | 1146 | del_timer_sync(&sdata->u.mgd.conn_mon_timer); |
1125 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); | 1147 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); |
@@ -1220,7 +1242,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1220 | } else { | 1242 | } else { |
1221 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1243 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1222 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, | 1244 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, |
1223 | (u32) -1, true); | 1245 | (u32) -1, true, false); |
1224 | } | 1246 | } |
1225 | 1247 | ||
1226 | ifmgd->probe_send_count++; | 1248 | ifmgd->probe_send_count++; |
@@ -1482,17 +1504,22 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1482 | 1504 | ||
1483 | ifmgd->aid = aid; | 1505 | ifmgd->aid = aid; |
1484 | 1506 | ||
1485 | sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); | 1507 | mutex_lock(&sdata->local->sta_mtx); |
1486 | if (!sta) { | 1508 | /* |
1487 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" | 1509 | * station info was already allocated and inserted before |
1488 | " the AP\n", sdata->name); | 1510 | * the association and should be available to us |
1511 | */ | ||
1512 | sta = sta_info_get_rx(sdata, cbss->bssid); | ||
1513 | if (WARN_ON(!sta)) { | ||
1514 | mutex_unlock(&sdata->local->sta_mtx); | ||
1489 | return false; | 1515 | return false; |
1490 | } | 1516 | } |
1491 | 1517 | ||
1492 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | 1518 | set_sta_flag(sta, WLAN_STA_AUTH); |
1493 | WLAN_STA_ASSOC_AP); | 1519 | set_sta_flag(sta, WLAN_STA_ASSOC); |
1520 | set_sta_flag(sta, WLAN_STA_ASSOC_AP); | ||
1494 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 1521 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
1495 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | 1522 | set_sta_flag(sta, WLAN_STA_AUTHORIZED); |
1496 | 1523 | ||
1497 | rates = 0; | 1524 | rates = 0; |
1498 | basic_rates = 0; | 1525 | basic_rates = 0; |
@@ -1551,12 +1578,13 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1551 | rate_control_rate_init(sta); | 1578 | rate_control_rate_init(sta); |
1552 | 1579 | ||
1553 | if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) | 1580 | if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) |
1554 | set_sta_flags(sta, WLAN_STA_MFP); | 1581 | set_sta_flag(sta, WLAN_STA_MFP); |
1555 | 1582 | ||
1556 | if (elems.wmm_param) | 1583 | if (elems.wmm_param) |
1557 | set_sta_flags(sta, WLAN_STA_WME); | 1584 | set_sta_flag(sta, WLAN_STA_WME); |
1558 | 1585 | ||
1559 | err = sta_info_insert(sta); | 1586 | /* sta_info_reinsert will also unlock the mutex lock */ |
1587 | err = sta_info_reinsert(sta); | ||
1560 | sta = NULL; | 1588 | sta = NULL; |
1561 | if (err) { | 1589 | if (err) { |
1562 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | 1590 | printk(KERN_DEBUG "%s: failed to insert STA entry for" |
@@ -1584,7 +1612,8 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1584 | (sdata->local->hw.queues >= 4) && | 1612 | (sdata->local->hw.queues >= 4) && |
1585 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 1613 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
1586 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 1614 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, |
1587 | cbss->bssid, ap_ht_cap_flags); | 1615 | cbss->bssid, ap_ht_cap_flags, |
1616 | false); | ||
1588 | 1617 | ||
1589 | /* set AID and assoc capability, | 1618 | /* set AID and assoc capability, |
1590 | * ieee80211_set_associated() will tell the driver */ | 1619 | * ieee80211_set_associated() will tell the driver */ |
@@ -1918,7 +1947,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1918 | rcu_read_unlock(); | 1947 | rcu_read_unlock(); |
1919 | 1948 | ||
1920 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 1949 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, |
1921 | bssid, ap_ht_cap_flags); | 1950 | bssid, ap_ht_cap_flags, true); |
1922 | } | 1951 | } |
1923 | 1952 | ||
1924 | /* Note: country IE parsing is done for us by cfg80211 */ | 1953 | /* Note: country IE parsing is done for us by cfg80211 */ |
@@ -2429,6 +2458,29 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2429 | return 0; | 2458 | return 0; |
2430 | } | 2459 | } |
2431 | 2460 | ||
2461 | /* create and insert a dummy station entry */ | ||
2462 | static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata, | ||
2463 | u8 *bssid) { | ||
2464 | struct sta_info *sta; | ||
2465 | int err; | ||
2466 | |||
2467 | sta = sta_info_alloc(sdata, bssid, GFP_KERNEL); | ||
2468 | if (!sta) | ||
2469 | return -ENOMEM; | ||
2470 | |||
2471 | sta->dummy = true; | ||
2472 | |||
2473 | err = sta_info_insert(sta); | ||
2474 | sta = NULL; | ||
2475 | if (err) { | ||
2476 | printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for" | ||
2477 | " the AP (error %d)\n", sdata->name, err); | ||
2478 | return err; | ||
2479 | } | ||
2480 | |||
2481 | return 0; | ||
2482 | } | ||
2483 | |||
2432 | static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, | 2484 | static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, |
2433 | struct sk_buff *skb) | 2485 | struct sk_buff *skb) |
2434 | { | 2486 | { |
@@ -2436,9 +2488,11 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, | |||
2436 | struct ieee80211_mgmt *mgmt; | 2488 | struct ieee80211_mgmt *mgmt; |
2437 | struct ieee80211_rx_status *rx_status; | 2489 | struct ieee80211_rx_status *rx_status; |
2438 | struct ieee802_11_elems elems; | 2490 | struct ieee802_11_elems elems; |
2491 | struct cfg80211_bss *cbss = wk->assoc.bss; | ||
2439 | u16 status; | 2492 | u16 status; |
2440 | 2493 | ||
2441 | if (!skb) { | 2494 | if (!skb) { |
2495 | sta_info_destroy_addr(wk->sdata, cbss->bssid); | ||
2442 | cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); | 2496 | cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); |
2443 | goto destroy; | 2497 | goto destroy; |
2444 | } | 2498 | } |
@@ -2468,12 +2522,16 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, | |||
2468 | if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { | 2522 | if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { |
2469 | mutex_unlock(&wk->sdata->u.mgd.mtx); | 2523 | mutex_unlock(&wk->sdata->u.mgd.mtx); |
2470 | /* oops -- internal error -- send timeout for now */ | 2524 | /* oops -- internal error -- send timeout for now */ |
2525 | sta_info_destroy_addr(wk->sdata, cbss->bssid); | ||
2471 | cfg80211_send_assoc_timeout(wk->sdata->dev, | 2526 | cfg80211_send_assoc_timeout(wk->sdata->dev, |
2472 | wk->filter_ta); | 2527 | wk->filter_ta); |
2473 | return WORK_DONE_DESTROY; | 2528 | return WORK_DONE_DESTROY; |
2474 | } | 2529 | } |
2475 | 2530 | ||
2476 | mutex_unlock(&wk->sdata->u.mgd.mtx); | 2531 | mutex_unlock(&wk->sdata->u.mgd.mtx); |
2532 | } else { | ||
2533 | /* assoc failed - destroy the dummy station entry */ | ||
2534 | sta_info_destroy_addr(wk->sdata, cbss->bssid); | ||
2477 | } | 2535 | } |
2478 | 2536 | ||
2479 | cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); | 2537 | cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); |
@@ -2492,7 +2550,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2492 | struct ieee80211_bss *bss = (void *)req->bss->priv; | 2550 | struct ieee80211_bss *bss = (void *)req->bss->priv; |
2493 | struct ieee80211_work *wk; | 2551 | struct ieee80211_work *wk; |
2494 | const u8 *ssid; | 2552 | const u8 *ssid; |
2495 | int i; | 2553 | int i, err; |
2496 | 2554 | ||
2497 | mutex_lock(&ifmgd->mtx); | 2555 | mutex_lock(&ifmgd->mtx); |
2498 | if (ifmgd->associated) { | 2556 | if (ifmgd->associated) { |
@@ -2517,6 +2575,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2517 | if (!wk) | 2575 | if (!wk) |
2518 | return -ENOMEM; | 2576 | return -ENOMEM; |
2519 | 2577 | ||
2578 | /* | ||
2579 | * create a dummy station info entry in order | ||
2580 | * to start accepting incoming EAPOL packets from the station | ||
2581 | */ | ||
2582 | err = ieee80211_pre_assoc(sdata, req->bss->bssid); | ||
2583 | if (err) { | ||
2584 | kfree(wk); | ||
2585 | return err; | ||
2586 | } | ||
2587 | |||
2520 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; | 2588 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; |
2521 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 2589 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; |
2522 | 2590 | ||
@@ -2674,7 +2742,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2674 | req->reason_code, cookie, | 2742 | req->reason_code, cookie, |
2675 | !req->local_state_change); | 2743 | !req->local_state_change); |
2676 | if (assoc_bss) | 2744 | if (assoc_bss) |
2677 | sta_info_destroy_addr(sdata, bssid); | 2745 | sta_info_flush(sdata->local, sdata); |
2678 | 2746 | ||
2679 | mutex_lock(&sdata->local->mtx); | 2747 | mutex_lock(&sdata->local->mtx); |
2680 | ieee80211_recalc_idle(sdata->local); | 2748 | ieee80211_recalc_idle(sdata->local); |
@@ -2714,7 +2782,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2714 | ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, | 2782 | ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, |
2715 | IEEE80211_STYPE_DISASSOC, req->reason_code, | 2783 | IEEE80211_STYPE_DISASSOC, req->reason_code, |
2716 | cookie, !req->local_state_change); | 2784 | cookie, !req->local_state_change); |
2717 | sta_info_destroy_addr(sdata, bssid); | 2785 | sta_info_flush(sdata->local, sdata); |
2718 | 2786 | ||
2719 | mutex_lock(&sdata->local->mtx); | 2787 | mutex_lock(&sdata->local->mtx); |
2720 | ieee80211_recalc_idle(sdata->local); | 2788 | ieee80211_recalc_idle(sdata->local); |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 6326d3439861..9ee7164b207c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -42,7 +42,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
42 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 42 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
43 | mutex_lock(&local->sta_mtx); | 43 | mutex_lock(&local->sta_mtx); |
44 | list_for_each_entry(sta, &local->sta_list, list) { | 44 | list_for_each_entry(sta, &local->sta_list, list) { |
45 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 45 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
46 | ieee80211_sta_tear_down_BA_sessions(sta, true); | 46 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
47 | } | 47 | } |
48 | mutex_unlock(&local->sta_mtx); | 48 | mutex_unlock(&local->sta_mtx); |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 3d5a2cb835c4..ff5c3aa48a15 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -199,7 +199,7 @@ static void rate_control_release(struct kref *kref) | |||
199 | kfree(ctrl_ref); | 199 | kfree(ctrl_ref); |
200 | } | 200 | } |
201 | 201 | ||
202 | static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) | 202 | static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc) |
203 | { | 203 | { |
204 | struct sk_buff *skb = txrc->skb; | 204 | struct sk_buff *skb = txrc->skb; |
205 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 205 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -208,7 +208,9 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) | |||
208 | 208 | ||
209 | fc = hdr->frame_control; | 209 | fc = hdr->frame_control; |
210 | 210 | ||
211 | return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc); | 211 | return (info->flags & (IEEE80211_TX_CTL_NO_ACK | |
212 | IEEE80211_TX_CTL_USE_MINRATE)) || | ||
213 | !ieee80211_is_data(fc); | ||
212 | } | 214 | } |
213 | 215 | ||
214 | static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, | 216 | static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, |
@@ -233,6 +235,27 @@ static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, | |||
233 | /* could not find a basic rate; use original selection */ | 235 | /* could not find a basic rate; use original selection */ |
234 | } | 236 | } |
235 | 237 | ||
238 | static inline s8 | ||
239 | rate_lowest_non_cck_index(struct ieee80211_supported_band *sband, | ||
240 | struct ieee80211_sta *sta) | ||
241 | { | ||
242 | int i; | ||
243 | |||
244 | for (i = 0; i < sband->n_bitrates; i++) { | ||
245 | struct ieee80211_rate *srate = &sband->bitrates[i]; | ||
246 | if ((srate->bitrate == 10) || (srate->bitrate == 20) || | ||
247 | (srate->bitrate == 55) || (srate->bitrate == 110)) | ||
248 | continue; | ||
249 | |||
250 | if (rate_supported(sta, sband->band, i)) | ||
251 | return i; | ||
252 | } | ||
253 | |||
254 | /* No matching rate found */ | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | |||
236 | bool rate_control_send_low(struct ieee80211_sta *sta, | 259 | bool rate_control_send_low(struct ieee80211_sta *sta, |
237 | void *priv_sta, | 260 | void *priv_sta, |
238 | struct ieee80211_tx_rate_control *txrc) | 261 | struct ieee80211_tx_rate_control *txrc) |
@@ -241,8 +264,14 @@ bool rate_control_send_low(struct ieee80211_sta *sta, | |||
241 | struct ieee80211_supported_band *sband = txrc->sband; | 264 | struct ieee80211_supported_band *sband = txrc->sband; |
242 | int mcast_rate; | 265 | int mcast_rate; |
243 | 266 | ||
244 | if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { | 267 | if (!sta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { |
245 | info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta); | 268 | if ((sband->band != IEEE80211_BAND_2GHZ) || |
269 | !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) | ||
270 | info->control.rates[0].idx = | ||
271 | rate_lowest_index(txrc->sband, sta); | ||
272 | else | ||
273 | info->control.rates[0].idx = | ||
274 | rate_lowest_non_cck_index(txrc->sband, sta); | ||
246 | info->control.rates[0].count = | 275 | info->control.rates[0].count = |
247 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | 276 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
248 | 1 : txrc->hw->max_rate_tries; | 277 | 1 : txrc->hw->max_rate_tries; |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 66a1eeb279c6..cdb28535716b 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -281,6 +281,8 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
281 | 281 | ||
282 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate); | 282 | mr = minstrel_get_ratestats(mi, mg->max_tp_rate); |
283 | if (cur_tp < mr->cur_tp) { | 283 | if (cur_tp < mr->cur_tp) { |
284 | mi->max_tp_rate2 = mi->max_tp_rate; | ||
285 | cur_tp2 = cur_tp; | ||
284 | mi->max_tp_rate = mg->max_tp_rate; | 286 | mi->max_tp_rate = mg->max_tp_rate; |
285 | cur_tp = mr->cur_tp; | 287 | cur_tp = mr->cur_tp; |
286 | } | 288 | } |
@@ -452,7 +454,8 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
452 | 454 | ||
453 | if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { | 455 | if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { |
454 | minstrel_ht_update_stats(mp, mi); | 456 | minstrel_ht_update_stats(mp, mi); |
455 | minstrel_aggr_check(mp, sta, skb); | 457 | if (!(info->flags & IEEE80211_TX_CTL_AMPDU)) |
458 | minstrel_aggr_check(mp, sta, skb); | ||
456 | } | 459 | } |
457 | } | 460 | } |
458 | 461 | ||
@@ -608,7 +611,13 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
608 | return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc); | 611 | return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc); |
609 | 612 | ||
610 | info->flags |= mi->tx_flags; | 613 | info->flags |= mi->tx_flags; |
611 | sample_idx = minstrel_get_sample_rate(mp, mi); | 614 | |
615 | /* Don't use EAPOL frames for sampling on non-mrr hw */ | ||
616 | if (mp->hw->max_rates == 1 && | ||
617 | txrc->skb->protocol == cpu_to_be16(ETH_P_PAE)) | ||
618 | sample_idx = -1; | ||
619 | else | ||
620 | sample_idx = minstrel_get_sample_rate(mp, mi); | ||
612 | 621 | ||
613 | #ifdef CONFIG_MAC80211_DEBUGFS | 622 | #ifdef CONFIG_MAC80211_DEBUGFS |
614 | /* use fixed index if set */ | 623 | /* use fixed index if set */ |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fe2c2a717793..b867bd55de7a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -476,7 +476,6 @@ static ieee80211_rx_result | |||
476 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | 476 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) |
477 | { | 477 | { |
478 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 478 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
479 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
480 | char *dev_addr = rx->sdata->vif.addr; | 479 | char *dev_addr = rx->sdata->vif.addr; |
481 | 480 | ||
482 | if (ieee80211_is_data(hdr->frame_control)) { | 481 | if (ieee80211_is_data(hdr->frame_control)) { |
@@ -524,14 +523,6 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
524 | 523 | ||
525 | } | 524 | } |
526 | 525 | ||
527 | #define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l)) | ||
528 | |||
529 | if (ieee80211_is_data(hdr->frame_control) && | ||
530 | is_multicast_ether_addr(hdr->addr1) && | ||
531 | mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata)) | ||
532 | return RX_DROP_MONITOR; | ||
533 | #undef msh_h_get | ||
534 | |||
535 | return RX_CONTINUE; | 526 | return RX_CONTINUE; |
536 | } | 527 | } |
537 | 528 | ||
@@ -850,8 +841,21 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
850 | ieee80211_is_pspoll(hdr->frame_control)) && | 841 | ieee80211_is_pspoll(hdr->frame_control)) && |
851 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | 842 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
852 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && | 843 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && |
853 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) | 844 | (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) { |
845 | if (rx->sta && rx->sta->dummy && | ||
846 | ieee80211_is_data_present(hdr->frame_control)) { | ||
847 | u16 ethertype; | ||
848 | u8 *payload; | ||
849 | |||
850 | payload = rx->skb->data + | ||
851 | ieee80211_hdrlen(hdr->frame_control); | ||
852 | ethertype = (payload[6] << 8) | payload[7]; | ||
853 | if (cpu_to_be16(ethertype) == | ||
854 | rx->sdata->control_port_protocol) | ||
855 | return RX_CONTINUE; | ||
856 | } | ||
854 | return RX_DROP_MONITOR; | 857 | return RX_DROP_MONITOR; |
858 | } | ||
855 | 859 | ||
856 | return RX_CONTINUE; | 860 | return RX_CONTINUE; |
857 | } | 861 | } |
@@ -1106,7 +1110,7 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
1106 | struct ieee80211_local *local = sdata->local; | 1110 | struct ieee80211_local *local = sdata->local; |
1107 | 1111 | ||
1108 | atomic_inc(&sdata->bss->num_sta_ps); | 1112 | atomic_inc(&sdata->bss->num_sta_ps); |
1109 | set_sta_flags(sta, WLAN_STA_PS_STA); | 1113 | set_sta_flag(sta, WLAN_STA_PS_STA); |
1110 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) | 1114 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
1111 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); | 1115 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); |
1112 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1116 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
@@ -1126,7 +1130,7 @@ static void ap_sta_ps_end(struct sta_info *sta) | |||
1126 | sdata->name, sta->sta.addr, sta->sta.aid); | 1130 | sdata->name, sta->sta.addr, sta->sta.aid); |
1127 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1131 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1128 | 1132 | ||
1129 | if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) { | 1133 | if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { |
1130 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1134 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1131 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", | 1135 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", |
1132 | sdata->name, sta->sta.addr, sta->sta.aid); | 1136 | sdata->name, sta->sta.addr, sta->sta.aid); |
@@ -1145,7 +1149,7 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start) | |||
1145 | WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS)); | 1149 | WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS)); |
1146 | 1150 | ||
1147 | /* Don't let the same PS state be set twice */ | 1151 | /* Don't let the same PS state be set twice */ |
1148 | in_ps = test_sta_flags(sta_inf, WLAN_STA_PS_STA); | 1152 | in_ps = test_sta_flag(sta_inf, WLAN_STA_PS_STA); |
1149 | if ((start && in_ps) || (!start && !in_ps)) | 1153 | if ((start && in_ps) || (!start && !in_ps)) |
1150 | return -EINVAL; | 1154 | return -EINVAL; |
1151 | 1155 | ||
@@ -1159,6 +1163,81 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start) | |||
1159 | EXPORT_SYMBOL(ieee80211_sta_ps_transition); | 1163 | EXPORT_SYMBOL(ieee80211_sta_ps_transition); |
1160 | 1164 | ||
1161 | static ieee80211_rx_result debug_noinline | 1165 | static ieee80211_rx_result debug_noinline |
1166 | ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) | ||
1167 | { | ||
1168 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
1169 | struct ieee80211_hdr *hdr = (void *)rx->skb->data; | ||
1170 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | ||
1171 | int tid, ac; | ||
1172 | |||
1173 | if (!rx->sta || !(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1174 | return RX_CONTINUE; | ||
1175 | |||
1176 | if (sdata->vif.type != NL80211_IFTYPE_AP && | ||
1177 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN) | ||
1178 | return RX_CONTINUE; | ||
1179 | |||
1180 | /* | ||
1181 | * The device handles station powersave, so don't do anything about | ||
1182 | * uAPSD and PS-Poll frames (the latter shouldn't even come up from | ||
1183 | * it to mac80211 since they're handled.) | ||
1184 | */ | ||
1185 | if (sdata->local->hw.flags & IEEE80211_HW_AP_LINK_PS) | ||
1186 | return RX_CONTINUE; | ||
1187 | |||
1188 | /* | ||
1189 | * Don't do anything if the station isn't already asleep. In | ||
1190 | * the uAPSD case, the station will probably be marked asleep, | ||
1191 | * in the PS-Poll case the station must be confused ... | ||
1192 | */ | ||
1193 | if (!test_sta_flag(rx->sta, WLAN_STA_PS_STA)) | ||
1194 | return RX_CONTINUE; | ||
1195 | |||
1196 | if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) { | ||
1197 | if (!test_sta_flag(rx->sta, WLAN_STA_SP)) { | ||
1198 | if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER)) | ||
1199 | ieee80211_sta_ps_deliver_poll_response(rx->sta); | ||
1200 | else | ||
1201 | set_sta_flag(rx->sta, WLAN_STA_PSPOLL); | ||
1202 | } | ||
1203 | |||
1204 | /* Free PS Poll skb here instead of returning RX_DROP that would | ||
1205 | * count as an dropped frame. */ | ||
1206 | dev_kfree_skb(rx->skb); | ||
1207 | |||
1208 | return RX_QUEUED; | ||
1209 | } else if (!ieee80211_has_morefrags(hdr->frame_control) && | ||
1210 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | ||
1211 | ieee80211_has_pm(hdr->frame_control) && | ||
1212 | (ieee80211_is_data_qos(hdr->frame_control) || | ||
1213 | ieee80211_is_qos_nullfunc(hdr->frame_control))) { | ||
1214 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | ||
1215 | ac = ieee802_1d_to_ac[tid & 7]; | ||
1216 | |||
1217 | /* | ||
1218 | * If this AC is not trigger-enabled do nothing. | ||
1219 | * | ||
1220 | * NB: This could/should check a separate bitmap of trigger- | ||
1221 | * enabled queues, but for now we only implement uAPSD w/o | ||
1222 | * TSPEC changes to the ACs, so they're always the same. | ||
1223 | */ | ||
1224 | if (!(rx->sta->sta.uapsd_queues & BIT(ac))) | ||
1225 | return RX_CONTINUE; | ||
1226 | |||
1227 | /* if we are in a service period, do nothing */ | ||
1228 | if (test_sta_flag(rx->sta, WLAN_STA_SP)) | ||
1229 | return RX_CONTINUE; | ||
1230 | |||
1231 | if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER)) | ||
1232 | ieee80211_sta_ps_deliver_uapsd(rx->sta); | ||
1233 | else | ||
1234 | set_sta_flag(rx->sta, WLAN_STA_UAPSD); | ||
1235 | } | ||
1236 | |||
1237 | return RX_CONTINUE; | ||
1238 | } | ||
1239 | |||
1240 | static ieee80211_rx_result debug_noinline | ||
1162 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 1241 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) |
1163 | { | 1242 | { |
1164 | struct sta_info *sta = rx->sta; | 1243 | struct sta_info *sta = rx->sta; |
@@ -1216,7 +1295,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1216 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | 1295 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && |
1217 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1296 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1218 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { | 1297 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { |
1219 | if (test_sta_flags(sta, WLAN_STA_PS_STA)) { | 1298 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { |
1220 | /* | 1299 | /* |
1221 | * Ignore doze->wake transitions that are | 1300 | * Ignore doze->wake transitions that are |
1222 | * indicated by non-data frames, the standard | 1301 | * indicated by non-data frames, the standard |
@@ -1469,33 +1548,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1469 | } | 1548 | } |
1470 | 1549 | ||
1471 | static ieee80211_rx_result debug_noinline | 1550 | static ieee80211_rx_result debug_noinline |
1472 | ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | ||
1473 | { | ||
1474 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
1475 | __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; | ||
1476 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | ||
1477 | |||
1478 | if (likely(!rx->sta || !ieee80211_is_pspoll(fc) || | ||
1479 | !(status->rx_flags & IEEE80211_RX_RA_MATCH))) | ||
1480 | return RX_CONTINUE; | ||
1481 | |||
1482 | if ((sdata->vif.type != NL80211_IFTYPE_AP) && | ||
1483 | (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) | ||
1484 | return RX_DROP_UNUSABLE; | ||
1485 | |||
1486 | if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER)) | ||
1487 | ieee80211_sta_ps_deliver_poll_response(rx->sta); | ||
1488 | else | ||
1489 | set_sta_flags(rx->sta, WLAN_STA_PSPOLL); | ||
1490 | |||
1491 | /* Free PS Poll skb here instead of returning RX_DROP that would | ||
1492 | * count as an dropped frame. */ | ||
1493 | dev_kfree_skb(rx->skb); | ||
1494 | |||
1495 | return RX_QUEUED; | ||
1496 | } | ||
1497 | |||
1498 | static ieee80211_rx_result debug_noinline | ||
1499 | ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | 1551 | ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) |
1500 | { | 1552 | { |
1501 | u8 *data = rx->skb->data; | 1553 | u8 *data = rx->skb->data; |
@@ -1518,7 +1570,7 @@ static int | |||
1518 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | 1570 | ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) |
1519 | { | 1571 | { |
1520 | if (unlikely(!rx->sta || | 1572 | if (unlikely(!rx->sta || |
1521 | !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) | 1573 | !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED))) |
1522 | return -EACCES; | 1574 | return -EACCES; |
1523 | 1575 | ||
1524 | return 0; | 1576 | return 0; |
@@ -1561,7 +1613,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | |||
1561 | if (status->flag & RX_FLAG_DECRYPTED) | 1613 | if (status->flag & RX_FLAG_DECRYPTED) |
1562 | return 0; | 1614 | return 0; |
1563 | 1615 | ||
1564 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1616 | if (rx->sta && test_sta_flag(rx->sta, WLAN_STA_MFP)) { |
1565 | if (unlikely(!ieee80211_has_protected(fc) && | 1617 | if (unlikely(!ieee80211_has_protected(fc) && |
1566 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1618 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && |
1567 | rx->key)) { | 1619 | rx->key)) { |
@@ -1827,6 +1879,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1827 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1879 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1828 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | 1880 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1829 | 1881 | ||
1882 | /* frame is in RMC, don't forward */ | ||
1883 | if (ieee80211_is_data(hdr->frame_control) && | ||
1884 | is_multicast_ether_addr(hdr->addr1) && | ||
1885 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) | ||
1886 | return RX_DROP_MONITOR; | ||
1887 | |||
1830 | if (!ieee80211_is_data(hdr->frame_control)) | 1888 | if (!ieee80211_is_data(hdr->frame_control)) |
1831 | return RX_CONTINUE; | 1889 | return RX_CONTINUE; |
1832 | 1890 | ||
@@ -1834,6 +1892,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1834 | /* illegal frame */ | 1892 | /* illegal frame */ |
1835 | return RX_DROP_MONITOR; | 1893 | return RX_DROP_MONITOR; |
1836 | 1894 | ||
1895 | if (ieee80211_queue_stopped(&local->hw, skb_get_queue_mapping(skb))) { | ||
1896 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1897 | dropped_frames_congestion); | ||
1898 | return RX_DROP_MONITOR; | ||
1899 | } | ||
1900 | |||
1837 | if (mesh_hdr->flags & MESH_FLAGS_AE) { | 1901 | if (mesh_hdr->flags & MESH_FLAGS_AE) { |
1838 | struct mesh_path *mppath; | 1902 | struct mesh_path *mppath; |
1839 | char *proxied_addr; | 1903 | char *proxied_addr; |
@@ -1889,13 +1953,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1889 | memset(info, 0, sizeof(*info)); | 1953 | memset(info, 0, sizeof(*info)); |
1890 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1954 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1891 | info->control.vif = &rx->sdata->vif; | 1955 | info->control.vif = &rx->sdata->vif; |
1892 | skb_set_queue_mapping(skb, | 1956 | if (is_multicast_ether_addr(fwd_hdr->addr1)) { |
1893 | ieee80211_select_queue(rx->sdata, fwd_skb)); | ||
1894 | ieee80211_set_qos_hdr(local, skb); | ||
1895 | if (is_multicast_ether_addr(fwd_hdr->addr1)) | ||
1896 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | 1957 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, |
1897 | fwded_mcast); | 1958 | fwded_mcast); |
1898 | else { | 1959 | skb_set_queue_mapping(fwd_skb, |
1960 | ieee80211_select_queue(sdata, fwd_skb)); | ||
1961 | ieee80211_set_qos_hdr(sdata, fwd_skb); | ||
1962 | } else { | ||
1899 | int err; | 1963 | int err; |
1900 | /* | 1964 | /* |
1901 | * Save TA to addr1 to send TA a path error if a | 1965 | * Save TA to addr1 to send TA a path error if a |
@@ -2220,12 +2284,29 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2220 | goto handled; | 2284 | goto handled; |
2221 | } | 2285 | } |
2222 | break; | 2286 | break; |
2287 | case WLAN_CATEGORY_SELF_PROTECTED: | ||
2288 | switch (mgmt->u.action.u.self_prot.action_code) { | ||
2289 | case WLAN_SP_MESH_PEERING_OPEN: | ||
2290 | case WLAN_SP_MESH_PEERING_CLOSE: | ||
2291 | case WLAN_SP_MESH_PEERING_CONFIRM: | ||
2292 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
2293 | goto invalid; | ||
2294 | if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) | ||
2295 | /* userspace handles this frame */ | ||
2296 | break; | ||
2297 | goto queue; | ||
2298 | case WLAN_SP_MGK_INFORM: | ||
2299 | case WLAN_SP_MGK_ACK: | ||
2300 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
2301 | goto invalid; | ||
2302 | break; | ||
2303 | } | ||
2304 | break; | ||
2223 | case WLAN_CATEGORY_MESH_ACTION: | 2305 | case WLAN_CATEGORY_MESH_ACTION: |
2224 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2306 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2225 | break; | 2307 | break; |
2226 | goto queue; | 2308 | if (mesh_action_is_path_sel(mgmt) && |
2227 | case WLAN_CATEGORY_MESH_PATH_SEL: | 2309 | (!mesh_path_sel_is_hwmp(sdata))) |
2228 | if (!mesh_path_sel_is_hwmp(sdata)) | ||
2229 | break; | 2310 | break; |
2230 | goto queue; | 2311 | goto queue; |
2231 | } | 2312 | } |
@@ -2534,17 +2615,17 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2534 | 2615 | ||
2535 | CALL_RXH(ieee80211_rx_h_decrypt) | 2616 | CALL_RXH(ieee80211_rx_h_decrypt) |
2536 | CALL_RXH(ieee80211_rx_h_check_more_data) | 2617 | CALL_RXH(ieee80211_rx_h_check_more_data) |
2618 | CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll) | ||
2537 | CALL_RXH(ieee80211_rx_h_sta_process) | 2619 | CALL_RXH(ieee80211_rx_h_sta_process) |
2538 | CALL_RXH(ieee80211_rx_h_defragment) | 2620 | CALL_RXH(ieee80211_rx_h_defragment) |
2539 | CALL_RXH(ieee80211_rx_h_ps_poll) | ||
2540 | CALL_RXH(ieee80211_rx_h_michael_mic_verify) | 2621 | CALL_RXH(ieee80211_rx_h_michael_mic_verify) |
2541 | /* must be after MMIC verify so header is counted in MPDU mic */ | 2622 | /* must be after MMIC verify so header is counted in MPDU mic */ |
2542 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | ||
2543 | CALL_RXH(ieee80211_rx_h_amsdu) | ||
2544 | #ifdef CONFIG_MAC80211_MESH | 2623 | #ifdef CONFIG_MAC80211_MESH |
2545 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) | 2624 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) |
2546 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 2625 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
2547 | #endif | 2626 | #endif |
2627 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | ||
2628 | CALL_RXH(ieee80211_rx_h_amsdu) | ||
2548 | CALL_RXH(ieee80211_rx_h_data) | 2629 | CALL_RXH(ieee80211_rx_h_data) |
2549 | CALL_RXH(ieee80211_rx_h_ctrl); | 2630 | CALL_RXH(ieee80211_rx_h_ctrl); |
2550 | CALL_RXH(ieee80211_rx_h_mgmt_check) | 2631 | CALL_RXH(ieee80211_rx_h_mgmt_check) |
@@ -2686,7 +2767,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2686 | } else if (!ieee80211_bssid_match(bssid, | 2767 | } else if (!ieee80211_bssid_match(bssid, |
2687 | sdata->vif.addr)) { | 2768 | sdata->vif.addr)) { |
2688 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && | 2769 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && |
2689 | !ieee80211_is_beacon(hdr->frame_control)) | 2770 | !ieee80211_is_beacon(hdr->frame_control) && |
2771 | !(ieee80211_is_action(hdr->frame_control) && | ||
2772 | sdata->vif.p2p)) | ||
2690 | return 0; | 2773 | return 0; |
2691 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2774 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2692 | } | 2775 | } |
@@ -2791,7 +2874,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2791 | if (ieee80211_is_data(fc)) { | 2874 | if (ieee80211_is_data(fc)) { |
2792 | prev_sta = NULL; | 2875 | prev_sta = NULL; |
2793 | 2876 | ||
2794 | for_each_sta_info(local, hdr->addr2, sta, tmp) { | 2877 | for_each_sta_info_rx(local, hdr->addr2, sta, tmp) { |
2795 | if (!prev_sta) { | 2878 | if (!prev_sta) { |
2796 | prev_sta = sta; | 2879 | prev_sta = sta; |
2797 | continue; | 2880 | continue; |
@@ -2835,7 +2918,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2835 | continue; | 2918 | continue; |
2836 | } | 2919 | } |
2837 | 2920 | ||
2838 | rx.sta = sta_info_get_bss(prev, hdr->addr2); | 2921 | rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); |
2839 | rx.sdata = prev; | 2922 | rx.sdata = prev; |
2840 | ieee80211_prepare_and_rx_handle(&rx, skb, false); | 2923 | ieee80211_prepare_and_rx_handle(&rx, skb, false); |
2841 | 2924 | ||
@@ -2843,7 +2926,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2843 | } | 2926 | } |
2844 | 2927 | ||
2845 | if (prev) { | 2928 | if (prev) { |
2846 | rx.sta = sta_info_get_bss(prev, hdr->addr2); | 2929 | rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); |
2847 | rx.sdata = prev; | 2930 | rx.sdata = prev; |
2848 | 2931 | ||
2849 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) | 2932 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 6f09eca01112..83a0b050b374 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <linux/pm_qos_params.h> | 17 | #include <linux/pm_qos.h> |
18 | #include <net/sch_generic.h> | 18 | #include <net/sch_generic.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
@@ -254,6 +254,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
254 | req->ie, req->ie_len, band, | 254 | req->ie, req->ie_len, band, |
255 | req->rates[band], 0); | 255 | req->rates[band], 0); |
256 | local->hw_scan_req->ie_len = ielen; | 256 | local->hw_scan_req->ie_len = ielen; |
257 | local->hw_scan_req->no_cck = req->no_cck; | ||
257 | 258 | ||
258 | return true; | 259 | return true; |
259 | } | 260 | } |
@@ -660,7 +661,8 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
660 | local->scan_req->ssids[i].ssid, | 661 | local->scan_req->ssids[i].ssid, |
661 | local->scan_req->ssids[i].ssid_len, | 662 | local->scan_req->ssids[i].ssid_len, |
662 | local->scan_req->ie, local->scan_req->ie_len, | 663 | local->scan_req->ie, local->scan_req->ie_len, |
663 | local->scan_req->rates[band], false); | 664 | local->scan_req->rates[band], false, |
665 | local->scan_req->no_cck); | ||
664 | 666 | ||
665 | /* | 667 | /* |
666 | * After sending probe requests, wait for probe responses | 668 | * After sending probe requests, wait for probe responses |
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 7733f66ee2c4..578eea3fc04d 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -32,12 +32,8 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da | |||
32 | 32 | ||
33 | skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + | 33 | skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + |
34 | sizeof(struct ieee80211_msrment_ie)); | 34 | sizeof(struct ieee80211_msrment_ie)); |
35 | 35 | if (!skb) | |
36 | if (!skb) { | ||
37 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
38 | "measurement report frame\n", sdata->name); | ||
39 | return; | 36 | return; |
40 | } | ||
41 | 37 | ||
42 | skb_reserve(skb, local->hw.extra_tx_headroom); | 38 | skb_reserve(skb, local->hw.extra_tx_headroom); |
43 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); | 39 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 21070e9bc8d0..ce962d2c8782 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "sta_info.h" | 24 | #include "sta_info.h" |
25 | #include "debugfs_sta.h" | 25 | #include "debugfs_sta.h" |
26 | #include "mesh.h" | 26 | #include "mesh.h" |
27 | #include "wme.h" | ||
27 | 28 | ||
28 | /** | 29 | /** |
29 | * DOC: STA information lifetime rules | 30 | * DOC: STA information lifetime rules |
@@ -72,7 +73,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
72 | if (!s) | 73 | if (!s) |
73 | return -ENOENT; | 74 | return -ENOENT; |
74 | if (s == sta) { | 75 | if (s == sta) { |
75 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], | 76 | RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], |
76 | s->hnext); | 77 | s->hnext); |
77 | return 0; | 78 | return 0; |
78 | } | 79 | } |
@@ -82,7 +83,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
82 | s = rcu_dereference_protected(s->hnext, | 83 | s = rcu_dereference_protected(s->hnext, |
83 | lockdep_is_held(&local->sta_lock)); | 84 | lockdep_is_held(&local->sta_lock)); |
84 | if (rcu_access_pointer(s->hnext)) { | 85 | if (rcu_access_pointer(s->hnext)) { |
85 | rcu_assign_pointer(s->hnext, sta->hnext); | 86 | RCU_INIT_POINTER(s->hnext, sta->hnext); |
86 | return 0; | 87 | return 0; |
87 | } | 88 | } |
88 | 89 | ||
@@ -100,6 +101,27 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
100 | lockdep_is_held(&local->sta_lock) || | 101 | lockdep_is_held(&local->sta_lock) || |
101 | lockdep_is_held(&local->sta_mtx)); | 102 | lockdep_is_held(&local->sta_mtx)); |
102 | while (sta) { | 103 | while (sta) { |
104 | if (sta->sdata == sdata && !sta->dummy && | ||
105 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
106 | break; | ||
107 | sta = rcu_dereference_check(sta->hnext, | ||
108 | lockdep_is_held(&local->sta_lock) || | ||
109 | lockdep_is_held(&local->sta_mtx)); | ||
110 | } | ||
111 | return sta; | ||
112 | } | ||
113 | |||
114 | /* get a station info entry even if it is a dummy station*/ | ||
115 | struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | ||
116 | const u8 *addr) | ||
117 | { | ||
118 | struct ieee80211_local *local = sdata->local; | ||
119 | struct sta_info *sta; | ||
120 | |||
121 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | ||
122 | lockdep_is_held(&local->sta_lock) || | ||
123 | lockdep_is_held(&local->sta_mtx)); | ||
124 | while (sta) { | ||
103 | if (sta->sdata == sdata && | 125 | if (sta->sdata == sdata && |
104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 126 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
105 | break; | 127 | break; |
@@ -126,6 +148,32 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
126 | while (sta) { | 148 | while (sta) { |
127 | if ((sta->sdata == sdata || | 149 | if ((sta->sdata == sdata || |
128 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && | 150 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && |
151 | !sta->dummy && | ||
152 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
153 | break; | ||
154 | sta = rcu_dereference_check(sta->hnext, | ||
155 | lockdep_is_held(&local->sta_lock) || | ||
156 | lockdep_is_held(&local->sta_mtx)); | ||
157 | } | ||
158 | return sta; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Get sta info either from the specified interface | ||
163 | * or from one of its vlans (including dummy stations) | ||
164 | */ | ||
165 | struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | ||
166 | const u8 *addr) | ||
167 | { | ||
168 | struct ieee80211_local *local = sdata->local; | ||
169 | struct sta_info *sta; | ||
170 | |||
171 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | ||
172 | lockdep_is_held(&local->sta_lock) || | ||
173 | lockdep_is_held(&local->sta_mtx)); | ||
174 | while (sta) { | ||
175 | if ((sta->sdata == sdata || | ||
176 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && | ||
129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 177 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
130 | break; | 178 | break; |
131 | sta = rcu_dereference_check(sta->hnext, | 179 | sta = rcu_dereference_check(sta->hnext, |
@@ -184,7 +232,7 @@ static void sta_info_hash_add(struct ieee80211_local *local, | |||
184 | struct sta_info *sta) | 232 | struct sta_info *sta) |
185 | { | 233 | { |
186 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; | 234 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; |
187 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); | 235 | RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta); |
188 | } | 236 | } |
189 | 237 | ||
190 | static void sta_unblock(struct work_struct *wk) | 238 | static void sta_unblock(struct work_struct *wk) |
@@ -196,13 +244,22 @@ static void sta_unblock(struct work_struct *wk) | |||
196 | if (sta->dead) | 244 | if (sta->dead) |
197 | return; | 245 | return; |
198 | 246 | ||
199 | if (!test_sta_flags(sta, WLAN_STA_PS_STA)) | 247 | if (!test_sta_flag(sta, WLAN_STA_PS_STA)) |
200 | ieee80211_sta_ps_deliver_wakeup(sta); | 248 | ieee80211_sta_ps_deliver_wakeup(sta); |
201 | else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) { | 249 | else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) { |
202 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER); | 250 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); |
251 | |||
252 | local_bh_disable(); | ||
203 | ieee80211_sta_ps_deliver_poll_response(sta); | 253 | ieee80211_sta_ps_deliver_poll_response(sta); |
254 | local_bh_enable(); | ||
255 | } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) { | ||
256 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
257 | |||
258 | local_bh_disable(); | ||
259 | ieee80211_sta_ps_deliver_uapsd(sta); | ||
260 | local_bh_enable(); | ||
204 | } else | 261 | } else |
205 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER); | 262 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); |
206 | } | 263 | } |
207 | 264 | ||
208 | static int sta_prepare_rate_control(struct ieee80211_local *local, | 265 | static int sta_prepare_rate_control(struct ieee80211_local *local, |
@@ -235,7 +292,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
235 | return NULL; | 292 | return NULL; |
236 | 293 | ||
237 | spin_lock_init(&sta->lock); | 294 | spin_lock_init(&sta->lock); |
238 | spin_lock_init(&sta->flaglock); | ||
239 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | 295 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); |
240 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | 296 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); |
241 | mutex_init(&sta->ampdu_mlme.mtx); | 297 | mutex_init(&sta->ampdu_mlme.mtx); |
@@ -262,8 +318,10 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
262 | */ | 318 | */ |
263 | sta->timer_to_tid[i] = i; | 319 | sta->timer_to_tid[i] = i; |
264 | } | 320 | } |
265 | skb_queue_head_init(&sta->ps_tx_buf); | 321 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
266 | skb_queue_head_init(&sta->tx_filtered); | 322 | skb_queue_head_init(&sta->ps_tx_buf[i]); |
323 | skb_queue_head_init(&sta->tx_filtered[i]); | ||
324 | } | ||
267 | 325 | ||
268 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 326 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) |
269 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); | 327 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); |
@@ -280,7 +338,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
280 | return sta; | 338 | return sta; |
281 | } | 339 | } |
282 | 340 | ||
283 | static int sta_info_finish_insert(struct sta_info *sta, bool async) | 341 | static int sta_info_finish_insert(struct sta_info *sta, |
342 | bool async, bool dummy_reinsert) | ||
284 | { | 343 | { |
285 | struct ieee80211_local *local = sta->local; | 344 | struct ieee80211_local *local = sta->local; |
286 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 345 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -290,50 +349,58 @@ static int sta_info_finish_insert(struct sta_info *sta, bool async) | |||
290 | 349 | ||
291 | lockdep_assert_held(&local->sta_mtx); | 350 | lockdep_assert_held(&local->sta_mtx); |
292 | 351 | ||
293 | /* notify driver */ | 352 | if (!sta->dummy || dummy_reinsert) { |
294 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 353 | /* notify driver */ |
295 | sdata = container_of(sdata->bss, | 354 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
296 | struct ieee80211_sub_if_data, | 355 | sdata = container_of(sdata->bss, |
297 | u.ap); | 356 | struct ieee80211_sub_if_data, |
298 | err = drv_sta_add(local, sdata, &sta->sta); | 357 | u.ap); |
299 | if (err) { | 358 | err = drv_sta_add(local, sdata, &sta->sta); |
300 | if (!async) | 359 | if (err) { |
301 | return err; | 360 | if (!async) |
302 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" | 361 | return err; |
303 | " - keeping it anyway.\n", | 362 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " |
304 | sdata->name, sta->sta.addr, err); | 363 | "driver (%d) - keeping it anyway.\n", |
305 | } else { | 364 | sdata->name, sta->sta.addr, err); |
306 | sta->uploaded = true; | 365 | } else { |
366 | sta->uploaded = true; | ||
307 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 367 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
308 | if (async) | 368 | if (async) |
309 | wiphy_debug(local->hw.wiphy, | 369 | wiphy_debug(local->hw.wiphy, |
310 | "Finished adding IBSS STA %pM\n", | 370 | "Finished adding IBSS STA %pM\n", |
311 | sta->sta.addr); | 371 | sta->sta.addr); |
312 | #endif | 372 | #endif |
373 | } | ||
374 | |||
375 | sdata = sta->sdata; | ||
313 | } | 376 | } |
314 | 377 | ||
315 | sdata = sta->sdata; | 378 | if (!dummy_reinsert) { |
379 | if (!async) { | ||
380 | local->num_sta++; | ||
381 | local->sta_generation++; | ||
382 | smp_mb(); | ||
316 | 383 | ||
317 | if (!async) { | 384 | /* make the station visible */ |
318 | local->num_sta++; | 385 | spin_lock_irqsave(&local->sta_lock, flags); |
319 | local->sta_generation++; | 386 | sta_info_hash_add(local, sta); |
320 | smp_mb(); | 387 | spin_unlock_irqrestore(&local->sta_lock, flags); |
388 | } | ||
321 | 389 | ||
322 | /* make the station visible */ | 390 | list_add(&sta->list, &local->sta_list); |
323 | spin_lock_irqsave(&local->sta_lock, flags); | 391 | } else { |
324 | sta_info_hash_add(local, sta); | 392 | sta->dummy = false; |
325 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
326 | } | 393 | } |
327 | 394 | ||
328 | list_add(&sta->list, &local->sta_list); | 395 | if (!sta->dummy) { |
329 | 396 | ieee80211_sta_debugfs_add(sta); | |
330 | ieee80211_sta_debugfs_add(sta); | 397 | rate_control_add_sta_debugfs(sta); |
331 | rate_control_add_sta_debugfs(sta); | ||
332 | |||
333 | sinfo.filled = 0; | ||
334 | sinfo.generation = local->sta_generation; | ||
335 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
336 | 398 | ||
399 | memset(&sinfo, 0, sizeof(sinfo)); | ||
400 | sinfo.filled = 0; | ||
401 | sinfo.generation = local->sta_generation; | ||
402 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
403 | } | ||
337 | 404 | ||
338 | return 0; | 405 | return 0; |
339 | } | 406 | } |
@@ -350,7 +417,7 @@ static void sta_info_finish_pending(struct ieee80211_local *local) | |||
350 | list_del(&sta->list); | 417 | list_del(&sta->list); |
351 | spin_unlock_irqrestore(&local->sta_lock, flags); | 418 | spin_unlock_irqrestore(&local->sta_lock, flags); |
352 | 419 | ||
353 | sta_info_finish_insert(sta, true); | 420 | sta_info_finish_insert(sta, true, false); |
354 | 421 | ||
355 | spin_lock_irqsave(&local->sta_lock, flags); | 422 | spin_lock_irqsave(&local->sta_lock, flags); |
356 | } | 423 | } |
@@ -367,106 +434,117 @@ static void sta_info_finish_work(struct work_struct *work) | |||
367 | mutex_unlock(&local->sta_mtx); | 434 | mutex_unlock(&local->sta_mtx); |
368 | } | 435 | } |
369 | 436 | ||
370 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | 437 | static int sta_info_insert_check(struct sta_info *sta) |
371 | { | 438 | { |
372 | struct ieee80211_local *local = sta->local; | ||
373 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 439 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
374 | unsigned long flags; | ||
375 | int err = 0; | ||
376 | 440 | ||
377 | /* | 441 | /* |
378 | * Can't be a WARN_ON because it can be triggered through a race: | 442 | * Can't be a WARN_ON because it can be triggered through a race: |
379 | * something inserts a STA (on one CPU) without holding the RTNL | 443 | * something inserts a STA (on one CPU) without holding the RTNL |
380 | * and another CPU turns off the net device. | 444 | * and another CPU turns off the net device. |
381 | */ | 445 | */ |
382 | if (unlikely(!ieee80211_sdata_running(sdata))) { | 446 | if (unlikely(!ieee80211_sdata_running(sdata))) |
383 | err = -ENETDOWN; | 447 | return -ENETDOWN; |
384 | rcu_read_lock(); | ||
385 | goto out_free; | ||
386 | } | ||
387 | 448 | ||
388 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || | 449 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || |
389 | is_multicast_ether_addr(sta->sta.addr))) { | 450 | is_multicast_ether_addr(sta->sta.addr))) |
390 | err = -EINVAL; | 451 | return -EINVAL; |
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU) | ||
457 | { | ||
458 | struct ieee80211_local *local = sta->local; | ||
459 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
460 | unsigned long flags; | ||
461 | |||
462 | spin_lock_irqsave(&local->sta_lock, flags); | ||
463 | /* check if STA exists already */ | ||
464 | if (sta_info_get_bss_rx(sdata, sta->sta.addr)) { | ||
465 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
391 | rcu_read_lock(); | 466 | rcu_read_lock(); |
392 | goto out_free; | 467 | return -EEXIST; |
393 | } | 468 | } |
394 | 469 | ||
395 | /* | 470 | local->num_sta++; |
396 | * In ad-hoc mode, we sometimes need to insert stations | 471 | local->sta_generation++; |
397 | * from tasklet context from the RX path. To avoid races, | 472 | smp_mb(); |
398 | * always do so in that case -- see the comment below. | 473 | sta_info_hash_add(local, sta); |
399 | */ | ||
400 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
401 | spin_lock_irqsave(&local->sta_lock, flags); | ||
402 | /* check if STA exists already */ | ||
403 | if (sta_info_get_bss(sdata, sta->sta.addr)) { | ||
404 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
405 | rcu_read_lock(); | ||
406 | err = -EEXIST; | ||
407 | goto out_free; | ||
408 | } | ||
409 | |||
410 | local->num_sta++; | ||
411 | local->sta_generation++; | ||
412 | smp_mb(); | ||
413 | sta_info_hash_add(local, sta); | ||
414 | 474 | ||
415 | list_add_tail(&sta->list, &local->sta_pending_list); | 475 | list_add_tail(&sta->list, &local->sta_pending_list); |
416 | 476 | ||
417 | rcu_read_lock(); | 477 | rcu_read_lock(); |
418 | spin_unlock_irqrestore(&local->sta_lock, flags); | 478 | spin_unlock_irqrestore(&local->sta_lock, flags); |
419 | 479 | ||
420 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 480 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
421 | wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", | 481 | wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", |
422 | sta->sta.addr); | 482 | sta->sta.addr); |
423 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 483 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
424 | 484 | ||
425 | ieee80211_queue_work(&local->hw, &local->sta_finish_work); | 485 | ieee80211_queue_work(&local->hw, &local->sta_finish_work); |
426 | 486 | ||
427 | return 0; | 487 | return 0; |
428 | } | 488 | } |
489 | |||
490 | /* | ||
491 | * should be called with sta_mtx locked | ||
492 | * this function replaces the mutex lock | ||
493 | * with a RCU lock | ||
494 | */ | ||
495 | static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) | ||
496 | { | ||
497 | struct ieee80211_local *local = sta->local; | ||
498 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
499 | unsigned long flags; | ||
500 | struct sta_info *exist_sta; | ||
501 | bool dummy_reinsert = false; | ||
502 | int err = 0; | ||
503 | |||
504 | lockdep_assert_held(&local->sta_mtx); | ||
429 | 505 | ||
430 | /* | 506 | /* |
431 | * On first glance, this will look racy, because the code | 507 | * On first glance, this will look racy, because the code |
432 | * below this point, which inserts a station with sleeping, | 508 | * in this function, which inserts a station with sleeping, |
433 | * unlocks the sta_lock between checking existence in the | 509 | * unlocks the sta_lock between checking existence in the |
434 | * hash table and inserting into it. | 510 | * hash table and inserting into it. |
435 | * | 511 | * |
436 | * However, it is not racy against itself because it keeps | 512 | * However, it is not racy against itself because it keeps |
437 | * the mutex locked. It still seems to race against the | 513 | * the mutex locked. |
438 | * above code that atomically inserts the station... That, | ||
439 | * however, is not true because the above code can only | ||
440 | * be invoked for IBSS interfaces, and the below code will | ||
441 | * not be -- and the two do not race against each other as | ||
442 | * the hash table also keys off the interface. | ||
443 | */ | 514 | */ |
444 | 515 | ||
445 | might_sleep(); | ||
446 | |||
447 | mutex_lock(&local->sta_mtx); | ||
448 | |||
449 | spin_lock_irqsave(&local->sta_lock, flags); | 516 | spin_lock_irqsave(&local->sta_lock, flags); |
450 | /* check if STA exists already */ | 517 | /* |
451 | if (sta_info_get_bss(sdata, sta->sta.addr)) { | 518 | * check if STA exists already. |
452 | spin_unlock_irqrestore(&local->sta_lock, flags); | 519 | * only accept a scenario of a second call to sta_info_insert_non_ibss |
453 | mutex_unlock(&local->sta_mtx); | 520 | * with a dummy station entry that was inserted earlier |
454 | rcu_read_lock(); | 521 | * in that case - assume that the dummy station flag should |
455 | err = -EEXIST; | 522 | * be removed. |
456 | goto out_free; | 523 | */ |
524 | exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr); | ||
525 | if (exist_sta) { | ||
526 | if (exist_sta == sta && sta->dummy) { | ||
527 | dummy_reinsert = true; | ||
528 | } else { | ||
529 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
530 | mutex_unlock(&local->sta_mtx); | ||
531 | rcu_read_lock(); | ||
532 | return -EEXIST; | ||
533 | } | ||
457 | } | 534 | } |
458 | 535 | ||
459 | spin_unlock_irqrestore(&local->sta_lock, flags); | 536 | spin_unlock_irqrestore(&local->sta_lock, flags); |
460 | 537 | ||
461 | err = sta_info_finish_insert(sta, false); | 538 | err = sta_info_finish_insert(sta, false, dummy_reinsert); |
462 | if (err) { | 539 | if (err) { |
463 | mutex_unlock(&local->sta_mtx); | 540 | mutex_unlock(&local->sta_mtx); |
464 | rcu_read_lock(); | 541 | rcu_read_lock(); |
465 | goto out_free; | 542 | return err; |
466 | } | 543 | } |
467 | 544 | ||
468 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 545 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
469 | wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); | 546 | wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", |
547 | sta->dummy ? "dummy " : "", sta->sta.addr); | ||
470 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 548 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
471 | 549 | ||
472 | /* move reference to rcu-protected */ | 550 | /* move reference to rcu-protected */ |
@@ -477,6 +555,51 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | |||
477 | mesh_accept_plinks_update(sdata); | 555 | mesh_accept_plinks_update(sdata); |
478 | 556 | ||
479 | return 0; | 557 | return 0; |
558 | } | ||
559 | |||
560 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | ||
561 | { | ||
562 | struct ieee80211_local *local = sta->local; | ||
563 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
564 | int err = 0; | ||
565 | |||
566 | err = sta_info_insert_check(sta); | ||
567 | if (err) { | ||
568 | rcu_read_lock(); | ||
569 | goto out_free; | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * In ad-hoc mode, we sometimes need to insert stations | ||
574 | * from tasklet context from the RX path. To avoid races, | ||
575 | * always do so in that case -- see the comment below. | ||
576 | */ | ||
577 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
578 | err = sta_info_insert_ibss(sta); | ||
579 | if (err) | ||
580 | goto out_free; | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | /* | ||
586 | * It might seem that the function called below is in race against | ||
587 | * the function call above that atomically inserts the station... That, | ||
588 | * however, is not true because the above code can only | ||
589 | * be invoked for IBSS interfaces, and the below code will | ||
590 | * not be -- and the two do not race against each other as | ||
591 | * the hash table also keys off the interface. | ||
592 | */ | ||
593 | |||
594 | might_sleep(); | ||
595 | |||
596 | mutex_lock(&local->sta_mtx); | ||
597 | |||
598 | err = sta_info_insert_non_ibss(sta); | ||
599 | if (err) | ||
600 | goto out_free; | ||
601 | |||
602 | return 0; | ||
480 | out_free: | 603 | out_free: |
481 | BUG_ON(!err); | 604 | BUG_ON(!err); |
482 | __sta_info_free(local, sta); | 605 | __sta_info_free(local, sta); |
@@ -492,6 +615,25 @@ int sta_info_insert(struct sta_info *sta) | |||
492 | return err; | 615 | return err; |
493 | } | 616 | } |
494 | 617 | ||
618 | /* Caller must hold sta->local->sta_mtx */ | ||
619 | int sta_info_reinsert(struct sta_info *sta) | ||
620 | { | ||
621 | struct ieee80211_local *local = sta->local; | ||
622 | int err = 0; | ||
623 | |||
624 | err = sta_info_insert_check(sta); | ||
625 | if (err) { | ||
626 | mutex_unlock(&local->sta_mtx); | ||
627 | return err; | ||
628 | } | ||
629 | |||
630 | might_sleep(); | ||
631 | |||
632 | err = sta_info_insert_non_ibss(sta); | ||
633 | rcu_read_unlock(); | ||
634 | return err; | ||
635 | } | ||
636 | |||
495 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) | 637 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) |
496 | { | 638 | { |
497 | /* | 639 | /* |
@@ -510,64 +652,93 @@ static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) | |||
510 | bss->tim[aid / 8] &= ~(1 << (aid % 8)); | 652 | bss->tim[aid / 8] &= ~(1 << (aid % 8)); |
511 | } | 653 | } |
512 | 654 | ||
513 | static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | 655 | static unsigned long ieee80211_tids_for_ac(int ac) |
514 | struct sta_info *sta) | ||
515 | { | 656 | { |
516 | BUG_ON(!bss); | 657 | /* If we ever support TIDs > 7, this obviously needs to be adjusted */ |
517 | 658 | switch (ac) { | |
518 | __bss_tim_set(bss, sta->sta.aid); | 659 | case IEEE80211_AC_VO: |
519 | 660 | return BIT(6) | BIT(7); | |
520 | if (sta->local->ops->set_tim) { | 661 | case IEEE80211_AC_VI: |
521 | sta->local->tim_in_locked_section = true; | 662 | return BIT(4) | BIT(5); |
522 | drv_set_tim(sta->local, &sta->sta, true); | 663 | case IEEE80211_AC_BE: |
523 | sta->local->tim_in_locked_section = false; | 664 | return BIT(0) | BIT(3); |
665 | case IEEE80211_AC_BK: | ||
666 | return BIT(1) | BIT(2); | ||
667 | default: | ||
668 | WARN_ON(1); | ||
669 | return 0; | ||
524 | } | 670 | } |
525 | } | 671 | } |
526 | 672 | ||
527 | void sta_info_set_tim_bit(struct sta_info *sta) | 673 | void sta_info_recalc_tim(struct sta_info *sta) |
528 | { | 674 | { |
675 | struct ieee80211_local *local = sta->local; | ||
676 | struct ieee80211_if_ap *bss = sta->sdata->bss; | ||
529 | unsigned long flags; | 677 | unsigned long flags; |
678 | bool indicate_tim = false; | ||
679 | u8 ignore_for_tim = sta->sta.uapsd_queues; | ||
680 | int ac; | ||
530 | 681 | ||
531 | BUG_ON(!sta->sdata->bss); | 682 | if (WARN_ON_ONCE(!sta->sdata->bss)) |
683 | return; | ||
532 | 684 | ||
533 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 685 | /* No need to do anything if the driver does all */ |
534 | __sta_info_set_tim_bit(sta->sdata->bss, sta); | 686 | if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) |
535 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 687 | return; |
536 | } | ||
537 | 688 | ||
538 | static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | 689 | if (sta->dead) |
539 | struct sta_info *sta) | 690 | goto done; |
540 | { | 691 | |
541 | BUG_ON(!bss); | 692 | /* |
693 | * If all ACs are delivery-enabled then we should build | ||
694 | * the TIM bit for all ACs anyway; if only some are then | ||
695 | * we ignore those and build the TIM bit using only the | ||
696 | * non-enabled ones. | ||
697 | */ | ||
698 | if (ignore_for_tim == BIT(IEEE80211_NUM_ACS) - 1) | ||
699 | ignore_for_tim = 0; | ||
700 | |||
701 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
702 | unsigned long tids; | ||
542 | 703 | ||
543 | __bss_tim_clear(bss, sta->sta.aid); | 704 | if (ignore_for_tim & BIT(ac)) |
705 | continue; | ||
706 | |||
707 | indicate_tim |= !skb_queue_empty(&sta->tx_filtered[ac]) || | ||
708 | !skb_queue_empty(&sta->ps_tx_buf[ac]); | ||
709 | if (indicate_tim) | ||
710 | break; | ||
544 | 711 | ||
545 | if (sta->local->ops->set_tim) { | 712 | tids = ieee80211_tids_for_ac(ac); |
546 | sta->local->tim_in_locked_section = true; | 713 | |
547 | drv_set_tim(sta->local, &sta->sta, false); | 714 | indicate_tim |= |
548 | sta->local->tim_in_locked_section = false; | 715 | sta->driver_buffered_tids & tids; |
549 | } | 716 | } |
550 | } | ||
551 | 717 | ||
552 | void sta_info_clear_tim_bit(struct sta_info *sta) | 718 | done: |
553 | { | 719 | spin_lock_irqsave(&local->sta_lock, flags); |
554 | unsigned long flags; | ||
555 | 720 | ||
556 | BUG_ON(!sta->sdata->bss); | 721 | if (indicate_tim) |
722 | __bss_tim_set(bss, sta->sta.aid); | ||
723 | else | ||
724 | __bss_tim_clear(bss, sta->sta.aid); | ||
557 | 725 | ||
558 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 726 | if (local->ops->set_tim) { |
559 | __sta_info_clear_tim_bit(sta->sdata->bss, sta); | 727 | local->tim_in_locked_section = true; |
560 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 728 | drv_set_tim(local, &sta->sta, indicate_tim); |
729 | local->tim_in_locked_section = false; | ||
730 | } | ||
731 | |||
732 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
561 | } | 733 | } |
562 | 734 | ||
563 | static int sta_info_buffer_expired(struct sta_info *sta, | 735 | static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) |
564 | struct sk_buff *skb) | ||
565 | { | 736 | { |
566 | struct ieee80211_tx_info *info; | 737 | struct ieee80211_tx_info *info; |
567 | int timeout; | 738 | int timeout; |
568 | 739 | ||
569 | if (!skb) | 740 | if (!skb) |
570 | return 0; | 741 | return false; |
571 | 742 | ||
572 | info = IEEE80211_SKB_CB(skb); | 743 | info = IEEE80211_SKB_CB(skb); |
573 | 744 | ||
@@ -581,24 +752,59 @@ static int sta_info_buffer_expired(struct sta_info *sta, | |||
581 | } | 752 | } |
582 | 753 | ||
583 | 754 | ||
584 | static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | 755 | static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, |
585 | struct sta_info *sta) | 756 | struct sta_info *sta, int ac) |
586 | { | 757 | { |
587 | unsigned long flags; | 758 | unsigned long flags; |
588 | struct sk_buff *skb; | 759 | struct sk_buff *skb; |
589 | 760 | ||
590 | if (skb_queue_empty(&sta->ps_tx_buf)) | 761 | /* |
591 | return false; | 762 | * First check for frames that should expire on the filtered |
763 | * queue. Frames here were rejected by the driver and are on | ||
764 | * a separate queue to avoid reordering with normal PS-buffered | ||
765 | * frames. They also aren't accounted for right now in the | ||
766 | * total_ps_buffered counter. | ||
767 | */ | ||
768 | for (;;) { | ||
769 | spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); | ||
770 | skb = skb_peek(&sta->tx_filtered[ac]); | ||
771 | if (sta_info_buffer_expired(sta, skb)) | ||
772 | skb = __skb_dequeue(&sta->tx_filtered[ac]); | ||
773 | else | ||
774 | skb = NULL; | ||
775 | spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); | ||
592 | 776 | ||
777 | /* | ||
778 | * Frames are queued in order, so if this one | ||
779 | * hasn't expired yet we can stop testing. If | ||
780 | * we actually reached the end of the queue we | ||
781 | * also need to stop, of course. | ||
782 | */ | ||
783 | if (!skb) | ||
784 | break; | ||
785 | dev_kfree_skb(skb); | ||
786 | } | ||
787 | |||
788 | /* | ||
789 | * Now also check the normal PS-buffered queue, this will | ||
790 | * only find something if the filtered queue was emptied | ||
791 | * since the filtered frames are all before the normal PS | ||
792 | * buffered frames. | ||
793 | */ | ||
593 | for (;;) { | 794 | for (;;) { |
594 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); | 795 | spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); |
595 | skb = skb_peek(&sta->ps_tx_buf); | 796 | skb = skb_peek(&sta->ps_tx_buf[ac]); |
596 | if (sta_info_buffer_expired(sta, skb)) | 797 | if (sta_info_buffer_expired(sta, skb)) |
597 | skb = __skb_dequeue(&sta->ps_tx_buf); | 798 | skb = __skb_dequeue(&sta->ps_tx_buf[ac]); |
598 | else | 799 | else |
599 | skb = NULL; | 800 | skb = NULL; |
600 | spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags); | 801 | spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); |
601 | 802 | ||
803 | /* | ||
804 | * frames are queued in order, so if this one | ||
805 | * hasn't expired yet (or we reached the end of | ||
806 | * the queue) we can stop testing | ||
807 | */ | ||
602 | if (!skb) | 808 | if (!skb) |
603 | break; | 809 | break; |
604 | 810 | ||
@@ -608,22 +814,47 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
608 | sta->sta.addr); | 814 | sta->sta.addr); |
609 | #endif | 815 | #endif |
610 | dev_kfree_skb(skb); | 816 | dev_kfree_skb(skb); |
611 | |||
612 | if (skb_queue_empty(&sta->ps_tx_buf) && | ||
613 | !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF)) | ||
614 | sta_info_clear_tim_bit(sta); | ||
615 | } | 817 | } |
616 | 818 | ||
617 | return true; | 819 | /* |
820 | * Finally, recalculate the TIM bit for this station -- it might | ||
821 | * now be clear because the station was too slow to retrieve its | ||
822 | * frames. | ||
823 | */ | ||
824 | sta_info_recalc_tim(sta); | ||
825 | |||
826 | /* | ||
827 | * Return whether there are any frames still buffered, this is | ||
828 | * used to check whether the cleanup timer still needs to run, | ||
829 | * if there are no frames we don't need to rearm the timer. | ||
830 | */ | ||
831 | return !(skb_queue_empty(&sta->ps_tx_buf[ac]) && | ||
832 | skb_queue_empty(&sta->tx_filtered[ac])); | ||
833 | } | ||
834 | |||
835 | static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | ||
836 | struct sta_info *sta) | ||
837 | { | ||
838 | bool have_buffered = false; | ||
839 | int ac; | ||
840 | |||
841 | /* This is only necessary for stations on BSS interfaces */ | ||
842 | if (!sta->sdata->bss) | ||
843 | return false; | ||
844 | |||
845 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
846 | have_buffered |= | ||
847 | sta_info_cleanup_expire_buffered_ac(local, sta, ac); | ||
848 | |||
849 | return have_buffered; | ||
618 | } | 850 | } |
619 | 851 | ||
620 | static int __must_check __sta_info_destroy(struct sta_info *sta) | 852 | static int __must_check __sta_info_destroy(struct sta_info *sta) |
621 | { | 853 | { |
622 | struct ieee80211_local *local; | 854 | struct ieee80211_local *local; |
623 | struct ieee80211_sub_if_data *sdata; | 855 | struct ieee80211_sub_if_data *sdata; |
624 | struct sk_buff *skb; | ||
625 | unsigned long flags; | 856 | unsigned long flags; |
626 | int ret, i; | 857 | int ret, i, ac; |
627 | 858 | ||
628 | might_sleep(); | 859 | might_sleep(); |
629 | 860 | ||
@@ -639,7 +870,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
639 | * sessions -- block that to make sure the tear-down | 870 | * sessions -- block that to make sure the tear-down |
640 | * will be sufficient. | 871 | * will be sufficient. |
641 | */ | 872 | */ |
642 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 873 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
643 | ieee80211_sta_tear_down_BA_sessions(sta, true); | 874 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
644 | 875 | ||
645 | spin_lock_irqsave(&local->sta_lock, flags); | 876 | spin_lock_irqsave(&local->sta_lock, flags); |
@@ -660,19 +891,22 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
660 | 891 | ||
661 | sta->dead = true; | 892 | sta->dead = true; |
662 | 893 | ||
663 | if (test_and_clear_sta_flags(sta, | 894 | if (test_sta_flag(sta, WLAN_STA_PS_STA) || |
664 | WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { | 895 | test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { |
665 | BUG_ON(!sdata->bss); | 896 | BUG_ON(!sdata->bss); |
666 | 897 | ||
898 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
899 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
900 | |||
667 | atomic_dec(&sdata->bss->num_sta_ps); | 901 | atomic_dec(&sdata->bss->num_sta_ps); |
668 | sta_info_clear_tim_bit(sta); | 902 | sta_info_recalc_tim(sta); |
669 | } | 903 | } |
670 | 904 | ||
671 | local->num_sta--; | 905 | local->num_sta--; |
672 | local->sta_generation++; | 906 | local->sta_generation++; |
673 | 907 | ||
674 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 908 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
675 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | 909 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); |
676 | 910 | ||
677 | if (sta->uploaded) { | 911 | if (sta->uploaded) { |
678 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 912 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -691,6 +925,12 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
691 | */ | 925 | */ |
692 | synchronize_rcu(); | 926 | synchronize_rcu(); |
693 | 927 | ||
928 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
929 | local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); | ||
930 | __skb_queue_purge(&sta->ps_tx_buf[ac]); | ||
931 | __skb_queue_purge(&sta->tx_filtered[ac]); | ||
932 | } | ||
933 | |||
694 | #ifdef CONFIG_MAC80211_MESH | 934 | #ifdef CONFIG_MAC80211_MESH |
695 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 935 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
696 | mesh_accept_plinks_update(sdata); | 936 | mesh_accept_plinks_update(sdata); |
@@ -713,14 +953,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
713 | } | 953 | } |
714 | #endif | 954 | #endif |
715 | 955 | ||
716 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
717 | local->total_ps_buffered--; | ||
718 | dev_kfree_skb_any(skb); | ||
719 | } | ||
720 | |||
721 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | ||
722 | dev_kfree_skb_any(skb); | ||
723 | |||
724 | __sta_info_free(local, sta); | 956 | __sta_info_free(local, sta); |
725 | 957 | ||
726 | return 0; | 958 | return 0; |
@@ -732,7 +964,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) | |||
732 | int ret; | 964 | int ret; |
733 | 965 | ||
734 | mutex_lock(&sdata->local->sta_mtx); | 966 | mutex_lock(&sdata->local->sta_mtx); |
735 | sta = sta_info_get(sdata, addr); | 967 | sta = sta_info_get_rx(sdata, addr); |
736 | ret = __sta_info_destroy(sta); | 968 | ret = __sta_info_destroy(sta); |
737 | mutex_unlock(&sdata->local->sta_mtx); | 969 | mutex_unlock(&sdata->local->sta_mtx); |
738 | 970 | ||
@@ -746,7 +978,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, | |||
746 | int ret; | 978 | int ret; |
747 | 979 | ||
748 | mutex_lock(&sdata->local->sta_mtx); | 980 | mutex_lock(&sdata->local->sta_mtx); |
749 | sta = sta_info_get_bss(sdata, addr); | 981 | sta = sta_info_get_bss_rx(sdata, addr); |
750 | ret = __sta_info_destroy(sta); | 982 | ret = __sta_info_destroy(sta); |
751 | mutex_unlock(&sdata->local->sta_mtx); | 983 | mutex_unlock(&sdata->local->sta_mtx); |
752 | 984 | ||
@@ -886,7 +1118,8 @@ static void clear_sta_ps_flags(void *_sta) | |||
886 | { | 1118 | { |
887 | struct sta_info *sta = _sta; | 1119 | struct sta_info *sta = _sta; |
888 | 1120 | ||
889 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER | WLAN_STA_PS_STA); | 1121 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); |
1122 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
890 | } | 1123 | } |
891 | 1124 | ||
892 | /* powersave support code */ | 1125 | /* powersave support code */ |
@@ -894,88 +1127,341 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
894 | { | 1127 | { |
895 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1128 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
896 | struct ieee80211_local *local = sdata->local; | 1129 | struct ieee80211_local *local = sdata->local; |
897 | int sent, buffered; | 1130 | struct sk_buff_head pending; |
1131 | int filtered = 0, buffered = 0, ac; | ||
1132 | |||
1133 | clear_sta_flag(sta, WLAN_STA_SP); | ||
1134 | |||
1135 | BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1); | ||
1136 | sta->driver_buffered_tids = 0; | ||
898 | 1137 | ||
899 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); | ||
900 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) | 1138 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
901 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); | 1139 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); |
902 | 1140 | ||
903 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 1141 | skb_queue_head_init(&pending); |
904 | sta_info_clear_tim_bit(sta); | ||
905 | 1142 | ||
906 | /* Send all buffered frames to the station */ | 1143 | /* Send all buffered frames to the station */ |
907 | sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); | 1144 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
908 | buffered = ieee80211_add_pending_skbs_fn(local, &sta->ps_tx_buf, | 1145 | int count = skb_queue_len(&pending), tmp; |
909 | clear_sta_ps_flags, sta); | 1146 | |
910 | sent += buffered; | 1147 | skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); |
1148 | tmp = skb_queue_len(&pending); | ||
1149 | filtered += tmp - count; | ||
1150 | count = tmp; | ||
1151 | |||
1152 | skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); | ||
1153 | tmp = skb_queue_len(&pending); | ||
1154 | buffered += tmp - count; | ||
1155 | } | ||
1156 | |||
1157 | ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); | ||
1158 | |||
911 | local->total_ps_buffered -= buffered; | 1159 | local->total_ps_buffered -= buffered; |
912 | 1160 | ||
1161 | sta_info_recalc_tim(sta); | ||
1162 | |||
913 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1163 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
914 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " | 1164 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " |
915 | "since STA not sleeping anymore\n", sdata->name, | 1165 | "since STA not sleeping anymore\n", sdata->name, |
916 | sta->sta.addr, sta->sta.aid, sent - buffered, buffered); | 1166 | sta->sta.addr, sta->sta.aid, filtered, buffered); |
917 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1167 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
918 | } | 1168 | } |
919 | 1169 | ||
920 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | 1170 | static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, |
1171 | struct sta_info *sta, int tid, | ||
1172 | enum ieee80211_frame_release_type reason) | ||
921 | { | 1173 | { |
922 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
923 | struct ieee80211_local *local = sdata->local; | 1174 | struct ieee80211_local *local = sdata->local; |
1175 | struct ieee80211_qos_hdr *nullfunc; | ||
924 | struct sk_buff *skb; | 1176 | struct sk_buff *skb; |
925 | int no_pending_pkts; | 1177 | int size = sizeof(*nullfunc); |
1178 | __le16 fc; | ||
1179 | bool qos = test_sta_flag(sta, WLAN_STA_WME); | ||
1180 | struct ieee80211_tx_info *info; | ||
926 | 1181 | ||
927 | skb = skb_dequeue(&sta->tx_filtered); | 1182 | if (qos) { |
928 | if (!skb) { | 1183 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | |
929 | skb = skb_dequeue(&sta->ps_tx_buf); | 1184 | IEEE80211_STYPE_QOS_NULLFUNC | |
930 | if (skb) | 1185 | IEEE80211_FCTL_FROMDS); |
931 | local->total_ps_buffered--; | 1186 | } else { |
1187 | size -= 2; | ||
1188 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
1189 | IEEE80211_STYPE_NULLFUNC | | ||
1190 | IEEE80211_FCTL_FROMDS); | ||
1191 | } | ||
1192 | |||
1193 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + size); | ||
1194 | if (!skb) | ||
1195 | return; | ||
1196 | |||
1197 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1198 | |||
1199 | nullfunc = (void *) skb_put(skb, size); | ||
1200 | nullfunc->frame_control = fc; | ||
1201 | nullfunc->duration_id = 0; | ||
1202 | memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); | ||
1203 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); | ||
1204 | memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); | ||
1205 | |||
1206 | skb->priority = tid; | ||
1207 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); | ||
1208 | if (qos) { | ||
1209 | nullfunc->qos_ctrl = cpu_to_le16(tid); | ||
1210 | |||
1211 | if (reason == IEEE80211_FRAME_RELEASE_UAPSD) | ||
1212 | nullfunc->qos_ctrl |= | ||
1213 | cpu_to_le16(IEEE80211_QOS_CTL_EOSP); | ||
932 | } | 1214 | } |
933 | no_pending_pkts = skb_queue_empty(&sta->tx_filtered) && | ||
934 | skb_queue_empty(&sta->ps_tx_buf); | ||
935 | 1215 | ||
936 | if (skb) { | 1216 | info = IEEE80211_SKB_CB(skb); |
937 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1217 | |
938 | struct ieee80211_hdr *hdr = | 1218 | /* |
939 | (struct ieee80211_hdr *) skb->data; | 1219 | * Tell TX path to send this frame even though the |
1220 | * STA may still remain is PS mode after this frame | ||
1221 | * exchange. Also set EOSP to indicate this packet | ||
1222 | * ends the poll/service period. | ||
1223 | */ | ||
1224 | info->flags |= IEEE80211_TX_CTL_POLL_RESPONSE | | ||
1225 | IEEE80211_TX_STATUS_EOSP | | ||
1226 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1227 | |||
1228 | drv_allow_buffered_frames(local, sta, BIT(tid), 1, reason, false); | ||
1229 | |||
1230 | ieee80211_xmit(sdata, skb); | ||
1231 | } | ||
1232 | |||
1233 | static void | ||
1234 | ieee80211_sta_ps_deliver_response(struct sta_info *sta, | ||
1235 | int n_frames, u8 ignored_acs, | ||
1236 | enum ieee80211_frame_release_type reason) | ||
1237 | { | ||
1238 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
1239 | struct ieee80211_local *local = sdata->local; | ||
1240 | bool found = false; | ||
1241 | bool more_data = false; | ||
1242 | int ac; | ||
1243 | unsigned long driver_release_tids = 0; | ||
1244 | struct sk_buff_head frames; | ||
1245 | |||
1246 | /* Service or PS-Poll period starts */ | ||
1247 | set_sta_flag(sta, WLAN_STA_SP); | ||
1248 | |||
1249 | __skb_queue_head_init(&frames); | ||
1250 | |||
1251 | /* | ||
1252 | * Get response frame(s) and more data bit for it. | ||
1253 | */ | ||
1254 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
1255 | unsigned long tids; | ||
1256 | |||
1257 | if (ignored_acs & BIT(ac)) | ||
1258 | continue; | ||
1259 | |||
1260 | tids = ieee80211_tids_for_ac(ac); | ||
1261 | |||
1262 | if (!found) { | ||
1263 | driver_release_tids = sta->driver_buffered_tids & tids; | ||
1264 | if (driver_release_tids) { | ||
1265 | found = true; | ||
1266 | } else { | ||
1267 | struct sk_buff *skb; | ||
1268 | |||
1269 | while (n_frames > 0) { | ||
1270 | skb = skb_dequeue(&sta->tx_filtered[ac]); | ||
1271 | if (!skb) { | ||
1272 | skb = skb_dequeue( | ||
1273 | &sta->ps_tx_buf[ac]); | ||
1274 | if (skb) | ||
1275 | local->total_ps_buffered--; | ||
1276 | } | ||
1277 | if (!skb) | ||
1278 | break; | ||
1279 | n_frames--; | ||
1280 | found = true; | ||
1281 | __skb_queue_tail(&frames, skb); | ||
1282 | } | ||
1283 | } | ||
1284 | |||
1285 | /* | ||
1286 | * If the driver has data on more than one TID then | ||
1287 | * certainly there's more data if we release just a | ||
1288 | * single frame now (from a single TID). | ||
1289 | */ | ||
1290 | if (reason == IEEE80211_FRAME_RELEASE_PSPOLL && | ||
1291 | hweight16(driver_release_tids) > 1) { | ||
1292 | more_data = true; | ||
1293 | driver_release_tids = | ||
1294 | BIT(ffs(driver_release_tids) - 1); | ||
1295 | break; | ||
1296 | } | ||
1297 | } | ||
1298 | |||
1299 | if (!skb_queue_empty(&sta->tx_filtered[ac]) || | ||
1300 | !skb_queue_empty(&sta->ps_tx_buf[ac])) { | ||
1301 | more_data = true; | ||
1302 | break; | ||
1303 | } | ||
1304 | } | ||
1305 | |||
1306 | if (!found) { | ||
1307 | int tid; | ||
940 | 1308 | ||
941 | /* | 1309 | /* |
942 | * Tell TX path to send this frame even though the STA may | 1310 | * For PS-Poll, this can only happen due to a race condition |
943 | * still remain is PS mode after this frame exchange. | 1311 | * when we set the TIM bit and the station notices it, but |
1312 | * before it can poll for the frame we expire it. | ||
1313 | * | ||
1314 | * For uAPSD, this is said in the standard (11.2.1.5 h): | ||
1315 | * At each unscheduled SP for a non-AP STA, the AP shall | ||
1316 | * attempt to transmit at least one MSDU or MMPDU, but no | ||
1317 | * more than the value specified in the Max SP Length field | ||
1318 | * in the QoS Capability element from delivery-enabled ACs, | ||
1319 | * that are destined for the non-AP STA. | ||
1320 | * | ||
1321 | * Since we have no other MSDU/MMPDU, transmit a QoS null frame. | ||
944 | */ | 1322 | */ |
945 | info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE; | ||
946 | 1323 | ||
947 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1324 | /* This will evaluate to 1, 3, 5 or 7. */ |
948 | printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n", | 1325 | tid = 7 - ((ffs(~ignored_acs) - 1) << 1); |
949 | sta->sta.addr, sta->sta.aid, | ||
950 | skb_queue_len(&sta->ps_tx_buf)); | ||
951 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | ||
952 | 1326 | ||
953 | /* Use MoreData flag to indicate whether there are more | 1327 | ieee80211_send_null_response(sdata, sta, tid, reason); |
954 | * buffered frames for this STA */ | 1328 | return; |
955 | if (no_pending_pkts) | 1329 | } |
956 | hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); | 1330 | |
957 | else | 1331 | if (!driver_release_tids) { |
958 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1332 | struct sk_buff_head pending; |
1333 | struct sk_buff *skb; | ||
1334 | int num = 0; | ||
1335 | u16 tids = 0; | ||
1336 | |||
1337 | skb_queue_head_init(&pending); | ||
1338 | |||
1339 | while ((skb = __skb_dequeue(&frames))) { | ||
1340 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1341 | struct ieee80211_hdr *hdr = (void *) skb->data; | ||
1342 | u8 *qoshdr = NULL; | ||
1343 | |||
1344 | num++; | ||
1345 | |||
1346 | /* | ||
1347 | * Tell TX path to send this frame even though the | ||
1348 | * STA may still remain is PS mode after this frame | ||
1349 | * exchange. | ||
1350 | */ | ||
1351 | info->flags |= IEEE80211_TX_CTL_POLL_RESPONSE; | ||
1352 | |||
1353 | /* | ||
1354 | * Use MoreData flag to indicate whether there are | ||
1355 | * more buffered frames for this STA | ||
1356 | */ | ||
1357 | if (!more_data) | ||
1358 | hdr->frame_control &= | ||
1359 | cpu_to_le16(~IEEE80211_FCTL_MOREDATA); | ||
1360 | else | ||
1361 | hdr->frame_control |= | ||
1362 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
1363 | |||
1364 | if (ieee80211_is_data_qos(hdr->frame_control) || | ||
1365 | ieee80211_is_qos_nullfunc(hdr->frame_control)) | ||
1366 | qoshdr = ieee80211_get_qos_ctl(hdr); | ||
1367 | |||
1368 | /* set EOSP for the frame */ | ||
1369 | if (reason == IEEE80211_FRAME_RELEASE_UAPSD && | ||
1370 | qoshdr && skb_queue_empty(&frames)) | ||
1371 | *qoshdr |= IEEE80211_QOS_CTL_EOSP; | ||
1372 | |||
1373 | info->flags |= IEEE80211_TX_STATUS_EOSP | | ||
1374 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1375 | |||
1376 | if (qoshdr) | ||
1377 | tids |= BIT(*qoshdr & IEEE80211_QOS_CTL_TID_MASK); | ||
1378 | else | ||
1379 | tids |= BIT(0); | ||
1380 | |||
1381 | __skb_queue_tail(&pending, skb); | ||
1382 | } | ||
959 | 1383 | ||
960 | ieee80211_add_pending_skb(local, skb); | 1384 | drv_allow_buffered_frames(local, sta, tids, num, |
1385 | reason, more_data); | ||
961 | 1386 | ||
962 | if (no_pending_pkts) | 1387 | ieee80211_add_pending_skbs(local, &pending); |
963 | sta_info_clear_tim_bit(sta); | 1388 | |
964 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1389 | sta_info_recalc_tim(sta); |
965 | } else { | 1390 | } else { |
966 | /* | 1391 | /* |
967 | * FIXME: This can be the result of a race condition between | 1392 | * We need to release a frame that is buffered somewhere in the |
968 | * us expiring a frame and the station polling for it. | 1393 | * driver ... it'll have to handle that. |
969 | * Should we send it a null-func frame indicating we | 1394 | * Note that, as per the comment above, it'll also have to see |
970 | * have nothing buffered for it? | 1395 | * if there is more than just one frame on the specific TID that |
1396 | * we're releasing from, and it needs to set the more-data bit | ||
1397 | * accordingly if we tell it that there's no more data. If we do | ||
1398 | * tell it there's more data, then of course the more-data bit | ||
1399 | * needs to be set anyway. | ||
1400 | */ | ||
1401 | drv_release_buffered_frames(local, sta, driver_release_tids, | ||
1402 | n_frames, reason, more_data); | ||
1403 | |||
1404 | /* | ||
1405 | * Note that we don't recalculate the TIM bit here as it would | ||
1406 | * most likely have no effect at all unless the driver told us | ||
1407 | * that the TID became empty before returning here from the | ||
1408 | * release function. | ||
1409 | * Either way, however, when the driver tells us that the TID | ||
1410 | * became empty we'll do the TIM recalculation. | ||
971 | */ | 1411 | */ |
972 | printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " | ||
973 | "though there are no buffered frames for it\n", | ||
974 | sdata->name, sta->sta.addr); | ||
975 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | ||
976 | } | 1412 | } |
977 | } | 1413 | } |
978 | 1414 | ||
1415 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | ||
1416 | { | ||
1417 | u8 ignore_for_response = sta->sta.uapsd_queues; | ||
1418 | |||
1419 | /* | ||
1420 | * If all ACs are delivery-enabled then we should reply | ||
1421 | * from any of them, if only some are enabled we reply | ||
1422 | * only from the non-enabled ones. | ||
1423 | */ | ||
1424 | if (ignore_for_response == BIT(IEEE80211_NUM_ACS) - 1) | ||
1425 | ignore_for_response = 0; | ||
1426 | |||
1427 | ieee80211_sta_ps_deliver_response(sta, 1, ignore_for_response, | ||
1428 | IEEE80211_FRAME_RELEASE_PSPOLL); | ||
1429 | } | ||
1430 | |||
1431 | void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta) | ||
1432 | { | ||
1433 | int n_frames = sta->sta.max_sp; | ||
1434 | u8 delivery_enabled = sta->sta.uapsd_queues; | ||
1435 | |||
1436 | /* | ||
1437 | * If we ever grow support for TSPEC this might happen if | ||
1438 | * the TSPEC update from hostapd comes in between a trigger | ||
1439 | * frame setting WLAN_STA_UAPSD in the RX path and this | ||
1440 | * actually getting called. | ||
1441 | */ | ||
1442 | if (!delivery_enabled) | ||
1443 | return; | ||
1444 | |||
1445 | switch (sta->sta.max_sp) { | ||
1446 | case 1: | ||
1447 | n_frames = 2; | ||
1448 | break; | ||
1449 | case 2: | ||
1450 | n_frames = 4; | ||
1451 | break; | ||
1452 | case 3: | ||
1453 | n_frames = 6; | ||
1454 | break; | ||
1455 | case 0: | ||
1456 | /* XXX: what is a good value? */ | ||
1457 | n_frames = 8; | ||
1458 | break; | ||
1459 | } | ||
1460 | |||
1461 | ieee80211_sta_ps_deliver_response(sta, n_frames, ~delivery_enabled, | ||
1462 | IEEE80211_FRAME_RELEASE_UAPSD); | ||
1463 | } | ||
1464 | |||
979 | void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | 1465 | void ieee80211_sta_block_awake(struct ieee80211_hw *hw, |
980 | struct ieee80211_sta *pubsta, bool block) | 1466 | struct ieee80211_sta *pubsta, bool block) |
981 | { | 1467 | { |
@@ -984,17 +1470,50 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
984 | trace_api_sta_block_awake(sta->local, pubsta, block); | 1470 | trace_api_sta_block_awake(sta->local, pubsta, block); |
985 | 1471 | ||
986 | if (block) | 1472 | if (block) |
987 | set_sta_flags(sta, WLAN_STA_PS_DRIVER); | 1473 | set_sta_flag(sta, WLAN_STA_PS_DRIVER); |
988 | else if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) | 1474 | else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) |
989 | ieee80211_queue_work(hw, &sta->drv_unblock_wk); | 1475 | ieee80211_queue_work(hw, &sta->drv_unblock_wk); |
990 | } | 1476 | } |
991 | EXPORT_SYMBOL(ieee80211_sta_block_awake); | 1477 | EXPORT_SYMBOL(ieee80211_sta_block_awake); |
992 | 1478 | ||
993 | void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta) | 1479 | void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta) |
994 | { | 1480 | { |
995 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 1481 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
1482 | struct ieee80211_local *local = sta->local; | ||
1483 | struct sk_buff *skb; | ||
1484 | struct skb_eosp_msg_data *data; | ||
1485 | |||
1486 | trace_api_eosp(local, pubsta); | ||
1487 | |||
1488 | skb = alloc_skb(0, GFP_ATOMIC); | ||
1489 | if (!skb) { | ||
1490 | /* too bad ... but race is better than loss */ | ||
1491 | clear_sta_flag(sta, WLAN_STA_SP); | ||
1492 | return; | ||
1493 | } | ||
1494 | |||
1495 | data = (void *)skb->cb; | ||
1496 | memcpy(data->sta, pubsta->addr, ETH_ALEN); | ||
1497 | memcpy(data->iface, sta->sdata->vif.addr, ETH_ALEN); | ||
1498 | skb->pkt_type = IEEE80211_EOSP_MSG; | ||
1499 | skb_queue_tail(&local->skb_queue, skb); | ||
1500 | tasklet_schedule(&local->tasklet); | ||
1501 | } | ||
1502 | EXPORT_SYMBOL(ieee80211_sta_eosp_irqsafe); | ||
1503 | |||
1504 | void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | ||
1505 | u8 tid, bool buffered) | ||
1506 | { | ||
1507 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | ||
1508 | |||
1509 | if (WARN_ON(tid >= STA_TID_NUM)) | ||
1510 | return; | ||
1511 | |||
1512 | if (buffered) | ||
1513 | set_bit(tid, &sta->driver_buffered_tids); | ||
1514 | else | ||
1515 | clear_bit(tid, &sta->driver_buffered_tids); | ||
996 | 1516 | ||
997 | set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); | 1517 | sta_info_recalc_tim(sta); |
998 | sta_info_set_tim_bit(sta); | ||
999 | } | 1518 | } |
1000 | EXPORT_SYMBOL(ieee80211_sta_set_tim); | 1519 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 28beb78e601e..8c8ce05ad26f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -19,7 +19,8 @@ | |||
19 | /** | 19 | /** |
20 | * enum ieee80211_sta_info_flags - Stations flags | 20 | * enum ieee80211_sta_info_flags - Stations flags |
21 | * | 21 | * |
22 | * These flags are used with &struct sta_info's @flags member. | 22 | * These flags are used with &struct sta_info's @flags member, but |
23 | * only indirectly with set_sta_flag() and friends. | ||
23 | * | 24 | * |
24 | * @WLAN_STA_AUTH: Station is authenticated. | 25 | * @WLAN_STA_AUTH: Station is authenticated. |
25 | * @WLAN_STA_ASSOC: Station is associated. | 26 | * @WLAN_STA_ASSOC: Station is associated. |
@@ -43,24 +44,33 @@ | |||
43 | * be in the queues | 44 | * be in the queues |
44 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping | 45 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping |
45 | * station in power-save mode, reply when the driver unblocks. | 46 | * station in power-save mode, reply when the driver unblocks. |
46 | * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal | 47 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. |
47 | * buffers. Automatically cleared on station wake-up. | 48 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct |
49 | * packets. This means the link is enabled. | ||
50 | * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was | ||
51 | * keeping station in power-save mode, reply when the driver | ||
52 | * unblocks the station. | ||
53 | * @WLAN_STA_SP: Station is in a service period, so don't try to | ||
54 | * reply to other uAPSD trigger frames or PS-Poll. | ||
48 | */ | 55 | */ |
49 | enum ieee80211_sta_info_flags { | 56 | enum ieee80211_sta_info_flags { |
50 | WLAN_STA_AUTH = 1<<0, | 57 | WLAN_STA_AUTH, |
51 | WLAN_STA_ASSOC = 1<<1, | 58 | WLAN_STA_ASSOC, |
52 | WLAN_STA_PS_STA = 1<<2, | 59 | WLAN_STA_PS_STA, |
53 | WLAN_STA_AUTHORIZED = 1<<3, | 60 | WLAN_STA_AUTHORIZED, |
54 | WLAN_STA_SHORT_PREAMBLE = 1<<4, | 61 | WLAN_STA_SHORT_PREAMBLE, |
55 | WLAN_STA_ASSOC_AP = 1<<5, | 62 | WLAN_STA_ASSOC_AP, |
56 | WLAN_STA_WME = 1<<6, | 63 | WLAN_STA_WME, |
57 | WLAN_STA_WDS = 1<<7, | 64 | WLAN_STA_WDS, |
58 | WLAN_STA_CLEAR_PS_FILT = 1<<9, | 65 | WLAN_STA_CLEAR_PS_FILT, |
59 | WLAN_STA_MFP = 1<<10, | 66 | WLAN_STA_MFP, |
60 | WLAN_STA_BLOCK_BA = 1<<11, | 67 | WLAN_STA_BLOCK_BA, |
61 | WLAN_STA_PS_DRIVER = 1<<12, | 68 | WLAN_STA_PS_DRIVER, |
62 | WLAN_STA_PSPOLL = 1<<13, | 69 | WLAN_STA_PSPOLL, |
63 | WLAN_STA_PS_DRIVER_BUF = 1<<14, | 70 | WLAN_STA_TDLS_PEER, |
71 | WLAN_STA_TDLS_PEER_AUTH, | ||
72 | WLAN_STA_UAPSD, | ||
73 | WLAN_STA_SP, | ||
64 | }; | 74 | }; |
65 | 75 | ||
66 | #define STA_TID_NUM 16 | 76 | #define STA_TID_NUM 16 |
@@ -86,6 +96,8 @@ enum ieee80211_sta_info_flags { | |||
86 | * @stop_initiator: initiator of a session stop | 96 | * @stop_initiator: initiator of a session stop |
87 | * @tx_stop: TX DelBA frame when stopping | 97 | * @tx_stop: TX DelBA frame when stopping |
88 | * @buf_size: reorder buffer size at receiver | 98 | * @buf_size: reorder buffer size at receiver |
99 | * @failed_bar_ssn: ssn of the last failed BAR tx attempt | ||
100 | * @bar_pending: BAR needs to be re-sent | ||
89 | * | 101 | * |
90 | * This structure's lifetime is managed by RCU, assignments to | 102 | * This structure's lifetime is managed by RCU, assignments to |
91 | * the array holding it must hold the aggregation mutex. | 103 | * the array holding it must hold the aggregation mutex. |
@@ -106,6 +118,9 @@ struct tid_ampdu_tx { | |||
106 | u8 stop_initiator; | 118 | u8 stop_initiator; |
107 | bool tx_stop; | 119 | bool tx_stop; |
108 | u8 buf_size; | 120 | u8 buf_size; |
121 | |||
122 | u16 failed_bar_ssn; | ||
123 | bool bar_pending; | ||
109 | }; | 124 | }; |
110 | 125 | ||
111 | /** | 126 | /** |
@@ -198,15 +213,16 @@ struct sta_ampdu_mlme { | |||
198 | * @last_rx_rate_flag: rx status flag of the last data packet | 213 | * @last_rx_rate_flag: rx status flag of the last data packet |
199 | * @lock: used for locking all fields that require locking, see comments | 214 | * @lock: used for locking all fields that require locking, see comments |
200 | * in the header file. | 215 | * in the header file. |
201 | * @flaglock: spinlock for flags accesses | ||
202 | * @drv_unblock_wk: used for driver PS unblocking | 216 | * @drv_unblock_wk: used for driver PS unblocking |
203 | * @listen_interval: listen interval of this station, when we're acting as AP | 217 | * @listen_interval: listen interval of this station, when we're acting as AP |
204 | * @flags: STA flags, see &enum ieee80211_sta_info_flags | 218 | * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly |
205 | * @ps_tx_buf: buffer of frames to transmit to this station | 219 | * @ps_tx_buf: buffers (per AC) of frames to transmit to this station |
206 | * when it leaves power saving state | 220 | * when it leaves power saving state or polls |
207 | * @tx_filtered: buffer of frames we already tried to transmit | 221 | * @tx_filtered: buffers (per AC) of frames we already tried to |
208 | * but were filtered by hardware due to STA having entered | 222 | * transmit but were filtered by hardware due to STA having |
209 | * power saving state | 223 | * entered power saving state, these are also delivered to |
224 | * the station when it leaves powersave or polls for frames | ||
225 | * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on | ||
210 | * @rx_packets: Number of MSDUs received from this STA | 226 | * @rx_packets: Number of MSDUs received from this STA |
211 | * @rx_bytes: Number of bytes received from this STA | 227 | * @rx_bytes: Number of bytes received from this STA |
212 | * @wep_weak_iv_count: number of weak WEP IVs received from this station | 228 | * @wep_weak_iv_count: number of weak WEP IVs received from this station |
@@ -238,10 +254,12 @@ struct sta_ampdu_mlme { | |||
238 | * @plink_timer: peer link watch timer | 254 | * @plink_timer: peer link watch timer |
239 | * @plink_timer_was_running: used by suspend/resume to restore timers | 255 | * @plink_timer_was_running: used by suspend/resume to restore timers |
240 | * @debugfs: debug filesystem info | 256 | * @debugfs: debug filesystem info |
241 | * @sta: station information we share with the driver | ||
242 | * @dead: set to true when sta is unlinked | 257 | * @dead: set to true when sta is unlinked |
243 | * @uploaded: set to true when sta is uploaded to the driver | 258 | * @uploaded: set to true when sta is uploaded to the driver |
244 | * @lost_packets: number of consecutive lost packets | 259 | * @lost_packets: number of consecutive lost packets |
260 | * @dummy: indicate a dummy station created for receiving | ||
261 | * EAP frames before association | ||
262 | * @sta: station information we share with the driver | ||
245 | */ | 263 | */ |
246 | struct sta_info { | 264 | struct sta_info { |
247 | /* General information, mostly static */ | 265 | /* General information, mostly static */ |
@@ -254,7 +272,6 @@ struct sta_info { | |||
254 | struct rate_control_ref *rate_ctrl; | 272 | struct rate_control_ref *rate_ctrl; |
255 | void *rate_ctrl_priv; | 273 | void *rate_ctrl_priv; |
256 | spinlock_t lock; | 274 | spinlock_t lock; |
257 | spinlock_t flaglock; | ||
258 | 275 | ||
259 | struct work_struct drv_unblock_wk; | 276 | struct work_struct drv_unblock_wk; |
260 | 277 | ||
@@ -264,18 +281,16 @@ struct sta_info { | |||
264 | 281 | ||
265 | bool uploaded; | 282 | bool uploaded; |
266 | 283 | ||
267 | /* | 284 | /* use the accessors defined below */ |
268 | * frequently updated, locked with own spinlock (flaglock), | 285 | unsigned long _flags; |
269 | * use the accessors defined below | ||
270 | */ | ||
271 | u32 flags; | ||
272 | 286 | ||
273 | /* | 287 | /* |
274 | * STA powersave frame queues, no more than the internal | 288 | * STA powersave frame queues, no more than the internal |
275 | * locking required. | 289 | * locking required. |
276 | */ | 290 | */ |
277 | struct sk_buff_head ps_tx_buf; | 291 | struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; |
278 | struct sk_buff_head tx_filtered; | 292 | struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; |
293 | unsigned long driver_buffered_tids; | ||
279 | 294 | ||
280 | /* Updated from RX path only, no locking requirements */ | 295 | /* Updated from RX path only, no locking requirements */ |
281 | unsigned long rx_packets, rx_bytes; | 296 | unsigned long rx_packets, rx_bytes; |
@@ -336,6 +351,9 @@ struct sta_info { | |||
336 | 351 | ||
337 | unsigned int lost_packets; | 352 | unsigned int lost_packets; |
338 | 353 | ||
354 | /* should be right in front of sta to be in the same cache line */ | ||
355 | bool dummy; | ||
356 | |||
339 | /* keep last! */ | 357 | /* keep last! */ |
340 | struct ieee80211_sta sta; | 358 | struct ieee80211_sta sta; |
341 | }; | 359 | }; |
@@ -348,60 +366,28 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta) | |||
348 | return NL80211_PLINK_LISTEN; | 366 | return NL80211_PLINK_LISTEN; |
349 | } | 367 | } |
350 | 368 | ||
351 | static inline void set_sta_flags(struct sta_info *sta, const u32 flags) | 369 | static inline void set_sta_flag(struct sta_info *sta, |
370 | enum ieee80211_sta_info_flags flag) | ||
352 | { | 371 | { |
353 | unsigned long irqfl; | 372 | set_bit(flag, &sta->_flags); |
354 | |||
355 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
356 | sta->flags |= flags; | ||
357 | spin_unlock_irqrestore(&sta->flaglock, irqfl); | ||
358 | } | 373 | } |
359 | 374 | ||
360 | static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) | 375 | static inline void clear_sta_flag(struct sta_info *sta, |
376 | enum ieee80211_sta_info_flags flag) | ||
361 | { | 377 | { |
362 | unsigned long irqfl; | 378 | clear_bit(flag, &sta->_flags); |
363 | |||
364 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
365 | sta->flags &= ~flags; | ||
366 | spin_unlock_irqrestore(&sta->flaglock, irqfl); | ||
367 | } | 379 | } |
368 | 380 | ||
369 | static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) | 381 | static inline int test_sta_flag(struct sta_info *sta, |
382 | enum ieee80211_sta_info_flags flag) | ||
370 | { | 383 | { |
371 | u32 ret; | 384 | return test_bit(flag, &sta->_flags); |
372 | unsigned long irqfl; | ||
373 | |||
374 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
375 | ret = sta->flags & flags; | ||
376 | spin_unlock_irqrestore(&sta->flaglock, irqfl); | ||
377 | |||
378 | return ret; | ||
379 | } | ||
380 | |||
381 | static inline u32 test_and_clear_sta_flags(struct sta_info *sta, | ||
382 | const u32 flags) | ||
383 | { | ||
384 | u32 ret; | ||
385 | unsigned long irqfl; | ||
386 | |||
387 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
388 | ret = sta->flags & flags; | ||
389 | sta->flags &= ~flags; | ||
390 | spin_unlock_irqrestore(&sta->flaglock, irqfl); | ||
391 | |||
392 | return ret; | ||
393 | } | 385 | } |
394 | 386 | ||
395 | static inline u32 get_sta_flags(struct sta_info *sta) | 387 | static inline int test_and_clear_sta_flag(struct sta_info *sta, |
388 | enum ieee80211_sta_info_flags flag) | ||
396 | { | 389 | { |
397 | u32 ret; | 390 | return test_and_clear_bit(flag, &sta->_flags); |
398 | unsigned long irqfl; | ||
399 | |||
400 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
401 | ret = sta->flags; | ||
402 | spin_unlock_irqrestore(&sta->flaglock, irqfl); | ||
403 | |||
404 | return ret; | ||
405 | } | 391 | } |
406 | 392 | ||
407 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, | 393 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, |
@@ -419,8 +405,8 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) | |||
419 | #define STA_HASH(sta) (sta[5]) | 405 | #define STA_HASH(sta) (sta[5]) |
420 | 406 | ||
421 | 407 | ||
422 | /* Maximum number of frames to buffer per power saving station */ | 408 | /* Maximum number of frames to buffer per power saving station per AC */ |
423 | #define STA_MAX_TX_BUFFER 128 | 409 | #define STA_MAX_TX_BUFFER 64 |
424 | 410 | ||
425 | /* Minimum buffered frame expiry time. If STA uses listen interval that is | 411 | /* Minimum buffered frame expiry time. If STA uses listen interval that is |
426 | * smaller than this value, the minimum value here is used instead. */ | 412 | * smaller than this value, the minimum value here is used instead. */ |
@@ -436,9 +422,15 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) | |||
436 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | 422 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
437 | const u8 *addr); | 423 | const u8 *addr); |
438 | 424 | ||
425 | struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | ||
426 | const u8 *addr); | ||
427 | |||
439 | struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | 428 | struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, |
440 | const u8 *addr); | 429 | const u8 *addr); |
441 | 430 | ||
431 | struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | ||
432 | const u8 *addr); | ||
433 | |||
442 | static inline | 434 | static inline |
443 | void for_each_sta_info_type_check(struct ieee80211_local *local, | 435 | void for_each_sta_info_type_check(struct ieee80211_local *local, |
444 | const u8 *addr, | 436 | const u8 *addr, |
@@ -459,6 +451,22 @@ void for_each_sta_info_type_check(struct ieee80211_local *local, | |||
459 | _sta = nxt, \ | 451 | _sta = nxt, \ |
460 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ | 452 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ |
461 | ) \ | 453 | ) \ |
454 | /* run code only if address matches and it's not a dummy sta */ \ | ||
455 | if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \ | ||
456 | !_sta->dummy) | ||
457 | |||
458 | #define for_each_sta_info_rx(local, _addr, _sta, nxt) \ | ||
459 | for ( /* initialise loop */ \ | ||
460 | _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ | ||
461 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ | ||
462 | /* typecheck */ \ | ||
463 | for_each_sta_info_type_check(local, (_addr), _sta, nxt),\ | ||
464 | /* continue condition */ \ | ||
465 | _sta; \ | ||
466 | /* advance loop */ \ | ||
467 | _sta = nxt, \ | ||
468 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ | ||
469 | ) \ | ||
462 | /* compare address and run code only if it matches */ \ | 470 | /* compare address and run code only if it matches */ \ |
463 | if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0) | 471 | if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0) |
464 | 472 | ||
@@ -484,14 +492,14 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
484 | int sta_info_insert(struct sta_info *sta); | 492 | int sta_info_insert(struct sta_info *sta); |
485 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); | 493 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
486 | int sta_info_insert_atomic(struct sta_info *sta); | 494 | int sta_info_insert_atomic(struct sta_info *sta); |
495 | int sta_info_reinsert(struct sta_info *sta); | ||
487 | 496 | ||
488 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, | 497 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |
489 | const u8 *addr); | 498 | const u8 *addr); |
490 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, | 499 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, |
491 | const u8 *addr); | 500 | const u8 *addr); |
492 | 501 | ||
493 | void sta_info_set_tim_bit(struct sta_info *sta); | 502 | void sta_info_recalc_tim(struct sta_info *sta); |
494 | void sta_info_clear_tim_bit(struct sta_info *sta); | ||
495 | 503 | ||
496 | void sta_info_init(struct ieee80211_local *local); | 504 | void sta_info_init(struct ieee80211_local *local); |
497 | void sta_info_stop(struct ieee80211_local *local); | 505 | void sta_info_stop(struct ieee80211_local *local); |
@@ -502,5 +510,6 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
502 | 510 | ||
503 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); | 511 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); |
504 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); | 512 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); |
513 | void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); | ||
505 | 514 | ||
506 | #endif /* STA_INFO_H */ | 515 | #endif /* STA_INFO_H */ |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 1658efaa2e8e..df643cedf9b9 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "rate.h" | 14 | #include "rate.h" |
15 | #include "mesh.h" | 15 | #include "mesh.h" |
16 | #include "led.h" | 16 | #include "led.h" |
17 | #include "wme.h" | ||
17 | 18 | ||
18 | 19 | ||
19 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | 20 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, |
@@ -43,6 +44,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
43 | struct sk_buff *skb) | 44 | struct sk_buff *skb) |
44 | { | 45 | { |
45 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 46 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
47 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
48 | int ac; | ||
46 | 49 | ||
47 | /* | 50 | /* |
48 | * This skb 'survived' a round-trip through the driver, and | 51 | * This skb 'survived' a round-trip through the driver, and |
@@ -63,11 +66,37 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
63 | sta->tx_filtered_count++; | 66 | sta->tx_filtered_count++; |
64 | 67 | ||
65 | /* | 68 | /* |
69 | * Clear more-data bit on filtered frames, it might be set | ||
70 | * but later frames might time out so it might have to be | ||
71 | * clear again ... It's all rather unlikely (this frame | ||
72 | * should time out first, right?) but let's not confuse | ||
73 | * peers unnecessarily. | ||
74 | */ | ||
75 | if (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) | ||
76 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
77 | |||
78 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
79 | u8 *p = ieee80211_get_qos_ctl(hdr); | ||
80 | int tid = *p & IEEE80211_QOS_CTL_TID_MASK; | ||
81 | |||
82 | /* | ||
83 | * Clear EOSP if set, this could happen e.g. | ||
84 | * if an absence period (us being a P2P GO) | ||
85 | * shortens the SP. | ||
86 | */ | ||
87 | if (*p & IEEE80211_QOS_CTL_EOSP) | ||
88 | *p &= ~IEEE80211_QOS_CTL_EOSP; | ||
89 | ac = ieee802_1d_to_ac[tid & 7]; | ||
90 | } else { | ||
91 | ac = IEEE80211_AC_BE; | ||
92 | } | ||
93 | |||
94 | /* | ||
66 | * Clear the TX filter mask for this STA when sending the next | 95 | * Clear the TX filter mask for this STA when sending the next |
67 | * packet. If the STA went to power save mode, this will happen | 96 | * packet. If the STA went to power save mode, this will happen |
68 | * when it wakes up for the next time. | 97 | * when it wakes up for the next time. |
69 | */ | 98 | */ |
70 | set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); | 99 | set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT); |
71 | 100 | ||
72 | /* | 101 | /* |
73 | * This code races in the following way: | 102 | * This code races in the following way: |
@@ -103,13 +132,19 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
103 | * changes before calling TX status events if ordering can be | 132 | * changes before calling TX status events if ordering can be |
104 | * unknown. | 133 | * unknown. |
105 | */ | 134 | */ |
106 | if (test_sta_flags(sta, WLAN_STA_PS_STA) && | 135 | if (test_sta_flag(sta, WLAN_STA_PS_STA) && |
107 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | 136 | skb_queue_len(&sta->tx_filtered[ac]) < STA_MAX_TX_BUFFER) { |
108 | skb_queue_tail(&sta->tx_filtered, skb); | 137 | skb_queue_tail(&sta->tx_filtered[ac], skb); |
138 | sta_info_recalc_tim(sta); | ||
139 | |||
140 | if (!timer_pending(&local->sta_cleanup)) | ||
141 | mod_timer(&local->sta_cleanup, | ||
142 | round_jiffies(jiffies + | ||
143 | STA_INFO_CLEANUP_INTERVAL)); | ||
109 | return; | 144 | return; |
110 | } | 145 | } |
111 | 146 | ||
112 | if (!test_sta_flags(sta, WLAN_STA_PS_STA) && | 147 | if (!test_sta_flag(sta, WLAN_STA_PS_STA) && |
113 | !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { | 148 | !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { |
114 | /* Software retry the packet once */ | 149 | /* Software retry the packet once */ |
115 | info->flags |= IEEE80211_TX_INTFL_RETRIED; | 150 | info->flags |= IEEE80211_TX_INTFL_RETRIED; |
@@ -121,18 +156,38 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
121 | if (net_ratelimit()) | 156 | if (net_ratelimit()) |
122 | wiphy_debug(local->hw.wiphy, | 157 | wiphy_debug(local->hw.wiphy, |
123 | "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", | 158 | "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", |
124 | skb_queue_len(&sta->tx_filtered), | 159 | skb_queue_len(&sta->tx_filtered[ac]), |
125 | !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); | 160 | !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies); |
126 | #endif | 161 | #endif |
127 | dev_kfree_skb(skb); | 162 | dev_kfree_skb(skb); |
128 | } | 163 | } |
129 | 164 | ||
165 | static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid) | ||
166 | { | ||
167 | struct tid_ampdu_tx *tid_tx; | ||
168 | |||
169 | tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); | ||
170 | if (!tid_tx || !tid_tx->bar_pending) | ||
171 | return; | ||
172 | |||
173 | tid_tx->bar_pending = false; | ||
174 | ieee80211_send_bar(&sta->sdata->vif, addr, tid, tid_tx->failed_bar_ssn); | ||
175 | } | ||
176 | |||
130 | static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | 177 | static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) |
131 | { | 178 | { |
132 | struct ieee80211_mgmt *mgmt = (void *) skb->data; | 179 | struct ieee80211_mgmt *mgmt = (void *) skb->data; |
133 | struct ieee80211_local *local = sta->local; | 180 | struct ieee80211_local *local = sta->local; |
134 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 181 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
135 | 182 | ||
183 | if (ieee80211_is_data_qos(mgmt->frame_control)) { | ||
184 | struct ieee80211_hdr *hdr = (void *) skb->data; | ||
185 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
186 | u16 tid = qc[0] & 0xf; | ||
187 | |||
188 | ieee80211_check_pending_bar(sta, hdr->addr1, tid); | ||
189 | } | ||
190 | |||
136 | if (ieee80211_is_action(mgmt->frame_control) && | 191 | if (ieee80211_is_action(mgmt->frame_control) && |
137 | sdata->vif.type == NL80211_IFTYPE_STATION && | 192 | sdata->vif.type == NL80211_IFTYPE_STATION && |
138 | mgmt->u.action.category == WLAN_CATEGORY_HT && | 193 | mgmt->u.action.category == WLAN_CATEGORY_HT && |
@@ -161,6 +216,114 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | |||
161 | } | 216 | } |
162 | } | 217 | } |
163 | 218 | ||
219 | static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn) | ||
220 | { | ||
221 | struct tid_ampdu_tx *tid_tx; | ||
222 | |||
223 | tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); | ||
224 | if (!tid_tx) | ||
225 | return; | ||
226 | |||
227 | tid_tx->failed_bar_ssn = ssn; | ||
228 | tid_tx->bar_pending = true; | ||
229 | } | ||
230 | |||
231 | static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info) | ||
232 | { | ||
233 | int len = sizeof(struct ieee80211_radiotap_header); | ||
234 | |||
235 | /* IEEE80211_RADIOTAP_RATE rate */ | ||
236 | if (info->status.rates[0].idx >= 0 && | ||
237 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) | ||
238 | len += 2; | ||
239 | |||
240 | /* IEEE80211_RADIOTAP_TX_FLAGS */ | ||
241 | len += 2; | ||
242 | |||
243 | /* IEEE80211_RADIOTAP_DATA_RETRIES */ | ||
244 | len += 1; | ||
245 | |||
246 | /* IEEE80211_TX_RC_MCS */ | ||
247 | if (info->status.rates[0].idx >= 0 && | ||
248 | info->status.rates[0].flags & IEEE80211_TX_RC_MCS) | ||
249 | len += 3; | ||
250 | |||
251 | return len; | ||
252 | } | ||
253 | |||
254 | static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | ||
255 | *sband, struct sk_buff *skb, | ||
256 | int retry_count, int rtap_len) | ||
257 | { | ||
258 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
259 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
260 | struct ieee80211_radiotap_header *rthdr; | ||
261 | unsigned char *pos; | ||
262 | __le16 txflags; | ||
263 | |||
264 | rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len); | ||
265 | |||
266 | memset(rthdr, 0, rtap_len); | ||
267 | rthdr->it_len = cpu_to_le16(rtap_len); | ||
268 | rthdr->it_present = | ||
269 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
270 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); | ||
271 | pos = (unsigned char *)(rthdr + 1); | ||
272 | |||
273 | /* | ||
274 | * XXX: Once radiotap gets the bitmap reset thing the vendor | ||
275 | * extensions proposal contains, we can actually report | ||
276 | * the whole set of tries we did. | ||
277 | */ | ||
278 | |||
279 | /* IEEE80211_RADIOTAP_RATE */ | ||
280 | if (info->status.rates[0].idx >= 0 && | ||
281 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) { | ||
282 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); | ||
283 | *pos = sband->bitrates[info->status.rates[0].idx].bitrate / 5; | ||
284 | /* padding for tx flags */ | ||
285 | pos += 2; | ||
286 | } | ||
287 | |||
288 | /* IEEE80211_RADIOTAP_TX_FLAGS */ | ||
289 | txflags = 0; | ||
290 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
291 | !is_multicast_ether_addr(hdr->addr1)) | ||
292 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
293 | |||
294 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
295 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
296 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
297 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
298 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
299 | |||
300 | put_unaligned_le16(txflags, pos); | ||
301 | pos += 2; | ||
302 | |||
303 | /* IEEE80211_RADIOTAP_DATA_RETRIES */ | ||
304 | /* for now report the total retry_count */ | ||
305 | *pos = retry_count; | ||
306 | pos++; | ||
307 | |||
308 | /* IEEE80211_TX_RC_MCS */ | ||
309 | if (info->status.rates[0].idx >= 0 && | ||
310 | info->status.rates[0].flags & IEEE80211_TX_RC_MCS) { | ||
311 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); | ||
312 | pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS | | ||
313 | IEEE80211_RADIOTAP_MCS_HAVE_GI | | ||
314 | IEEE80211_RADIOTAP_MCS_HAVE_BW; | ||
315 | if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI) | ||
316 | pos[1] |= IEEE80211_RADIOTAP_MCS_SGI; | ||
317 | if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
318 | pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40; | ||
319 | if (info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD) | ||
320 | pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF; | ||
321 | pos[2] = info->status.rates[0].idx; | ||
322 | pos += 3; | ||
323 | } | ||
324 | |||
325 | } | ||
326 | |||
164 | /* | 327 | /* |
165 | * Use a static threshold for now, best value to be determined | 328 | * Use a static threshold for now, best value to be determined |
166 | * by testing ... | 329 | * by testing ... |
@@ -179,7 +342,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
179 | u16 frag, type; | 342 | u16 frag, type; |
180 | __le16 fc; | 343 | __le16 fc; |
181 | struct ieee80211_supported_band *sband; | 344 | struct ieee80211_supported_band *sband; |
182 | struct ieee80211_tx_status_rtap_hdr *rthdr; | ||
183 | struct ieee80211_sub_if_data *sdata; | 345 | struct ieee80211_sub_if_data *sdata; |
184 | struct net_device *prev_dev = NULL; | 346 | struct net_device *prev_dev = NULL; |
185 | struct sta_info *sta, *tmp; | 347 | struct sta_info *sta, *tmp; |
@@ -187,6 +349,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
187 | int rates_idx = -1; | 349 | int rates_idx = -1; |
188 | bool send_to_cooked; | 350 | bool send_to_cooked; |
189 | bool acked; | 351 | bool acked; |
352 | struct ieee80211_bar *bar; | ||
353 | u16 tid; | ||
354 | int rtap_len; | ||
190 | 355 | ||
191 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 356 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
192 | if (info->status.rates[i].idx < 0) { | 357 | if (info->status.rates[i].idx < 0) { |
@@ -215,8 +380,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
215 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | 380 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) |
216 | continue; | 381 | continue; |
217 | 382 | ||
383 | if (info->flags & IEEE80211_TX_STATUS_EOSP) | ||
384 | clear_sta_flag(sta, WLAN_STA_SP); | ||
385 | |||
218 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); | 386 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); |
219 | if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) { | 387 | if (!acked && test_sta_flag(sta, WLAN_STA_PS_STA)) { |
220 | /* | 388 | /* |
221 | * The STA is in power save mode, so assume | 389 | * The STA is in power save mode, so assume |
222 | * that this TX packet failed because of that. | 390 | * that this TX packet failed because of that. |
@@ -239,10 +407,31 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
239 | tid = qc[0] & 0xf; | 407 | tid = qc[0] & 0xf; |
240 | ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) | 408 | ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) |
241 | & IEEE80211_SCTL_SEQ); | 409 | & IEEE80211_SCTL_SEQ); |
242 | ieee80211_send_bar(sta->sdata, hdr->addr1, | 410 | ieee80211_send_bar(&sta->sdata->vif, hdr->addr1, |
243 | tid, ssn); | 411 | tid, ssn); |
244 | } | 412 | } |
245 | 413 | ||
414 | if (!acked && ieee80211_is_back_req(fc)) { | ||
415 | u16 control; | ||
416 | |||
417 | /* | ||
418 | * BAR failed, store the last SSN and retry sending | ||
419 | * the BAR when the next unicast transmission on the | ||
420 | * same TID succeeds. | ||
421 | */ | ||
422 | bar = (struct ieee80211_bar *) skb->data; | ||
423 | control = le16_to_cpu(bar->control); | ||
424 | if (!(control & IEEE80211_BAR_CTRL_MULTI_TID)) { | ||
425 | u16 ssn = le16_to_cpu(bar->start_seq_num); | ||
426 | |||
427 | tid = (control & | ||
428 | IEEE80211_BAR_CTRL_TID_INFO_MASK) >> | ||
429 | IEEE80211_BAR_CTRL_TID_INFO_SHIFT; | ||
430 | |||
431 | ieee80211_set_bar_pending(sta, tid, ssn); | ||
432 | } | ||
433 | } | ||
434 | |||
246 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | 435 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { |
247 | ieee80211_handle_filtered_frame(local, sta, skb); | 436 | ieee80211_handle_filtered_frame(local, sta, skb); |
248 | rcu_read_unlock(); | 437 | rcu_read_unlock(); |
@@ -336,7 +525,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
336 | continue; | 525 | continue; |
337 | if (wk->offchan_tx.frame != skb) | 526 | if (wk->offchan_tx.frame != skb) |
338 | continue; | 527 | continue; |
339 | wk->offchan_tx.frame = NULL; | 528 | wk->offchan_tx.status = true; |
340 | break; | 529 | break; |
341 | } | 530 | } |
342 | rcu_read_unlock(); | 531 | rcu_read_unlock(); |
@@ -345,9 +534,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
345 | local->hw_roc_skb_for_status = NULL; | 534 | local->hw_roc_skb_for_status = NULL; |
346 | } | 535 | } |
347 | 536 | ||
348 | if (cookie == local->hw_offchan_tx_cookie) | ||
349 | local->hw_offchan_tx_cookie = 0; | ||
350 | |||
351 | cfg80211_mgmt_tx_status( | 537 | cfg80211_mgmt_tx_status( |
352 | skb->dev, cookie, skb->data, skb->len, | 538 | skb->dev, cookie, skb->data, skb->len, |
353 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); | 539 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); |
@@ -370,44 +556,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
370 | } | 556 | } |
371 | 557 | ||
372 | /* send frame to monitor interfaces now */ | 558 | /* send frame to monitor interfaces now */ |
373 | 559 | rtap_len = ieee80211_tx_radiotap_len(info); | |
374 | if (skb_headroom(skb) < sizeof(*rthdr)) { | 560 | if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { |
375 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); | 561 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); |
376 | dev_kfree_skb(skb); | 562 | dev_kfree_skb(skb); |
377 | return; | 563 | return; |
378 | } | 564 | } |
379 | 565 | ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len); | |
380 | rthdr = (struct ieee80211_tx_status_rtap_hdr *) | ||
381 | skb_push(skb, sizeof(*rthdr)); | ||
382 | |||
383 | memset(rthdr, 0, sizeof(*rthdr)); | ||
384 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | ||
385 | rthdr->hdr.it_present = | ||
386 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
387 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | | ||
388 | (1 << IEEE80211_RADIOTAP_RATE)); | ||
389 | |||
390 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
391 | !is_multicast_ether_addr(hdr->addr1)) | ||
392 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
393 | |||
394 | /* | ||
395 | * XXX: Once radiotap gets the bitmap reset thing the vendor | ||
396 | * extensions proposal contains, we can actually report | ||
397 | * the whole set of tries we did. | ||
398 | */ | ||
399 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
400 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
401 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
402 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
403 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
404 | if (info->status.rates[0].idx >= 0 && | ||
405 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) | ||
406 | rthdr->rate = sband->bitrates[ | ||
407 | info->status.rates[0].idx].bitrate / 5; | ||
408 | |||
409 | /* for now report the total retry_count */ | ||
410 | rthdr->data_retries = retry_count; | ||
411 | 566 | ||
412 | /* XXX: is this sufficient for BPF? */ | 567 | /* XXX: is this sufficient for BPF? */ |
413 | skb_set_mac_header(skb, 0); | 568 | skb_set_mac_header(skb, 0); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 8cb0d2d0ac69..48bbb96d8edb 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -253,7 +253,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
253 | 253 | ||
254 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 254 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
255 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 255 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
256 | u32 sta_flags; | 256 | bool assoc = false; |
257 | 257 | ||
258 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) | 258 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) |
259 | return TX_CONTINUE; | 259 | return TX_CONTINUE; |
@@ -284,10 +284,11 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
284 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) | 284 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) |
285 | return TX_CONTINUE; | 285 | return TX_CONTINUE; |
286 | 286 | ||
287 | sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; | 287 | if (tx->sta) |
288 | assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC); | ||
288 | 289 | ||
289 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { | 290 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { |
290 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && | 291 | if (unlikely(!assoc && |
291 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | 292 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
292 | ieee80211_is_data(hdr->frame_control))) { | 293 | ieee80211_is_data(hdr->frame_control))) { |
293 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 294 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -343,13 +344,22 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
343 | total += skb_queue_len(&ap->ps_bc_buf); | 344 | total += skb_queue_len(&ap->ps_bc_buf); |
344 | } | 345 | } |
345 | 346 | ||
347 | /* | ||
348 | * Drop one frame from each station from the lowest-priority | ||
349 | * AC that has frames at all. | ||
350 | */ | ||
346 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 351 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
347 | skb = skb_dequeue(&sta->ps_tx_buf); | 352 | int ac; |
348 | if (skb) { | 353 | |
349 | purged++; | 354 | for (ac = IEEE80211_AC_BK; ac >= IEEE80211_AC_VO; ac--) { |
350 | dev_kfree_skb(skb); | 355 | skb = skb_dequeue(&sta->ps_tx_buf[ac]); |
356 | total += skb_queue_len(&sta->ps_tx_buf[ac]); | ||
357 | if (skb) { | ||
358 | purged++; | ||
359 | dev_kfree_skb(skb); | ||
360 | break; | ||
361 | } | ||
351 | } | 362 | } |
352 | total += skb_queue_len(&sta->ps_tx_buf); | ||
353 | } | 363 | } |
354 | 364 | ||
355 | rcu_read_unlock(); | 365 | rcu_read_unlock(); |
@@ -418,7 +428,7 @@ static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, | |||
418 | if (!ieee80211_is_mgmt(fc)) | 428 | if (!ieee80211_is_mgmt(fc)) |
419 | return 0; | 429 | return 0; |
420 | 430 | ||
421 | if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP)) | 431 | if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) |
422 | return 0; | 432 | return 0; |
423 | 433 | ||
424 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) | 434 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) |
@@ -435,7 +445,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
435 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 445 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
436 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 446 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
437 | struct ieee80211_local *local = tx->local; | 447 | struct ieee80211_local *local = tx->local; |
438 | u32 staflags; | ||
439 | 448 | ||
440 | if (unlikely(!sta || | 449 | if (unlikely(!sta || |
441 | ieee80211_is_probe_resp(hdr->frame_control) || | 450 | ieee80211_is_probe_resp(hdr->frame_control) || |
@@ -444,57 +453,52 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
444 | ieee80211_is_reassoc_resp(hdr->frame_control))) | 453 | ieee80211_is_reassoc_resp(hdr->frame_control))) |
445 | return TX_CONTINUE; | 454 | return TX_CONTINUE; |
446 | 455 | ||
447 | staflags = get_sta_flags(sta); | 456 | if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) || |
457 | test_sta_flag(sta, WLAN_STA_PS_DRIVER)) && | ||
458 | !(info->flags & IEEE80211_TX_CTL_POLL_RESPONSE))) { | ||
459 | int ac = skb_get_queue_mapping(tx->skb); | ||
448 | 460 | ||
449 | if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) && | ||
450 | !(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) { | ||
451 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 461 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
452 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries " | 462 | printk(KERN_DEBUG "STA %pM aid %d: PS buffer for AC %d\n", |
453 | "before %d)\n", | 463 | sta->sta.addr, sta->sta.aid, ac); |
454 | sta->sta.addr, sta->sta.aid, | ||
455 | skb_queue_len(&sta->ps_tx_buf)); | ||
456 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 464 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
457 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 465 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
458 | purge_old_ps_buffers(tx->local); | 466 | purge_old_ps_buffers(tx->local); |
459 | if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) { | 467 | if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { |
460 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf); | 468 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); |
461 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 469 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
462 | if (net_ratelimit()) { | 470 | if (net_ratelimit()) |
463 | printk(KERN_DEBUG "%s: STA %pM TX " | 471 | printk(KERN_DEBUG "%s: STA %pM TX buffer for " |
464 | "buffer full - dropping oldest frame\n", | 472 | "AC %d full - dropping oldest frame\n", |
465 | tx->sdata->name, sta->sta.addr); | 473 | tx->sdata->name, sta->sta.addr, ac); |
466 | } | ||
467 | #endif | 474 | #endif |
468 | dev_kfree_skb(old); | 475 | dev_kfree_skb(old); |
469 | } else | 476 | } else |
470 | tx->local->total_ps_buffered++; | 477 | tx->local->total_ps_buffered++; |
471 | 478 | ||
472 | /* | ||
473 | * Queue frame to be sent after STA wakes up/polls, | ||
474 | * but don't set the TIM bit if the driver is blocking | ||
475 | * wakeup or poll response transmissions anyway. | ||
476 | */ | ||
477 | if (skb_queue_empty(&sta->ps_tx_buf) && | ||
478 | !(staflags & WLAN_STA_PS_DRIVER)) | ||
479 | sta_info_set_tim_bit(sta); | ||
480 | |||
481 | info->control.jiffies = jiffies; | 479 | info->control.jiffies = jiffies; |
482 | info->control.vif = &tx->sdata->vif; | 480 | info->control.vif = &tx->sdata->vif; |
483 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 481 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
484 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); | 482 | skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); |
485 | 483 | ||
486 | if (!timer_pending(&local->sta_cleanup)) | 484 | if (!timer_pending(&local->sta_cleanup)) |
487 | mod_timer(&local->sta_cleanup, | 485 | mod_timer(&local->sta_cleanup, |
488 | round_jiffies(jiffies + | 486 | round_jiffies(jiffies + |
489 | STA_INFO_CLEANUP_INTERVAL)); | 487 | STA_INFO_CLEANUP_INTERVAL)); |
490 | 488 | ||
489 | /* | ||
490 | * We queued up some frames, so the TIM bit might | ||
491 | * need to be set, recalculate it. | ||
492 | */ | ||
493 | sta_info_recalc_tim(sta); | ||
494 | |||
491 | return TX_QUEUED; | 495 | return TX_QUEUED; |
492 | } | 496 | } |
493 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 497 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
494 | else if (unlikely(staflags & WLAN_STA_PS_STA)) { | 498 | else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) { |
495 | printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " | 499 | printk(KERN_DEBUG |
496 | "set -> send frame\n", tx->sdata->name, | 500 | "%s: STA %pM in PS mode, but polling/in SP -> send frame\n", |
497 | sta->sta.addr); | 501 | tx->sdata->name, sta->sta.addr); |
498 | } | 502 | } |
499 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 503 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
500 | 504 | ||
@@ -552,7 +556,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
552 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | 556 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && |
553 | (!ieee80211_is_robust_mgmt_frame(hdr) || | 557 | (!ieee80211_is_robust_mgmt_frame(hdr) || |
554 | (ieee80211_is_action(hdr->frame_control) && | 558 | (ieee80211_is_action(hdr->frame_control) && |
555 | tx->sta && test_sta_flags(tx->sta, WLAN_STA_MFP)))) { | 559 | tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))) { |
556 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 560 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
557 | return TX_DROP; | 561 | return TX_DROP; |
558 | } else | 562 | } else |
@@ -611,7 +615,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
611 | u32 len; | 615 | u32 len; |
612 | bool inval = false, rts = false, short_preamble = false; | 616 | bool inval = false, rts = false, short_preamble = false; |
613 | struct ieee80211_tx_rate_control txrc; | 617 | struct ieee80211_tx_rate_control txrc; |
614 | u32 sta_flags; | 618 | bool assoc = false; |
615 | 619 | ||
616 | memset(&txrc, 0, sizeof(txrc)); | 620 | memset(&txrc, 0, sizeof(txrc)); |
617 | 621 | ||
@@ -647,17 +651,17 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
647 | */ | 651 | */ |
648 | if (tx->sdata->vif.bss_conf.use_short_preamble && | 652 | if (tx->sdata->vif.bss_conf.use_short_preamble && |
649 | (ieee80211_is_data(hdr->frame_control) || | 653 | (ieee80211_is_data(hdr->frame_control) || |
650 | (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) | 654 | (tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) |
651 | txrc.short_preamble = short_preamble = true; | 655 | txrc.short_preamble = short_preamble = true; |
652 | 656 | ||
653 | sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; | 657 | if (tx->sta) |
658 | assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC); | ||
654 | 659 | ||
655 | /* | 660 | /* |
656 | * Lets not bother rate control if we're associated and cannot | 661 | * Lets not bother rate control if we're associated and cannot |
657 | * talk to the sta. This should not happen. | 662 | * talk to the sta. This should not happen. |
658 | */ | 663 | */ |
659 | if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && | 664 | if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc && |
660 | (sta_flags & WLAN_STA_ASSOC) && | ||
661 | !rate_usable_index_exists(sband, &tx->sta->sta), | 665 | !rate_usable_index_exists(sband, &tx->sta->sta), |
662 | "%s: Dropped data frame as no usable bitrate found while " | 666 | "%s: Dropped data frame as no usable bitrate found while " |
663 | "scanning and associated. Target station: " | 667 | "scanning and associated. Target station: " |
@@ -800,6 +804,9 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
800 | if (ieee80211_hdrlen(hdr->frame_control) < 24) | 804 | if (ieee80211_hdrlen(hdr->frame_control) < 24) |
801 | return TX_CONTINUE; | 805 | return TX_CONTINUE; |
802 | 806 | ||
807 | if (ieee80211_is_qos_nullfunc(hdr->frame_control)) | ||
808 | return TX_CONTINUE; | ||
809 | |||
803 | /* | 810 | /* |
804 | * Anything but QoS data that has a sequence number field | 811 | * Anything but QoS data that has a sequence number field |
805 | * (is long enough) gets a sequence number from the global | 812 | * (is long enough) gets a sequence number from the global |
@@ -891,7 +898,10 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
891 | int hdrlen; | 898 | int hdrlen; |
892 | int fragnum; | 899 | int fragnum; |
893 | 900 | ||
894 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) | 901 | if (info->flags & IEEE80211_TX_CTL_DONTFRAG) |
902 | return TX_CONTINUE; | ||
903 | |||
904 | if (tx->local->ops->set_frag_threshold) | ||
895 | return TX_CONTINUE; | 905 | return TX_CONTINUE; |
896 | 906 | ||
897 | /* | 907 | /* |
@@ -904,7 +914,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
904 | 914 | ||
905 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 915 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
906 | 916 | ||
907 | /* internal error, why is TX_FRAGMENTED set? */ | 917 | /* internal error, why isn't DONTFRAG set? */ |
908 | if (WARN_ON(skb->len + FCS_LEN <= frag_threshold)) | 918 | if (WARN_ON(skb->len + FCS_LEN <= frag_threshold)) |
909 | return TX_DROP; | 919 | return TX_DROP; |
910 | 920 | ||
@@ -1025,100 +1035,6 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) | |||
1025 | 1035 | ||
1026 | /* actual transmit path */ | 1036 | /* actual transmit path */ |
1027 | 1037 | ||
1028 | /* | ||
1029 | * deal with packet injection down monitor interface | ||
1030 | * with Radiotap Header -- only called for monitor mode interface | ||
1031 | */ | ||
1032 | static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | ||
1033 | struct sk_buff *skb) | ||
1034 | { | ||
1035 | /* | ||
1036 | * this is the moment to interpret and discard the radiotap header that | ||
1037 | * must be at the start of the packet injected in Monitor mode | ||
1038 | * | ||
1039 | * Need to take some care with endian-ness since radiotap | ||
1040 | * args are little-endian | ||
1041 | */ | ||
1042 | |||
1043 | struct ieee80211_radiotap_iterator iterator; | ||
1044 | struct ieee80211_radiotap_header *rthdr = | ||
1045 | (struct ieee80211_radiotap_header *) skb->data; | ||
1046 | bool hw_frag; | ||
1047 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1048 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, | ||
1049 | NULL); | ||
1050 | |||
1051 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1052 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | ||
1053 | |||
1054 | /* packet is fragmented in HW if we have a non-NULL driver callback */ | ||
1055 | hw_frag = (tx->local->ops->set_frag_threshold != NULL); | ||
1056 | |||
1057 | /* | ||
1058 | * for every radiotap entry that is present | ||
1059 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | ||
1060 | * entries present, or -EINVAL on error) | ||
1061 | */ | ||
1062 | |||
1063 | while (!ret) { | ||
1064 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
1065 | |||
1066 | if (ret) | ||
1067 | continue; | ||
1068 | |||
1069 | /* see if this argument is something we can use */ | ||
1070 | switch (iterator.this_arg_index) { | ||
1071 | /* | ||
1072 | * You must take care when dereferencing iterator.this_arg | ||
1073 | * for multibyte types... the pointer is not aligned. Use | ||
1074 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
1075 | * iterator.this_arg for type "type" safely on all arches. | ||
1076 | */ | ||
1077 | case IEEE80211_RADIOTAP_FLAGS: | ||
1078 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | ||
1079 | /* | ||
1080 | * this indicates that the skb we have been | ||
1081 | * handed has the 32-bit FCS CRC at the end... | ||
1082 | * we should react to that by snipping it off | ||
1083 | * because it will be recomputed and added | ||
1084 | * on transmission | ||
1085 | */ | ||
1086 | if (skb->len < (iterator._max_length + FCS_LEN)) | ||
1087 | return false; | ||
1088 | |||
1089 | skb_trim(skb, skb->len - FCS_LEN); | ||
1090 | } | ||
1091 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | ||
1092 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1093 | if ((*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) && | ||
1094 | !hw_frag) | ||
1095 | tx->flags |= IEEE80211_TX_FRAGMENTED; | ||
1096 | break; | ||
1097 | |||
1098 | /* | ||
1099 | * Please update the file | ||
1100 | * Documentation/networking/mac80211-injection.txt | ||
1101 | * when parsing new fields here. | ||
1102 | */ | ||
1103 | |||
1104 | default: | ||
1105 | break; | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1109 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | ||
1110 | return false; | ||
1111 | |||
1112 | /* | ||
1113 | * remove the radiotap header | ||
1114 | * iterator->_max_length was sanity-checked against | ||
1115 | * skb->len by iterator init | ||
1116 | */ | ||
1117 | skb_pull(skb, iterator._max_length); | ||
1118 | |||
1119 | return true; | ||
1120 | } | ||
1121 | |||
1122 | static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | 1038 | static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, |
1123 | struct sk_buff *skb, | 1039 | struct sk_buff *skb, |
1124 | struct ieee80211_tx_info *info, | 1040 | struct ieee80211_tx_info *info, |
@@ -1183,7 +1099,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1183 | struct ieee80211_local *local = sdata->local; | 1099 | struct ieee80211_local *local = sdata->local; |
1184 | struct ieee80211_hdr *hdr; | 1100 | struct ieee80211_hdr *hdr; |
1185 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1101 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1186 | int hdrlen, tid; | 1102 | int tid; |
1187 | u8 *qc; | 1103 | u8 *qc; |
1188 | 1104 | ||
1189 | memset(tx, 0, sizeof(*tx)); | 1105 | memset(tx, 0, sizeof(*tx)); |
@@ -1191,26 +1107,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1191 | tx->local = local; | 1107 | tx->local = local; |
1192 | tx->sdata = sdata; | 1108 | tx->sdata = sdata; |
1193 | tx->channel = local->hw.conf.channel; | 1109 | tx->channel = local->hw.conf.channel; |
1194 | /* | ||
1195 | * Set this flag (used below to indicate "automatic fragmentation"), | ||
1196 | * it will be cleared/left by radiotap as desired. | ||
1197 | * Only valid when fragmentation is done by the stack. | ||
1198 | */ | ||
1199 | if (!local->ops->set_frag_threshold) | ||
1200 | tx->flags |= IEEE80211_TX_FRAGMENTED; | ||
1201 | |||
1202 | /* process and remove the injection radiotap header */ | ||
1203 | if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) { | ||
1204 | if (!__ieee80211_parse_tx_radiotap(tx, skb)) | ||
1205 | return TX_DROP; | ||
1206 | |||
1207 | /* | ||
1208 | * __ieee80211_parse_tx_radiotap has now removed | ||
1209 | * the radiotap header that was present and pre-filled | ||
1210 | * 'tx' with tx control information. | ||
1211 | */ | ||
1212 | info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP; | ||
1213 | } | ||
1214 | 1110 | ||
1215 | /* | 1111 | /* |
1216 | * If this flag is set to true anywhere, and we get here, | 1112 | * If this flag is set to true anywhere, and we get here, |
@@ -1232,7 +1128,9 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1232 | tx->sta = sta_info_get(sdata, hdr->addr1); | 1128 | tx->sta = sta_info_get(sdata, hdr->addr1); |
1233 | 1129 | ||
1234 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && | 1130 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && |
1235 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { | 1131 | !ieee80211_is_qos_nullfunc(hdr->frame_control) && |
1132 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) && | ||
1133 | !(local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) { | ||
1236 | struct tid_ampdu_tx *tid_tx; | 1134 | struct tid_ampdu_tx *tid_tx; |
1237 | 1135 | ||
1238 | qc = ieee80211_get_qos_ctl(hdr); | 1136 | qc = ieee80211_get_qos_ctl(hdr); |
@@ -1257,29 +1155,25 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1257 | tx->flags |= IEEE80211_TX_UNICAST; | 1155 | tx->flags |= IEEE80211_TX_UNICAST; |
1258 | if (unlikely(local->wifi_wme_noack_test)) | 1156 | if (unlikely(local->wifi_wme_noack_test)) |
1259 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | 1157 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
1260 | else | 1158 | /* |
1261 | info->flags &= ~IEEE80211_TX_CTL_NO_ACK; | 1159 | * Flags are initialized to 0. Hence, no need to |
1160 | * explicitly unset IEEE80211_TX_CTL_NO_ACK since | ||
1161 | * it might already be set for injected frames. | ||
1162 | */ | ||
1262 | } | 1163 | } |
1263 | 1164 | ||
1264 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { | 1165 | if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) { |
1265 | if ((tx->flags & IEEE80211_TX_UNICAST) && | 1166 | if (!(tx->flags & IEEE80211_TX_UNICAST) || |
1266 | skb->len + FCS_LEN > local->hw.wiphy->frag_threshold && | 1167 | skb->len + FCS_LEN <= local->hw.wiphy->frag_threshold || |
1267 | !(info->flags & IEEE80211_TX_CTL_AMPDU)) | 1168 | info->flags & IEEE80211_TX_CTL_AMPDU) |
1268 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 1169 | info->flags |= IEEE80211_TX_CTL_DONTFRAG; |
1269 | else | ||
1270 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | ||
1271 | } | 1170 | } |
1272 | 1171 | ||
1273 | if (!tx->sta) | 1172 | if (!tx->sta) |
1274 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1173 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1275 | else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) | 1174 | else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) |
1276 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1175 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1277 | 1176 | ||
1278 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1279 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | ||
1280 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; | ||
1281 | tx->ethertype = (pos[0] << 8) | pos[1]; | ||
1282 | } | ||
1283 | info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT; | 1177 | info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT; |
1284 | 1178 | ||
1285 | return TX_CONTINUE; | 1179 | return TX_CONTINUE; |
@@ -1490,11 +1384,6 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, | |||
1490 | tail_need = max_t(int, tail_need, 0); | 1384 | tail_need = max_t(int, tail_need, 0); |
1491 | } | 1385 | } |
1492 | 1386 | ||
1493 | if (head_need || tail_need) { | ||
1494 | /* Sorry. Can't account for this any more */ | ||
1495 | skb_orphan(skb); | ||
1496 | } | ||
1497 | |||
1498 | if (skb_cloned(skb)) | 1387 | if (skb_cloned(skb)) |
1499 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | 1388 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); |
1500 | else if (head_need || tail_need) | 1389 | else if (head_need || tail_need) |
@@ -1508,67 +1397,19 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, | |||
1508 | return -ENOMEM; | 1397 | return -ENOMEM; |
1509 | } | 1398 | } |
1510 | 1399 | ||
1511 | /* update truesize too */ | ||
1512 | skb->truesize += head_need + tail_need; | ||
1513 | |||
1514 | return 0; | 1400 | return 0; |
1515 | } | 1401 | } |
1516 | 1402 | ||
1517 | static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | 1403 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) |
1518 | struct sk_buff *skb) | ||
1519 | { | 1404 | { |
1520 | struct ieee80211_local *local = sdata->local; | 1405 | struct ieee80211_local *local = sdata->local; |
1521 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1406 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1522 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1407 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1523 | struct ieee80211_sub_if_data *tmp_sdata; | ||
1524 | int headroom; | 1408 | int headroom; |
1525 | bool may_encrypt; | 1409 | bool may_encrypt; |
1526 | 1410 | ||
1527 | rcu_read_lock(); | 1411 | rcu_read_lock(); |
1528 | 1412 | ||
1529 | if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { | ||
1530 | int hdrlen; | ||
1531 | u16 len_rthdr; | ||
1532 | |||
1533 | info->flags |= IEEE80211_TX_CTL_INJECTED | | ||
1534 | IEEE80211_TX_INTFL_HAS_RADIOTAP; | ||
1535 | |||
1536 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | ||
1537 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); | ||
1538 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1539 | |||
1540 | /* check the header is complete in the frame */ | ||
1541 | if (likely(skb->len >= len_rthdr + hdrlen)) { | ||
1542 | /* | ||
1543 | * We process outgoing injected frames that have a | ||
1544 | * local address we handle as though they are our | ||
1545 | * own frames. | ||
1546 | * This code here isn't entirely correct, the local | ||
1547 | * MAC address is not necessarily enough to find | ||
1548 | * the interface to use; for that proper VLAN/WDS | ||
1549 | * support we will need a different mechanism. | ||
1550 | */ | ||
1551 | |||
1552 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, | ||
1553 | list) { | ||
1554 | if (!ieee80211_sdata_running(tmp_sdata)) | ||
1555 | continue; | ||
1556 | if (tmp_sdata->vif.type == | ||
1557 | NL80211_IFTYPE_MONITOR || | ||
1558 | tmp_sdata->vif.type == | ||
1559 | NL80211_IFTYPE_AP_VLAN || | ||
1560 | tmp_sdata->vif.type == | ||
1561 | NL80211_IFTYPE_WDS) | ||
1562 | continue; | ||
1563 | if (compare_ether_addr(tmp_sdata->vif.addr, | ||
1564 | hdr->addr2) == 0) { | ||
1565 | sdata = tmp_sdata; | ||
1566 | break; | ||
1567 | } | ||
1568 | } | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); | 1413 | may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); |
1573 | 1414 | ||
1574 | headroom = local->tx_headroom; | 1415 | headroom = local->tx_headroom; |
@@ -1595,11 +1436,94 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1595 | return; | 1436 | return; |
1596 | } | 1437 | } |
1597 | 1438 | ||
1598 | ieee80211_set_qos_hdr(local, skb); | 1439 | ieee80211_set_qos_hdr(sdata, skb); |
1599 | ieee80211_tx(sdata, skb, false); | 1440 | ieee80211_tx(sdata, skb, false); |
1600 | rcu_read_unlock(); | 1441 | rcu_read_unlock(); |
1601 | } | 1442 | } |
1602 | 1443 | ||
1444 | static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) | ||
1445 | { | ||
1446 | struct ieee80211_radiotap_iterator iterator; | ||
1447 | struct ieee80211_radiotap_header *rthdr = | ||
1448 | (struct ieee80211_radiotap_header *) skb->data; | ||
1449 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1450 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, | ||
1451 | NULL); | ||
1452 | u16 txflags; | ||
1453 | |||
1454 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | | ||
1455 | IEEE80211_TX_CTL_DONTFRAG; | ||
1456 | |||
1457 | /* | ||
1458 | * for every radiotap entry that is present | ||
1459 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | ||
1460 | * entries present, or -EINVAL on error) | ||
1461 | */ | ||
1462 | |||
1463 | while (!ret) { | ||
1464 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
1465 | |||
1466 | if (ret) | ||
1467 | continue; | ||
1468 | |||
1469 | /* see if this argument is something we can use */ | ||
1470 | switch (iterator.this_arg_index) { | ||
1471 | /* | ||
1472 | * You must take care when dereferencing iterator.this_arg | ||
1473 | * for multibyte types... the pointer is not aligned. Use | ||
1474 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
1475 | * iterator.this_arg for type "type" safely on all arches. | ||
1476 | */ | ||
1477 | case IEEE80211_RADIOTAP_FLAGS: | ||
1478 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | ||
1479 | /* | ||
1480 | * this indicates that the skb we have been | ||
1481 | * handed has the 32-bit FCS CRC at the end... | ||
1482 | * we should react to that by snipping it off | ||
1483 | * because it will be recomputed and added | ||
1484 | * on transmission | ||
1485 | */ | ||
1486 | if (skb->len < (iterator._max_length + FCS_LEN)) | ||
1487 | return false; | ||
1488 | |||
1489 | skb_trim(skb, skb->len - FCS_LEN); | ||
1490 | } | ||
1491 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | ||
1492 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1493 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | ||
1494 | info->flags &= ~IEEE80211_TX_CTL_DONTFRAG; | ||
1495 | break; | ||
1496 | |||
1497 | case IEEE80211_RADIOTAP_TX_FLAGS: | ||
1498 | txflags = get_unaligned_le16(iterator.this_arg); | ||
1499 | if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK) | ||
1500 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1501 | break; | ||
1502 | |||
1503 | /* | ||
1504 | * Please update the file | ||
1505 | * Documentation/networking/mac80211-injection.txt | ||
1506 | * when parsing new fields here. | ||
1507 | */ | ||
1508 | |||
1509 | default: | ||
1510 | break; | ||
1511 | } | ||
1512 | } | ||
1513 | |||
1514 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | ||
1515 | return false; | ||
1516 | |||
1517 | /* | ||
1518 | * remove the radiotap header | ||
1519 | * iterator->_max_length was sanity-checked against | ||
1520 | * skb->len by iterator init | ||
1521 | */ | ||
1522 | skb_pull(skb, iterator._max_length); | ||
1523 | |||
1524 | return true; | ||
1525 | } | ||
1526 | |||
1603 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | 1527 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, |
1604 | struct net_device *dev) | 1528 | struct net_device *dev) |
1605 | { | 1529 | { |
@@ -1608,7 +1532,10 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1608 | struct ieee80211_radiotap_header *prthdr = | 1532 | struct ieee80211_radiotap_header *prthdr = |
1609 | (struct ieee80211_radiotap_header *)skb->data; | 1533 | (struct ieee80211_radiotap_header *)skb->data; |
1610 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1534 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1535 | struct ieee80211_hdr *hdr; | ||
1536 | struct ieee80211_sub_if_data *tmp_sdata, *sdata; | ||
1611 | u16 len_rthdr; | 1537 | u16 len_rthdr; |
1538 | int hdrlen; | ||
1612 | 1539 | ||
1613 | /* | 1540 | /* |
1614 | * Frame injection is not allowed if beaconing is not allowed | 1541 | * Frame injection is not allowed if beaconing is not allowed |
@@ -1659,12 +1586,65 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1659 | skb_set_network_header(skb, len_rthdr); | 1586 | skb_set_network_header(skb, len_rthdr); |
1660 | skb_set_transport_header(skb, len_rthdr); | 1587 | skb_set_transport_header(skb, len_rthdr); |
1661 | 1588 | ||
1589 | if (skb->len < len_rthdr + 2) | ||
1590 | goto fail; | ||
1591 | |||
1592 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); | ||
1593 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1594 | |||
1595 | if (skb->len < len_rthdr + hdrlen) | ||
1596 | goto fail; | ||
1597 | |||
1598 | /* | ||
1599 | * Initialize skb->protocol if the injected frame is a data frame | ||
1600 | * carrying a rfc1042 header | ||
1601 | */ | ||
1602 | if (ieee80211_is_data(hdr->frame_control) && | ||
1603 | skb->len >= len_rthdr + hdrlen + sizeof(rfc1042_header) + 2) { | ||
1604 | u8 *payload = (u8 *)hdr + hdrlen; | ||
1605 | |||
1606 | if (compare_ether_addr(payload, rfc1042_header) == 0) | ||
1607 | skb->protocol = cpu_to_be16((payload[6] << 8) | | ||
1608 | payload[7]); | ||
1609 | } | ||
1610 | |||
1662 | memset(info, 0, sizeof(*info)); | 1611 | memset(info, 0, sizeof(*info)); |
1663 | 1612 | ||
1664 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 1613 | info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS | |
1614 | IEEE80211_TX_CTL_INJECTED; | ||
1615 | |||
1616 | /* process and remove the injection radiotap header */ | ||
1617 | if (!ieee80211_parse_tx_radiotap(skb)) | ||
1618 | goto fail; | ||
1619 | |||
1620 | rcu_read_lock(); | ||
1621 | |||
1622 | /* | ||
1623 | * We process outgoing injected frames that have a local address | ||
1624 | * we handle as though they are non-injected frames. | ||
1625 | * This code here isn't entirely correct, the local MAC address | ||
1626 | * isn't always enough to find the interface to use; for proper | ||
1627 | * VLAN/WDS support we will need a different mechanism (which | ||
1628 | * likely isn't going to be monitor interfaces). | ||
1629 | */ | ||
1630 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1631 | |||
1632 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) { | ||
1633 | if (!ieee80211_sdata_running(tmp_sdata)) | ||
1634 | continue; | ||
1635 | if (tmp_sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
1636 | tmp_sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
1637 | tmp_sdata->vif.type == NL80211_IFTYPE_WDS) | ||
1638 | continue; | ||
1639 | if (compare_ether_addr(tmp_sdata->vif.addr, hdr->addr2) == 0) { | ||
1640 | sdata = tmp_sdata; | ||
1641 | break; | ||
1642 | } | ||
1643 | } | ||
1644 | |||
1645 | ieee80211_xmit(sdata, skb); | ||
1646 | rcu_read_unlock(); | ||
1665 | 1647 | ||
1666 | /* pass the radiotap header up to xmit */ | ||
1667 | ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb); | ||
1668 | return NETDEV_TX_OK; | 1648 | return NETDEV_TX_OK; |
1669 | 1649 | ||
1670 | fail: | 1650 | fail: |
@@ -1703,8 +1683,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1703 | int encaps_len, skip_header_bytes; | 1683 | int encaps_len, skip_header_bytes; |
1704 | int nh_pos, h_pos; | 1684 | int nh_pos, h_pos; |
1705 | struct sta_info *sta = NULL; | 1685 | struct sta_info *sta = NULL; |
1706 | u32 sta_flags = 0; | 1686 | bool wme_sta = false, authorized = false, tdls_auth = false; |
1707 | struct sk_buff *tmp_skb; | 1687 | struct sk_buff *tmp_skb; |
1688 | bool tdls_direct = false; | ||
1708 | 1689 | ||
1709 | if (unlikely(skb->len < ETH_HLEN)) { | 1690 | if (unlikely(skb->len < ETH_HLEN)) { |
1710 | ret = NETDEV_TX_OK; | 1691 | ret = NETDEV_TX_OK; |
@@ -1728,7 +1709,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1728 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1709 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1729 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1710 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1730 | hdrlen = 30; | 1711 | hdrlen = 30; |
1731 | sta_flags = get_sta_flags(sta); | 1712 | authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); |
1713 | wme_sta = test_sta_flag(sta, WLAN_STA_WME); | ||
1732 | } | 1714 | } |
1733 | rcu_read_unlock(); | 1715 | rcu_read_unlock(); |
1734 | if (sta) | 1716 | if (sta) |
@@ -1816,11 +1798,50 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1816 | break; | 1798 | break; |
1817 | #endif | 1799 | #endif |
1818 | case NL80211_IFTYPE_STATION: | 1800 | case NL80211_IFTYPE_STATION: |
1819 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); | 1801 | if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { |
1820 | if (sdata->u.mgd.use_4addr && | 1802 | bool tdls_peer = false; |
1821 | cpu_to_be16(ethertype) != sdata->control_port_protocol) { | 1803 | |
1822 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1804 | rcu_read_lock(); |
1805 | sta = sta_info_get(sdata, skb->data); | ||
1806 | if (sta) { | ||
1807 | authorized = test_sta_flag(sta, | ||
1808 | WLAN_STA_AUTHORIZED); | ||
1809 | wme_sta = test_sta_flag(sta, WLAN_STA_WME); | ||
1810 | tdls_peer = test_sta_flag(sta, | ||
1811 | WLAN_STA_TDLS_PEER); | ||
1812 | tdls_auth = test_sta_flag(sta, | ||
1813 | WLAN_STA_TDLS_PEER_AUTH); | ||
1814 | } | ||
1815 | rcu_read_unlock(); | ||
1816 | |||
1817 | /* | ||
1818 | * If the TDLS link is enabled, send everything | ||
1819 | * directly. Otherwise, allow TDLS setup frames | ||
1820 | * to be transmitted indirectly. | ||
1821 | */ | ||
1822 | tdls_direct = tdls_peer && (tdls_auth || | ||
1823 | !(ethertype == ETH_P_TDLS && skb->len > 14 && | ||
1824 | skb->data[14] == WLAN_TDLS_SNAP_RFTYPE)); | ||
1825 | } | ||
1826 | |||
1827 | if (tdls_direct) { | ||
1828 | /* link during setup - throw out frames to peer */ | ||
1829 | if (!tdls_auth) { | ||
1830 | ret = NETDEV_TX_OK; | ||
1831 | goto fail; | ||
1832 | } | ||
1833 | |||
1834 | /* DA SA BSSID */ | ||
1835 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | ||
1836 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
1837 | memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN); | ||
1838 | hdrlen = 24; | ||
1839 | } else if (sdata->u.mgd.use_4addr && | ||
1840 | cpu_to_be16(ethertype) != sdata->control_port_protocol) { | ||
1841 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | | ||
1842 | IEEE80211_FCTL_TODS); | ||
1823 | /* RA TA DA SA */ | 1843 | /* RA TA DA SA */ |
1844 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); | ||
1824 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); | 1845 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1825 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1846 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1826 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1847 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
@@ -1828,6 +1849,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1828 | } else { | 1849 | } else { |
1829 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | 1850 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); |
1830 | /* BSSID SA DA */ | 1851 | /* BSSID SA DA */ |
1852 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); | ||
1831 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1853 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
1832 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1854 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1833 | hdrlen = 24; | 1855 | hdrlen = 24; |
@@ -1853,13 +1875,19 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1853 | if (!is_multicast_ether_addr(hdr.addr1)) { | 1875 | if (!is_multicast_ether_addr(hdr.addr1)) { |
1854 | rcu_read_lock(); | 1876 | rcu_read_lock(); |
1855 | sta = sta_info_get(sdata, hdr.addr1); | 1877 | sta = sta_info_get(sdata, hdr.addr1); |
1856 | if (sta) | 1878 | if (sta) { |
1857 | sta_flags = get_sta_flags(sta); | 1879 | authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); |
1880 | wme_sta = test_sta_flag(sta, WLAN_STA_WME); | ||
1881 | } | ||
1858 | rcu_read_unlock(); | 1882 | rcu_read_unlock(); |
1859 | } | 1883 | } |
1860 | 1884 | ||
1885 | /* For mesh, the use of the QoS header is mandatory */ | ||
1886 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1887 | wme_sta = true; | ||
1888 | |||
1861 | /* receiver and we are QoS enabled, use a QoS type frame */ | 1889 | /* receiver and we are QoS enabled, use a QoS type frame */ |
1862 | if ((sta_flags & WLAN_STA_WME) && local->hw.queues >= 4) { | 1890 | if (wme_sta && local->hw.queues >= 4) { |
1863 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | 1891 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1864 | hdrlen += 2; | 1892 | hdrlen += 2; |
1865 | } | 1893 | } |
@@ -1868,12 +1896,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1868 | * Drop unicast frames to unauthorised stations unless they are | 1896 | * Drop unicast frames to unauthorised stations unless they are |
1869 | * EAPOL frames from the local station. | 1897 | * EAPOL frames from the local station. |
1870 | */ | 1898 | */ |
1871 | if (!ieee80211_vif_is_mesh(&sdata->vif) && | 1899 | if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) && |
1872 | unlikely(!is_multicast_ether_addr(hdr.addr1) && | 1900 | !is_multicast_ether_addr(hdr.addr1) && !authorized && |
1873 | !(sta_flags & WLAN_STA_AUTHORIZED) && | 1901 | (cpu_to_be16(ethertype) != sdata->control_port_protocol || |
1874 | !(cpu_to_be16(ethertype) == sdata->control_port_protocol && | 1902 | compare_ether_addr(sdata->vif.addr, skb->data + ETH_ALEN)))) { |
1875 | compare_ether_addr(sdata->vif.addr, | ||
1876 | skb->data + ETH_ALEN) == 0))) { | ||
1877 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1903 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1878 | if (net_ratelimit()) | 1904 | if (net_ratelimit()) |
1879 | printk(KERN_DEBUG "%s: dropped frame to %pM" | 1905 | printk(KERN_DEBUG "%s: dropped frame to %pM" |
@@ -2275,13 +2301,23 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2275 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 2301 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
2276 | mgmt->u.beacon.beacon_int = | 2302 | mgmt->u.beacon.beacon_int = |
2277 | cpu_to_le16(sdata->vif.bss_conf.beacon_int); | 2303 | cpu_to_le16(sdata->vif.bss_conf.beacon_int); |
2278 | mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ | 2304 | mgmt->u.beacon.capab_info |= cpu_to_le16( |
2305 | sdata->u.mesh.security ? WLAN_CAPABILITY_PRIVACY : 0); | ||
2279 | 2306 | ||
2280 | pos = skb_put(skb, 2); | 2307 | pos = skb_put(skb, 2); |
2281 | *pos++ = WLAN_EID_SSID; | 2308 | *pos++ = WLAN_EID_SSID; |
2282 | *pos++ = 0x0; | 2309 | *pos++ = 0x0; |
2283 | 2310 | ||
2284 | mesh_mgmt_ies_add(skb, sdata); | 2311 | if (ieee80211_add_srates_ie(&sdata->vif, skb) || |
2312 | mesh_add_ds_params_ie(skb, sdata) || | ||
2313 | ieee80211_add_ext_srates_ie(&sdata->vif, skb) || | ||
2314 | mesh_add_rsn_ie(skb, sdata) || | ||
2315 | mesh_add_meshid_ie(skb, sdata) || | ||
2316 | mesh_add_meshconf_ie(skb, sdata) || | ||
2317 | mesh_add_vendor_ies(skb, sdata)) { | ||
2318 | pr_err("o11s: couldn't add ies!\n"); | ||
2319 | goto out; | ||
2320 | } | ||
2285 | } else { | 2321 | } else { |
2286 | WARN_ON(1); | 2322 | WARN_ON(1); |
2287 | goto out; | 2323 | goto out; |
@@ -2335,11 +2371,9 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, | |||
2335 | local = sdata->local; | 2371 | local = sdata->local; |
2336 | 2372 | ||
2337 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); | 2373 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); |
2338 | if (!skb) { | 2374 | if (!skb) |
2339 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | ||
2340 | "pspoll template\n", sdata->name); | ||
2341 | return NULL; | 2375 | return NULL; |
2342 | } | 2376 | |
2343 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2377 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2344 | 2378 | ||
2345 | pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll)); | 2379 | pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll)); |
@@ -2375,11 +2409,9 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | |||
2375 | local = sdata->local; | 2409 | local = sdata->local; |
2376 | 2410 | ||
2377 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc)); | 2411 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc)); |
2378 | if (!skb) { | 2412 | if (!skb) |
2379 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " | ||
2380 | "template\n", sdata->name); | ||
2381 | return NULL; | 2413 | return NULL; |
2382 | } | 2414 | |
2383 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2415 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2384 | 2416 | ||
2385 | nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb, | 2417 | nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb, |
@@ -2414,11 +2446,8 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | |||
2414 | 2446 | ||
2415 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + | 2447 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + |
2416 | ie_ssid_len + ie_len); | 2448 | ie_ssid_len + ie_len); |
2417 | if (!skb) { | 2449 | if (!skb) |
2418 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | ||
2419 | "request template\n", sdata->name); | ||
2420 | return NULL; | 2450 | return NULL; |
2421 | } | ||
2422 | 2451 | ||
2423 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2452 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2424 | 2453 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ddeb1b998383..7439d26bf5f9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/etherdevice.h> | 19 | #include <linux/etherdevice.h> |
20 | #include <linux/if_arp.h> | 20 | #include <linux/if_arp.h> |
21 | #include <linux/bitmap.h> | 21 | #include <linux/bitmap.h> |
22 | #include <linux/crc32.h> | ||
23 | #include <net/net_namespace.h> | 22 | #include <net/net_namespace.h> |
24 | #include <net/cfg80211.h> | 23 | #include <net/cfg80211.h> |
25 | #include <net/rtnetlink.h> | 24 | #include <net/rtnetlink.h> |
@@ -368,14 +367,14 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
368 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 367 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
369 | } | 368 | } |
370 | 369 | ||
371 | int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | 370 | void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, |
372 | struct sk_buff_head *skbs, | 371 | struct sk_buff_head *skbs, |
373 | void (*fn)(void *data), void *data) | 372 | void (*fn)(void *data), void *data) |
374 | { | 373 | { |
375 | struct ieee80211_hw *hw = &local->hw; | 374 | struct ieee80211_hw *hw = &local->hw; |
376 | struct sk_buff *skb; | 375 | struct sk_buff *skb; |
377 | unsigned long flags; | 376 | unsigned long flags; |
378 | int queue, ret = 0, i; | 377 | int queue, i; |
379 | 378 | ||
380 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 379 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
381 | for (i = 0; i < hw->queues; i++) | 380 | for (i = 0; i < hw->queues; i++) |
@@ -390,7 +389,6 @@ int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
390 | continue; | 389 | continue; |
391 | } | 390 | } |
392 | 391 | ||
393 | ret++; | ||
394 | queue = skb_get_queue_mapping(skb); | 392 | queue = skb_get_queue_mapping(skb); |
395 | __skb_queue_tail(&local->pending[queue], skb); | 393 | __skb_queue_tail(&local->pending[queue], skb); |
396 | } | 394 | } |
@@ -402,14 +400,12 @@ int ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
402 | __ieee80211_wake_queue(hw, i, | 400 | __ieee80211_wake_queue(hw, i, |
403 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 401 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
404 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 402 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
405 | |||
406 | return ret; | ||
407 | } | 403 | } |
408 | 404 | ||
409 | int ieee80211_add_pending_skbs(struct ieee80211_local *local, | 405 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, |
410 | struct sk_buff_head *skbs) | 406 | struct sk_buff_head *skbs) |
411 | { | 407 | { |
412 | return ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); | 408 | ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); |
413 | } | 409 | } |
414 | 410 | ||
415 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 411 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
@@ -573,172 +569,6 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
573 | ieee802_11_parse_elems_crc(start, len, elems, 0, 0); | 569 | ieee802_11_parse_elems_crc(start, len, elems, 0, 0); |
574 | } | 570 | } |
575 | 571 | ||
576 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | ||
577 | struct ieee802_11_elems *elems, | ||
578 | u64 filter, u32 crc) | ||
579 | { | ||
580 | size_t left = len; | ||
581 | u8 *pos = start; | ||
582 | bool calc_crc = filter != 0; | ||
583 | |||
584 | memset(elems, 0, sizeof(*elems)); | ||
585 | elems->ie_start = start; | ||
586 | elems->total_len = len; | ||
587 | |||
588 | while (left >= 2) { | ||
589 | u8 id, elen; | ||
590 | |||
591 | id = *pos++; | ||
592 | elen = *pos++; | ||
593 | left -= 2; | ||
594 | |||
595 | if (elen > left) | ||
596 | break; | ||
597 | |||
598 | if (calc_crc && id < 64 && (filter & (1ULL << id))) | ||
599 | crc = crc32_be(crc, pos - 2, elen + 2); | ||
600 | |||
601 | switch (id) { | ||
602 | case WLAN_EID_SSID: | ||
603 | elems->ssid = pos; | ||
604 | elems->ssid_len = elen; | ||
605 | break; | ||
606 | case WLAN_EID_SUPP_RATES: | ||
607 | elems->supp_rates = pos; | ||
608 | elems->supp_rates_len = elen; | ||
609 | break; | ||
610 | case WLAN_EID_FH_PARAMS: | ||
611 | elems->fh_params = pos; | ||
612 | elems->fh_params_len = elen; | ||
613 | break; | ||
614 | case WLAN_EID_DS_PARAMS: | ||
615 | elems->ds_params = pos; | ||
616 | elems->ds_params_len = elen; | ||
617 | break; | ||
618 | case WLAN_EID_CF_PARAMS: | ||
619 | elems->cf_params = pos; | ||
620 | elems->cf_params_len = elen; | ||
621 | break; | ||
622 | case WLAN_EID_TIM: | ||
623 | if (elen >= sizeof(struct ieee80211_tim_ie)) { | ||
624 | elems->tim = (void *)pos; | ||
625 | elems->tim_len = elen; | ||
626 | } | ||
627 | break; | ||
628 | case WLAN_EID_IBSS_PARAMS: | ||
629 | elems->ibss_params = pos; | ||
630 | elems->ibss_params_len = elen; | ||
631 | break; | ||
632 | case WLAN_EID_CHALLENGE: | ||
633 | elems->challenge = pos; | ||
634 | elems->challenge_len = elen; | ||
635 | break; | ||
636 | case WLAN_EID_VENDOR_SPECIFIC: | ||
637 | if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && | ||
638 | pos[2] == 0xf2) { | ||
639 | /* Microsoft OUI (00:50:F2) */ | ||
640 | |||
641 | if (calc_crc) | ||
642 | crc = crc32_be(crc, pos - 2, elen + 2); | ||
643 | |||
644 | if (pos[3] == 1) { | ||
645 | /* OUI Type 1 - WPA IE */ | ||
646 | elems->wpa = pos; | ||
647 | elems->wpa_len = elen; | ||
648 | } else if (elen >= 5 && pos[3] == 2) { | ||
649 | /* OUI Type 2 - WMM IE */ | ||
650 | if (pos[4] == 0) { | ||
651 | elems->wmm_info = pos; | ||
652 | elems->wmm_info_len = elen; | ||
653 | } else if (pos[4] == 1) { | ||
654 | elems->wmm_param = pos; | ||
655 | elems->wmm_param_len = elen; | ||
656 | } | ||
657 | } | ||
658 | } | ||
659 | break; | ||
660 | case WLAN_EID_RSN: | ||
661 | elems->rsn = pos; | ||
662 | elems->rsn_len = elen; | ||
663 | break; | ||
664 | case WLAN_EID_ERP_INFO: | ||
665 | elems->erp_info = pos; | ||
666 | elems->erp_info_len = elen; | ||
667 | break; | ||
668 | case WLAN_EID_EXT_SUPP_RATES: | ||
669 | elems->ext_supp_rates = pos; | ||
670 | elems->ext_supp_rates_len = elen; | ||
671 | break; | ||
672 | case WLAN_EID_HT_CAPABILITY: | ||
673 | if (elen >= sizeof(struct ieee80211_ht_cap)) | ||
674 | elems->ht_cap_elem = (void *)pos; | ||
675 | break; | ||
676 | case WLAN_EID_HT_INFORMATION: | ||
677 | if (elen >= sizeof(struct ieee80211_ht_info)) | ||
678 | elems->ht_info_elem = (void *)pos; | ||
679 | break; | ||
680 | case WLAN_EID_MESH_ID: | ||
681 | elems->mesh_id = pos; | ||
682 | elems->mesh_id_len = elen; | ||
683 | break; | ||
684 | case WLAN_EID_MESH_CONFIG: | ||
685 | if (elen >= sizeof(struct ieee80211_meshconf_ie)) | ||
686 | elems->mesh_config = (void *)pos; | ||
687 | break; | ||
688 | case WLAN_EID_PEER_LINK: | ||
689 | elems->peer_link = pos; | ||
690 | elems->peer_link_len = elen; | ||
691 | break; | ||
692 | case WLAN_EID_PREQ: | ||
693 | elems->preq = pos; | ||
694 | elems->preq_len = elen; | ||
695 | break; | ||
696 | case WLAN_EID_PREP: | ||
697 | elems->prep = pos; | ||
698 | elems->prep_len = elen; | ||
699 | break; | ||
700 | case WLAN_EID_PERR: | ||
701 | elems->perr = pos; | ||
702 | elems->perr_len = elen; | ||
703 | break; | ||
704 | case WLAN_EID_RANN: | ||
705 | if (elen >= sizeof(struct ieee80211_rann_ie)) | ||
706 | elems->rann = (void *)pos; | ||
707 | break; | ||
708 | case WLAN_EID_CHANNEL_SWITCH: | ||
709 | elems->ch_switch_elem = pos; | ||
710 | elems->ch_switch_elem_len = elen; | ||
711 | break; | ||
712 | case WLAN_EID_QUIET: | ||
713 | if (!elems->quiet_elem) { | ||
714 | elems->quiet_elem = pos; | ||
715 | elems->quiet_elem_len = elen; | ||
716 | } | ||
717 | elems->num_of_quiet_elem++; | ||
718 | break; | ||
719 | case WLAN_EID_COUNTRY: | ||
720 | elems->country_elem = pos; | ||
721 | elems->country_elem_len = elen; | ||
722 | break; | ||
723 | case WLAN_EID_PWR_CONSTRAINT: | ||
724 | elems->pwr_constr_elem = pos; | ||
725 | elems->pwr_constr_elem_len = elen; | ||
726 | break; | ||
727 | case WLAN_EID_TIMEOUT_INTERVAL: | ||
728 | elems->timeout_int = pos; | ||
729 | elems->timeout_int_len = elen; | ||
730 | break; | ||
731 | default: | ||
732 | break; | ||
733 | } | ||
734 | |||
735 | left -= elen; | ||
736 | pos += elen; | ||
737 | } | ||
738 | |||
739 | return crc; | ||
740 | } | ||
741 | |||
742 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | 572 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) |
743 | { | 573 | { |
744 | struct ieee80211_local *local = sdata->local; | 574 | struct ieee80211_local *local = sdata->local; |
@@ -799,8 +629,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
799 | 629 | ||
800 | qparam.uapsd = false; | 630 | qparam.uapsd = false; |
801 | 631 | ||
802 | local->tx_conf[queue] = qparam; | 632 | sdata->tx_conf[queue] = qparam; |
803 | drv_conf_tx(local, queue, &qparam); | 633 | drv_conf_tx(local, sdata, queue, &qparam); |
804 | } | 634 | } |
805 | 635 | ||
806 | /* after reinitialize QoS TX queues setting to default, | 636 | /* after reinitialize QoS TX queues setting to default, |
@@ -874,11 +704,9 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
874 | 704 | ||
875 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 705 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
876 | sizeof(*mgmt) + 6 + extra_len); | 706 | sizeof(*mgmt) + 6 + extra_len); |
877 | if (!skb) { | 707 | if (!skb) |
878 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " | ||
879 | "frame\n", sdata->name); | ||
880 | return; | 708 | return; |
881 | } | 709 | |
882 | skb_reserve(skb, local->hw.extra_tx_headroom); | 710 | skb_reserve(skb, local->hw.extra_tx_headroom); |
883 | 711 | ||
884 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); | 712 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); |
@@ -1031,11 +859,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1031 | 859 | ||
1032 | /* FIXME: come up with a proper value */ | 860 | /* FIXME: come up with a proper value */ |
1033 | buf = kmalloc(200 + ie_len, GFP_KERNEL); | 861 | buf = kmalloc(200 + ie_len, GFP_KERNEL); |
1034 | if (!buf) { | 862 | if (!buf) |
1035 | printk(KERN_DEBUG "%s: failed to allocate temporary IE " | ||
1036 | "buffer\n", sdata->name); | ||
1037 | return NULL; | 863 | return NULL; |
1038 | } | ||
1039 | 864 | ||
1040 | /* | 865 | /* |
1041 | * Do not send DS Channel parameter for directed probe requests | 866 | * Do not send DS Channel parameter for directed probe requests |
@@ -1071,14 +896,18 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1071 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 896 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1072 | const u8 *ssid, size_t ssid_len, | 897 | const u8 *ssid, size_t ssid_len, |
1073 | const u8 *ie, size_t ie_len, | 898 | const u8 *ie, size_t ie_len, |
1074 | u32 ratemask, bool directed) | 899 | u32 ratemask, bool directed, bool no_cck) |
1075 | { | 900 | { |
1076 | struct sk_buff *skb; | 901 | struct sk_buff *skb; |
1077 | 902 | ||
1078 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, | 903 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, |
1079 | ie, ie_len, directed); | 904 | ie, ie_len, directed); |
1080 | if (skb) | 905 | if (skb) { |
906 | if (no_cck) | ||
907 | IEEE80211_SKB_CB(skb)->flags |= | ||
908 | IEEE80211_TX_CTL_NO_CCK_RATE; | ||
1081 | ieee80211_tx_skb(sdata, skb); | 909 | ieee80211_tx_skb(sdata, skb); |
910 | } | ||
1082 | } | 911 | } |
1083 | 912 | ||
1084 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 913 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
@@ -1205,14 +1034,22 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1205 | struct ieee80211_sub_if_data, | 1034 | struct ieee80211_sub_if_data, |
1206 | u.ap); | 1035 | u.ap); |
1207 | 1036 | ||
1037 | memset(&sta->sta.drv_priv, 0, hw->sta_data_size); | ||
1208 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); | 1038 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); |
1209 | } | 1039 | } |
1210 | } | 1040 | } |
1211 | mutex_unlock(&local->sta_mtx); | 1041 | mutex_unlock(&local->sta_mtx); |
1212 | 1042 | ||
1213 | /* reconfigure tx conf */ | 1043 | /* reconfigure tx conf */ |
1214 | for (i = 0; i < hw->queues; i++) | 1044 | list_for_each_entry(sdata, &local->interfaces, list) { |
1215 | drv_conf_tx(local, i, &local->tx_conf[i]); | 1045 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
1046 | sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
1047 | !ieee80211_sdata_running(sdata)) | ||
1048 | continue; | ||
1049 | |||
1050 | for (i = 0; i < hw->queues; i++) | ||
1051 | drv_conf_tx(local, sdata, i, &sdata->tx_conf[i]); | ||
1052 | } | ||
1216 | 1053 | ||
1217 | /* reconfigure hardware */ | 1054 | /* reconfigure hardware */ |
1218 | ieee80211_hw_config(local, ~0); | 1055 | ieee80211_hw_config(local, ~0); |
@@ -1248,6 +1085,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1248 | changed |= BSS_CHANGED_IBSS; | 1085 | changed |= BSS_CHANGED_IBSS; |
1249 | /* fall through */ | 1086 | /* fall through */ |
1250 | case NL80211_IFTYPE_AP: | 1087 | case NL80211_IFTYPE_AP: |
1088 | changed |= BSS_CHANGED_SSID; | ||
1089 | /* fall through */ | ||
1251 | case NL80211_IFTYPE_MESH_POINT: | 1090 | case NL80211_IFTYPE_MESH_POINT: |
1252 | changed |= BSS_CHANGED_BEACON | | 1091 | changed |= BSS_CHANGED_BEACON | |
1253 | BSS_CHANGED_BEACON_ENABLED; | 1092 | BSS_CHANGED_BEACON_ENABLED; |
@@ -1283,7 +1122,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1283 | 1122 | ||
1284 | list_for_each_entry(sta, &local->sta_list, list) { | 1123 | list_for_each_entry(sta, &local->sta_list, list) { |
1285 | ieee80211_sta_tear_down_BA_sessions(sta, true); | 1124 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
1286 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); | 1125 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); |
1287 | } | 1126 | } |
1288 | 1127 | ||
1289 | mutex_unlock(&local->sta_mtx); | 1128 | mutex_unlock(&local->sta_mtx); |
@@ -1522,3 +1361,60 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) | |||
1522 | _ieee80211_enable_rssi_reports(sdata, 0, 0); | 1361 | _ieee80211_enable_rssi_reports(sdata, 0, 0); |
1523 | } | 1362 | } |
1524 | EXPORT_SYMBOL(ieee80211_disable_rssi_reports); | 1363 | EXPORT_SYMBOL(ieee80211_disable_rssi_reports); |
1364 | |||
1365 | int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) | ||
1366 | { | ||
1367 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1368 | struct ieee80211_local *local = sdata->local; | ||
1369 | struct ieee80211_supported_band *sband; | ||
1370 | int rate; | ||
1371 | u8 i, rates, *pos; | ||
1372 | |||
1373 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1374 | rates = sband->n_bitrates; | ||
1375 | if (rates > 8) | ||
1376 | rates = 8; | ||
1377 | |||
1378 | if (skb_tailroom(skb) < rates + 2) | ||
1379 | return -ENOMEM; | ||
1380 | |||
1381 | pos = skb_put(skb, rates + 2); | ||
1382 | *pos++ = WLAN_EID_SUPP_RATES; | ||
1383 | *pos++ = rates; | ||
1384 | for (i = 0; i < rates; i++) { | ||
1385 | rate = sband->bitrates[i].bitrate; | ||
1386 | *pos++ = (u8) (rate / 5); | ||
1387 | } | ||
1388 | |||
1389 | return 0; | ||
1390 | } | ||
1391 | |||
1392 | int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) | ||
1393 | { | ||
1394 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1395 | struct ieee80211_local *local = sdata->local; | ||
1396 | struct ieee80211_supported_band *sband; | ||
1397 | int rate; | ||
1398 | u8 i, exrates, *pos; | ||
1399 | |||
1400 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1401 | exrates = sband->n_bitrates; | ||
1402 | if (exrates > 8) | ||
1403 | exrates -= 8; | ||
1404 | else | ||
1405 | exrates = 0; | ||
1406 | |||
1407 | if (skb_tailroom(skb) < exrates + 2) | ||
1408 | return -ENOMEM; | ||
1409 | |||
1410 | if (exrates) { | ||
1411 | pos = skb_put(skb, exrates + 2); | ||
1412 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
1413 | *pos++ = exrates; | ||
1414 | for (i = 8; i < sband->n_bitrates; i++) { | ||
1415 | rate = sband->bitrates[i].bitrate; | ||
1416 | *pos++ = (u8) (rate / 5); | ||
1417 | } | ||
1418 | } | ||
1419 | return 0; | ||
1420 | } | ||
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 7a49532f14cb..fd52e695c071 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -72,7 +72,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
72 | case NL80211_IFTYPE_AP_VLAN: | 72 | case NL80211_IFTYPE_AP_VLAN: |
73 | sta = rcu_dereference(sdata->u.vlan.sta); | 73 | sta = rcu_dereference(sdata->u.vlan.sta); |
74 | if (sta) { | 74 | if (sta) { |
75 | qos = get_sta_flags(sta) & WLAN_STA_WME; | 75 | qos = test_sta_flag(sta, WLAN_STA_WME); |
76 | break; | 76 | break; |
77 | } | 77 | } |
78 | case NL80211_IFTYPE_AP: | 78 | case NL80211_IFTYPE_AP: |
@@ -83,11 +83,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
83 | break; | 83 | break; |
84 | #ifdef CONFIG_MAC80211_MESH | 84 | #ifdef CONFIG_MAC80211_MESH |
85 | case NL80211_IFTYPE_MESH_POINT: | 85 | case NL80211_IFTYPE_MESH_POINT: |
86 | /* | 86 | ra = skb->data; |
87 | * XXX: This is clearly broken ... but already was before, | ||
88 | * because ieee80211_fill_mesh_addresses() would clear A1 | ||
89 | * except for multicast addresses. | ||
90 | */ | ||
91 | break; | 87 | break; |
92 | #endif | 88 | #endif |
93 | case NL80211_IFTYPE_STATION: | 89 | case NL80211_IFTYPE_STATION: |
@@ -103,7 +99,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
103 | if (!sta && ra && !is_multicast_ether_addr(ra)) { | 99 | if (!sta && ra && !is_multicast_ether_addr(ra)) { |
104 | sta = sta_info_get(sdata, ra); | 100 | sta = sta_info_get(sdata, ra); |
105 | if (sta) | 101 | if (sta) |
106 | qos = get_sta_flags(sta) & WLAN_STA_WME; | 102 | qos = test_sta_flag(sta, WLAN_STA_WME); |
107 | } | 103 | } |
108 | rcu_read_unlock(); | 104 | rcu_read_unlock(); |
109 | 105 | ||
@@ -139,7 +135,8 @@ u16 ieee80211_downgrade_queue(struct ieee80211_local *local, | |||
139 | return ieee802_1d_to_ac[skb->priority]; | 135 | return ieee802_1d_to_ac[skb->priority]; |
140 | } | 136 | } |
141 | 137 | ||
142 | void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb) | 138 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, |
139 | struct sk_buff *skb) | ||
143 | { | 140 | { |
144 | struct ieee80211_hdr *hdr = (void *)skb->data; | 141 | struct ieee80211_hdr *hdr = (void *)skb->data; |
145 | 142 | ||
@@ -150,10 +147,11 @@ void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb) | |||
150 | 147 | ||
151 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | 148 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
152 | 149 | ||
153 | if (unlikely(local->wifi_wme_noack_test)) | 150 | if (unlikely(sdata->local->wifi_wme_noack_test)) |
154 | ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; | 151 | ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; |
155 | /* qos header is 2 bytes, second reserved */ | 152 | /* qos header is 2 bytes */ |
156 | *p++ = ack_policy | tid; | 153 | *p++ = ack_policy | tid; |
157 | *p = 0; | 154 | *p = ieee80211_vif_is_mesh(&sdata->vif) ? |
155 | (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; | ||
158 | } | 156 | } |
159 | } | 157 | } |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index faead6d02026..34e166fbf4d4 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -17,7 +17,8 @@ extern const int ieee802_1d_to_ac[8]; | |||
17 | 17 | ||
18 | u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | 18 | u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, |
19 | struct sk_buff *skb); | 19 | struct sk_buff *skb); |
20 | void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb); | 20 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, |
21 | struct sk_buff *skb); | ||
21 | u16 ieee80211_downgrade_queue(struct ieee80211_local *local, | 22 | u16 ieee80211_downgrade_queue(struct ieee80211_local *local, |
22 | struct sk_buff *skb); | 23 | struct sk_buff *skb); |
23 | 24 | ||
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 380b9a7462b6..94472eb34d76 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -229,11 +229,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
229 | wk->ie_len + /* extra IEs */ | 229 | wk->ie_len + /* extra IEs */ |
230 | 9, /* WMM */ | 230 | 9, /* WMM */ |
231 | GFP_KERNEL); | 231 | GFP_KERNEL); |
232 | if (!skb) { | 232 | if (!skb) |
233 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | ||
234 | "frame\n", sdata->name); | ||
235 | return; | 233 | return; |
236 | } | 234 | |
237 | skb_reserve(skb, local->hw.extra_tx_headroom); | 235 | skb_reserve(skb, local->hw.extra_tx_headroom); |
238 | 236 | ||
239 | capab = WLAN_CAPABILITY_ESS; | 237 | capab = WLAN_CAPABILITY_ESS; |
@@ -460,7 +458,7 @@ ieee80211_direct_probe(struct ieee80211_work *wk) | |||
460 | */ | 458 | */ |
461 | ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, | 459 | ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, |
462 | wk->probe_auth.ssid_len, NULL, 0, | 460 | wk->probe_auth.ssid_len, NULL, 0, |
463 | (u32) -1, true); | 461 | (u32) -1, true, false); |
464 | 462 | ||
465 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 463 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
466 | run_again(local, wk->timeout); | 464 | run_again(local, wk->timeout); |
@@ -579,7 +577,7 @@ ieee80211_offchannel_tx(struct ieee80211_work *wk) | |||
579 | /* | 577 | /* |
580 | * After this, offchan_tx.frame remains but now is no | 578 | * After this, offchan_tx.frame remains but now is no |
581 | * longer a valid pointer -- we still need it as the | 579 | * longer a valid pointer -- we still need it as the |
582 | * cookie for canceling this work. | 580 | * cookie for canceling this work/status matching. |
583 | */ | 581 | */ |
584 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); | 582 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); |
585 | 583 | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 7bc8702808fa..f614ce7bb6e3 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -53,7 +53,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
53 | } | 53 | } |
54 | 54 | ||
55 | if (info->control.hw_key && | 55 | if (info->control.hw_key && |
56 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && | 56 | (info->flags & IEEE80211_TX_CTL_DONTFRAG || |
57 | tx->local->ops->set_frag_threshold) && | ||
57 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { | 58 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
58 | /* hwaccel - with no need for SW-generated MMIC */ | 59 | /* hwaccel - with no need for SW-generated MMIC */ |
59 | return TX_CONTINUE; | 60 | return TX_CONTINUE; |