diff options
Diffstat (limited to 'net/mac80211')
42 files changed, 4446 insertions, 2476 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index a10d508b07e1..a952b7f8c648 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -96,18 +96,6 @@ menuconfig MAC80211_DEBUG_MENU | |||
96 | ---help--- | 96 | ---help--- |
97 | This option collects various mac80211 debug settings. | 97 | This option collects various mac80211 debug settings. |
98 | 98 | ||
99 | config MAC80211_DEBUG_PACKET_ALIGNMENT | ||
100 | bool "Enable packet alignment debugging" | ||
101 | depends on MAC80211_DEBUG_MENU | ||
102 | ---help--- | ||
103 | This option is recommended for driver authors and strongly | ||
104 | discouraged for everybody else, it will trigger a warning | ||
105 | when a driver hands mac80211 a buffer that is aligned in | ||
106 | a way that will cause problems with the IP stack on some | ||
107 | architectures. | ||
108 | |||
109 | Say N unless you're writing a mac80211 based driver. | ||
110 | |||
111 | config MAC80211_NOINLINE | 99 | config MAC80211_NOINLINE |
112 | bool "Do not inline TX/RX handlers" | 100 | bool "Do not inline TX/RX handlers" |
113 | depends on MAC80211_DEBUG_MENU | 101 | depends on MAC80211_DEBUG_MENU |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 298cfcc1bf8d..04420291e7ad 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -6,10 +6,10 @@ mac80211-y := \ | |||
6 | sta_info.o \ | 6 | sta_info.o \ |
7 | wep.o \ | 7 | wep.o \ |
8 | wpa.o \ | 8 | wpa.o \ |
9 | scan.o \ | 9 | scan.o offchannel.o \ |
10 | ht.o agg-tx.o agg-rx.o \ | 10 | ht.o agg-tx.o agg-rx.o \ |
11 | ibss.o \ | 11 | ibss.o \ |
12 | mlme.o \ | 12 | mlme.o work.o \ |
13 | iface.o \ | 13 | iface.o \ |
14 | rate.o \ | 14 | rate.o \ |
15 | michael.o \ | 15 | michael.o \ |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 51c7dc3c4c3b..a978e666ed6f 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -41,8 +41,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
41 | sta->sta.addr, tid); | 41 | sta->sta.addr, tid); |
42 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 42 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
43 | 43 | ||
44 | if (drv_ampdu_action(local, &sta->sdata->vif, | 44 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, |
45 | IEEE80211_AMPDU_RX_STOP, | ||
46 | &sta->sta, tid, NULL)) | 45 | &sta->sta, tid, NULL)) |
47 | printk(KERN_DEBUG "HW problem - can not stop rx " | 46 | printk(KERN_DEBUG "HW problem - can not stop rx " |
48 | "aggregation for tid %d\n", tid); | 47 | "aggregation for tid %d\n", tid); |
@@ -83,12 +82,11 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
83 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | 82 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, |
84 | u16 initiator, u16 reason) | 83 | u16 initiator, u16 reason) |
85 | { | 84 | { |
86 | struct ieee80211_local *local = sdata->local; | ||
87 | struct sta_info *sta; | 85 | struct sta_info *sta; |
88 | 86 | ||
89 | rcu_read_lock(); | 87 | rcu_read_lock(); |
90 | 88 | ||
91 | sta = sta_info_get(local, ra); | 89 | sta = sta_info_get(sdata, ra); |
92 | if (!sta) { | 90 | if (!sta) { |
93 | rcu_read_unlock(); | 91 | rcu_read_unlock(); |
94 | return; | 92 | return; |
@@ -136,7 +134,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
136 | 134 | ||
137 | if (!skb) { | 135 | if (!skb) { |
138 | printk(KERN_DEBUG "%s: failed to allocate buffer " | 136 | printk(KERN_DEBUG "%s: failed to allocate buffer " |
139 | "for addba resp frame\n", sdata->dev->name); | 137 | "for addba resp frame\n", sdata->name); |
140 | return; | 138 | return; |
141 | } | 139 | } |
142 | 140 | ||
@@ -144,10 +142,10 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
144 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 142 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
145 | memset(mgmt, 0, 24); | 143 | memset(mgmt, 0, 24); |
146 | memcpy(mgmt->da, da, ETH_ALEN); | 144 | memcpy(mgmt->da, da, ETH_ALEN); |
147 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 145 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
148 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 146 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
149 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 147 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
150 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 148 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
151 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 149 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
152 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 150 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
153 | 151 | ||
@@ -281,8 +279,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
281 | goto end; | 279 | goto end; |
282 | } | 280 | } |
283 | 281 | ||
284 | ret = drv_ampdu_action(local, &sta->sdata->vif, | 282 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
285 | IEEE80211_AMPDU_RX_START, | ||
286 | &sta->sta, tid, &start_seq_num); | 283 | &sta->sta, tid, &start_seq_num); |
287 | #ifdef CONFIG_MAC80211_HT_DEBUG | 284 | #ifdef CONFIG_MAC80211_HT_DEBUG |
288 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | 285 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 5e3a7eccef5a..5538e1b4a697 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -58,17 +58,17 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
58 | 58 | ||
59 | if (!skb) { | 59 | if (!skb) { |
60 | printk(KERN_ERR "%s: failed to allocate buffer " | 60 | printk(KERN_ERR "%s: failed to allocate buffer " |
61 | "for addba request frame\n", sdata->dev->name); | 61 | "for addba request frame\n", sdata->name); |
62 | return; | 62 | return; |
63 | } | 63 | } |
64 | skb_reserve(skb, local->hw.extra_tx_headroom); | 64 | skb_reserve(skb, local->hw.extra_tx_headroom); |
65 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 65 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
66 | memset(mgmt, 0, 24); | 66 | memset(mgmt, 0, 24); |
67 | memcpy(mgmt->da, da, ETH_ALEN); | 67 | memcpy(mgmt->da, da, ETH_ALEN); |
68 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 68 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
69 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 69 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
70 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 70 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
71 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 71 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
72 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 72 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
73 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 73 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
74 | 74 | ||
@@ -104,7 +104,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
104 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | 104 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); |
105 | if (!skb) { | 105 | if (!skb) { |
106 | printk(KERN_ERR "%s: failed to allocate buffer for " | 106 | printk(KERN_ERR "%s: failed to allocate buffer for " |
107 | "bar frame\n", sdata->dev->name); | 107 | "bar frame\n", sdata->name); |
108 | return; | 108 | return; |
109 | } | 109 | } |
110 | skb_reserve(skb, local->hw.extra_tx_headroom); | 110 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -113,7 +113,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
113 | bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | | 113 | bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | |
114 | IEEE80211_STYPE_BACK_REQ); | 114 | IEEE80211_STYPE_BACK_REQ); |
115 | memcpy(bar->ra, ra, ETH_ALEN); | 115 | memcpy(bar->ra, ra, ETH_ALEN); |
116 | memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); | 116 | memcpy(bar->ta, sdata->vif.addr, ETH_ALEN); |
117 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | 117 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; |
118 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | 118 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; |
119 | bar_control |= (u16)(tid << 12); | 119 | bar_control |= (u16)(tid << 12); |
@@ -144,7 +144,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
144 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | 144 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | |
145 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 145 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
146 | 146 | ||
147 | ret = drv_ampdu_action(local, &sta->sdata->vif, | 147 | ret = drv_ampdu_action(local, sta->sdata, |
148 | IEEE80211_AMPDU_TX_STOP, | 148 | IEEE80211_AMPDU_TX_STOP, |
149 | &sta->sta, tid, NULL); | 149 | &sta->sta, tid, NULL); |
150 | 150 | ||
@@ -179,7 +179,8 @@ static void sta_addba_resp_timer_expired(unsigned long data) | |||
179 | 179 | ||
180 | /* check if the TID waits for addBA response */ | 180 | /* check if the TID waits for addBA response */ |
181 | spin_lock_bh(&sta->lock); | 181 | spin_lock_bh(&sta->lock); |
182 | if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK)) != | 182 | if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK | |
183 | HT_AGG_STATE_REQ_STOP_BA_MSK)) != | ||
183 | HT_ADDBA_REQUESTED_MSK) { | 184 | HT_ADDBA_REQUESTED_MSK) { |
184 | spin_unlock_bh(&sta->lock); | 185 | spin_unlock_bh(&sta->lock); |
185 | *state = HT_AGG_STATE_IDLE; | 186 | *state = HT_AGG_STATE_IDLE; |
@@ -236,6 +237,14 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
236 | sdata->vif.type != NL80211_IFTYPE_AP) | 237 | sdata->vif.type != NL80211_IFTYPE_AP) |
237 | return -EINVAL; | 238 | return -EINVAL; |
238 | 239 | ||
240 | if (test_sta_flags(sta, WLAN_STA_DISASSOC)) { | ||
241 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
242 | printk(KERN_DEBUG "Disassociation is in progress. " | ||
243 | "Denying BA session request\n"); | ||
244 | #endif | ||
245 | return -EINVAL; | ||
246 | } | ||
247 | |||
239 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { | 248 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { |
240 | #ifdef CONFIG_MAC80211_HT_DEBUG | 249 | #ifdef CONFIG_MAC80211_HT_DEBUG |
241 | printk(KERN_DEBUG "Suspend in progress. " | 250 | printk(KERN_DEBUG "Suspend in progress. " |
@@ -301,10 +310,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
301 | * call back right away, it must see that the flow has begun */ | 310 | * call back right away, it must see that the flow has begun */ |
302 | *state |= HT_ADDBA_REQUESTED_MSK; | 311 | *state |= HT_ADDBA_REQUESTED_MSK; |
303 | 312 | ||
304 | start_seq_num = sta->tid_seq[tid]; | 313 | start_seq_num = sta->tid_seq[tid] >> 4; |
305 | 314 | ||
306 | ret = drv_ampdu_action(local, &sdata->vif, | 315 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, |
307 | IEEE80211_AMPDU_TX_START, | ||
308 | pubsta, tid, &start_seq_num); | 316 | pubsta, tid, &start_seq_num); |
309 | 317 | ||
310 | if (ret) { | 318 | if (ret) { |
@@ -420,7 +428,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
420 | ieee80211_agg_splice_finish(local, sta, tid); | 428 | ieee80211_agg_splice_finish(local, sta, tid); |
421 | spin_unlock(&local->ampdu_lock); | 429 | spin_unlock(&local->ampdu_lock); |
422 | 430 | ||
423 | drv_ampdu_action(local, &sta->sdata->vif, | 431 | drv_ampdu_action(local, sta->sdata, |
424 | IEEE80211_AMPDU_TX_OPERATIONAL, | 432 | IEEE80211_AMPDU_TX_OPERATIONAL, |
425 | &sta->sta, tid, NULL); | 433 | &sta->sta, tid, NULL); |
426 | } | 434 | } |
@@ -441,7 +449,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
441 | } | 449 | } |
442 | 450 | ||
443 | rcu_read_lock(); | 451 | rcu_read_lock(); |
444 | sta = sta_info_get(local, ra); | 452 | sta = sta_info_get(sdata, ra); |
445 | if (!sta) { | 453 | if (!sta) { |
446 | rcu_read_unlock(); | 454 | rcu_read_unlock(); |
447 | #ifdef CONFIG_MAC80211_HT_DEBUG | 455 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -489,7 +497,7 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
489 | #ifdef CONFIG_MAC80211_HT_DEBUG | 497 | #ifdef CONFIG_MAC80211_HT_DEBUG |
490 | if (net_ratelimit()) | 498 | if (net_ratelimit()) |
491 | printk(KERN_WARNING "%s: Not enough memory, " | 499 | printk(KERN_WARNING "%s: Not enough memory, " |
492 | "dropping start BA session", skb->dev->name); | 500 | "dropping start BA session", sdata->name); |
493 | #endif | 501 | #endif |
494 | return; | 502 | return; |
495 | } | 503 | } |
@@ -564,7 +572,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
564 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 572 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
565 | 573 | ||
566 | rcu_read_lock(); | 574 | rcu_read_lock(); |
567 | sta = sta_info_get(local, ra); | 575 | sta = sta_info_get(sdata, ra); |
568 | if (!sta) { | 576 | if (!sta) { |
569 | #ifdef CONFIG_MAC80211_HT_DEBUG | 577 | #ifdef CONFIG_MAC80211_HT_DEBUG |
570 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | 578 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); |
@@ -621,7 +629,7 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
621 | #ifdef CONFIG_MAC80211_HT_DEBUG | 629 | #ifdef CONFIG_MAC80211_HT_DEBUG |
622 | if (net_ratelimit()) | 630 | if (net_ratelimit()) |
623 | printk(KERN_WARNING "%s: Not enough memory, " | 631 | printk(KERN_WARNING "%s: Not enough memory, " |
624 | "dropping stop BA session", skb->dev->name); | 632 | "dropping stop BA session", sdata->name); |
625 | #endif | 633 | #endif |
626 | return; | 634 | return; |
627 | } | 635 | } |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9ae1a4760b58..b7116ef84a3b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * mac80211 configuration hooks for cfg80211 | 2 | * mac80211 configuration hooks for cfg80211 |
3 | * | 3 | * |
4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
5 | * | 5 | * |
6 | * This file is GPLv2 as found in COPYING. | 6 | * This file is GPLv2 as found in COPYING. |
7 | */ | 7 | */ |
@@ -78,17 +78,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
78 | enum nl80211_iftype type, u32 *flags, | 78 | enum nl80211_iftype type, u32 *flags, |
79 | struct vif_params *params) | 79 | struct vif_params *params) |
80 | { | 80 | { |
81 | struct ieee80211_sub_if_data *sdata; | 81 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
82 | int ret; | 82 | int ret; |
83 | 83 | ||
84 | if (netif_running(dev)) | 84 | if (ieee80211_sdata_running(sdata)) |
85 | return -EBUSY; | 85 | return -EBUSY; |
86 | 86 | ||
87 | if (!nl80211_params_check(type, params)) | 87 | if (!nl80211_params_check(type, params)) |
88 | return -EINVAL; | 88 | return -EINVAL; |
89 | 89 | ||
90 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
91 | |||
92 | ret = ieee80211_if_change_type(sdata, type); | 90 | ret = ieee80211_if_change_type(sdata, type); |
93 | if (ret) | 91 | if (ret) |
94 | return ret; | 92 | return ret; |
@@ -150,7 +148,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
150 | rcu_read_lock(); | 148 | rcu_read_lock(); |
151 | 149 | ||
152 | if (mac_addr) { | 150 | if (mac_addr) { |
153 | sta = sta_info_get(sdata->local, mac_addr); | 151 | sta = sta_info_get_bss(sdata, mac_addr); |
154 | if (!sta) { | 152 | if (!sta) { |
155 | ieee80211_key_free(key); | 153 | ieee80211_key_free(key); |
156 | err = -ENOENT; | 154 | err = -ENOENT; |
@@ -181,7 +179,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
181 | if (mac_addr) { | 179 | if (mac_addr) { |
182 | ret = -ENOENT; | 180 | ret = -ENOENT; |
183 | 181 | ||
184 | sta = sta_info_get(sdata->local, mac_addr); | 182 | sta = sta_info_get_bss(sdata, mac_addr); |
185 | if (!sta) | 183 | if (!sta) |
186 | goto out_unlock; | 184 | goto out_unlock; |
187 | 185 | ||
@@ -228,7 +226,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
228 | rcu_read_lock(); | 226 | rcu_read_lock(); |
229 | 227 | ||
230 | if (mac_addr) { | 228 | if (mac_addr) { |
231 | sta = sta_info_get(sdata->local, mac_addr); | 229 | sta = sta_info_get_bss(sdata, mac_addr); |
232 | if (!sta) | 230 | if (!sta) |
233 | goto out; | 231 | goto out; |
234 | 232 | ||
@@ -415,15 +413,13 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
415 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 413 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
416 | u8 *mac, struct station_info *sinfo) | 414 | u8 *mac, struct station_info *sinfo) |
417 | { | 415 | { |
418 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 416 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
419 | struct sta_info *sta; | 417 | struct sta_info *sta; |
420 | int ret = -ENOENT; | 418 | int ret = -ENOENT; |
421 | 419 | ||
422 | rcu_read_lock(); | 420 | rcu_read_lock(); |
423 | 421 | ||
424 | /* XXX: verify sta->dev == dev */ | 422 | sta = sta_info_get_bss(sdata, mac); |
425 | |||
426 | sta = sta_info_get(local, mac); | ||
427 | if (sta) { | 423 | if (sta) { |
428 | ret = 0; | 424 | ret = 0; |
429 | sta_set_sinfo(sta, sinfo); | 425 | sta_set_sinfo(sta, sinfo); |
@@ -519,6 +515,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
519 | if (old) | 515 | if (old) |
520 | memcpy(new->tail, old->tail, new_tail_len); | 516 | memcpy(new->tail, old->tail, new_tail_len); |
521 | 517 | ||
518 | sdata->vif.bss_conf.dtim_period = new->dtim_period; | ||
519 | |||
522 | rcu_assign_pointer(sdata->u.ap.beacon, new); | 520 | rcu_assign_pointer(sdata->u.ap.beacon, new); |
523 | 521 | ||
524 | synchronize_rcu(); | 522 | synchronize_rcu(); |
@@ -732,7 +730,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
732 | } else | 730 | } else |
733 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 731 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
734 | 732 | ||
735 | if (compare_ether_addr(mac, dev->dev_addr) == 0) | 733 | if (compare_ether_addr(mac, sdata->vif.addr) == 0) |
736 | return -EINVAL; | 734 | return -EINVAL; |
737 | 735 | ||
738 | if (is_multicast_ether_addr(mac)) | 736 | if (is_multicast_ether_addr(mac)) |
@@ -751,9 +749,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
751 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 749 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
752 | sdata->vif.type == NL80211_IFTYPE_AP; | 750 | sdata->vif.type == NL80211_IFTYPE_AP; |
753 | 751 | ||
754 | rcu_read_lock(); | 752 | err = sta_info_insert_rcu(sta); |
755 | |||
756 | err = sta_info_insert(sta); | ||
757 | if (err) { | 753 | if (err) { |
758 | rcu_read_unlock(); | 754 | rcu_read_unlock(); |
759 | return err; | 755 | return err; |
@@ -772,27 +768,13 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
772 | { | 768 | { |
773 | struct ieee80211_local *local = wiphy_priv(wiphy); | 769 | struct ieee80211_local *local = wiphy_priv(wiphy); |
774 | struct ieee80211_sub_if_data *sdata; | 770 | struct ieee80211_sub_if_data *sdata; |
775 | struct sta_info *sta; | ||
776 | 771 | ||
777 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 772 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
778 | 773 | ||
779 | if (mac) { | 774 | if (mac) |
780 | rcu_read_lock(); | 775 | return sta_info_destroy_addr_bss(sdata, mac); |
781 | |||
782 | /* XXX: get sta belonging to dev */ | ||
783 | sta = sta_info_get(local, mac); | ||
784 | if (!sta) { | ||
785 | rcu_read_unlock(); | ||
786 | return -ENOENT; | ||
787 | } | ||
788 | |||
789 | sta_info_unlink(&sta); | ||
790 | rcu_read_unlock(); | ||
791 | |||
792 | sta_info_destroy(sta); | ||
793 | } else | ||
794 | sta_info_flush(local, sdata); | ||
795 | 776 | ||
777 | sta_info_flush(local, sdata); | ||
796 | return 0; | 778 | return 0; |
797 | } | 779 | } |
798 | 780 | ||
@@ -801,14 +783,14 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
801 | u8 *mac, | 783 | u8 *mac, |
802 | struct station_parameters *params) | 784 | struct station_parameters *params) |
803 | { | 785 | { |
786 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
804 | struct ieee80211_local *local = wiphy_priv(wiphy); | 787 | struct ieee80211_local *local = wiphy_priv(wiphy); |
805 | struct sta_info *sta; | 788 | struct sta_info *sta; |
806 | struct ieee80211_sub_if_data *vlansdata; | 789 | struct ieee80211_sub_if_data *vlansdata; |
807 | 790 | ||
808 | rcu_read_lock(); | 791 | rcu_read_lock(); |
809 | 792 | ||
810 | /* XXX: get sta belonging to dev */ | 793 | sta = sta_info_get_bss(sdata, mac); |
811 | sta = sta_info_get(local, mac); | ||
812 | if (!sta) { | 794 | if (!sta) { |
813 | rcu_read_unlock(); | 795 | rcu_read_unlock(); |
814 | return -ENOENT; | 796 | return -ENOENT; |
@@ -847,7 +829,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
847 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | 829 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, |
848 | u8 *dst, u8 *next_hop) | 830 | u8 *dst, u8 *next_hop) |
849 | { | 831 | { |
850 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
851 | struct ieee80211_sub_if_data *sdata; | 832 | struct ieee80211_sub_if_data *sdata; |
852 | struct mesh_path *mpath; | 833 | struct mesh_path *mpath; |
853 | struct sta_info *sta; | 834 | struct sta_info *sta; |
@@ -856,7 +837,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
856 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 837 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
857 | 838 | ||
858 | rcu_read_lock(); | 839 | rcu_read_lock(); |
859 | sta = sta_info_get(local, next_hop); | 840 | sta = sta_info_get(sdata, next_hop); |
860 | if (!sta) { | 841 | if (!sta) { |
861 | rcu_read_unlock(); | 842 | rcu_read_unlock(); |
862 | return -ENOENT; | 843 | return -ENOENT; |
@@ -895,7 +876,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
895 | struct net_device *dev, | 876 | struct net_device *dev, |
896 | u8 *dst, u8 *next_hop) | 877 | u8 *dst, u8 *next_hop) |
897 | { | 878 | { |
898 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
899 | struct ieee80211_sub_if_data *sdata; | 879 | struct ieee80211_sub_if_data *sdata; |
900 | struct mesh_path *mpath; | 880 | struct mesh_path *mpath; |
901 | struct sta_info *sta; | 881 | struct sta_info *sta; |
@@ -904,7 +884,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
904 | 884 | ||
905 | rcu_read_lock(); | 885 | rcu_read_lock(); |
906 | 886 | ||
907 | sta = sta_info_get(local, next_hop); | 887 | sta = sta_info_get(sdata, next_hop); |
908 | if (!sta) { | 888 | if (!sta) { |
909 | rcu_read_unlock(); | 889 | rcu_read_unlock(); |
910 | return -ENOENT; | 890 | return -ENOENT; |
@@ -1092,6 +1072,13 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1092 | params->use_short_preamble; | 1072 | params->use_short_preamble; |
1093 | changed |= BSS_CHANGED_ERP_PREAMBLE; | 1073 | changed |= BSS_CHANGED_ERP_PREAMBLE; |
1094 | } | 1074 | } |
1075 | |||
1076 | if (!sdata->vif.bss_conf.use_short_slot && | ||
1077 | sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) { | ||
1078 | sdata->vif.bss_conf.use_short_slot = true; | ||
1079 | changed |= BSS_CHANGED_ERP_SLOT; | ||
1080 | } | ||
1081 | |||
1095 | if (params->use_short_slot_time >= 0) { | 1082 | if (params->use_short_slot_time >= 0) { |
1096 | sdata->vif.bss_conf.use_short_slot = | 1083 | sdata->vif.bss_conf.use_short_slot = |
1097 | params->use_short_slot_time; | 1084 | params->use_short_slot_time; |
@@ -1135,6 +1122,13 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1135 | p.cw_max = params->cwmax; | 1122 | p.cw_max = params->cwmax; |
1136 | p.cw_min = params->cwmin; | 1123 | p.cw_min = params->cwmin; |
1137 | p.txop = params->txop; | 1124 | p.txop = params->txop; |
1125 | |||
1126 | /* | ||
1127 | * Setting tx queue params disables u-apsd because it's only | ||
1128 | * called in master mode. | ||
1129 | */ | ||
1130 | p.uapsd = false; | ||
1131 | |||
1138 | if (drv_conf_tx(local, params->queue, &p)) { | 1132 | if (drv_conf_tx(local, params->queue, &p)) { |
1139 | printk(KERN_DEBUG "%s: failed to set TX queue " | 1133 | printk(KERN_DEBUG "%s: failed to set TX queue " |
1140 | "parameters for queue %d\n", | 1134 | "parameters for queue %d\n", |
@@ -1237,6 +1231,13 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1237 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1231 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1238 | int err; | 1232 | int err; |
1239 | 1233 | ||
1234 | if (changed & WIPHY_PARAM_COVERAGE_CLASS) { | ||
1235 | err = drv_set_coverage_class(local, wiphy->coverage_class); | ||
1236 | |||
1237 | if (err) | ||
1238 | return err; | ||
1239 | } | ||
1240 | |||
1240 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | 1241 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { |
1241 | err = drv_set_rts_threshold(local, wiphy->rts_threshold); | 1242 | err = drv_set_rts_threshold(local, wiphy->rts_threshold); |
1242 | 1243 | ||
@@ -1324,6 +1325,50 @@ static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) | |||
1324 | } | 1325 | } |
1325 | #endif | 1326 | #endif |
1326 | 1327 | ||
1328 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | ||
1329 | enum ieee80211_smps_mode smps_mode) | ||
1330 | { | ||
1331 | const u8 *ap; | ||
1332 | enum ieee80211_smps_mode old_req; | ||
1333 | int err; | ||
1334 | |||
1335 | old_req = sdata->u.mgd.req_smps; | ||
1336 | sdata->u.mgd.req_smps = smps_mode; | ||
1337 | |||
1338 | if (old_req == smps_mode && | ||
1339 | smps_mode != IEEE80211_SMPS_AUTOMATIC) | ||
1340 | return 0; | ||
1341 | |||
1342 | /* | ||
1343 | * If not associated, or current association is not an HT | ||
1344 | * association, there's no need to send an action frame. | ||
1345 | */ | ||
1346 | if (!sdata->u.mgd.associated || | ||
1347 | sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) { | ||
1348 | mutex_lock(&sdata->local->iflist_mtx); | ||
1349 | ieee80211_recalc_smps(sdata->local, sdata); | ||
1350 | mutex_unlock(&sdata->local->iflist_mtx); | ||
1351 | return 0; | ||
1352 | } | ||
1353 | |||
1354 | ap = sdata->u.mgd.associated->bssid; | ||
1355 | |||
1356 | if (smps_mode == IEEE80211_SMPS_AUTOMATIC) { | ||
1357 | if (sdata->u.mgd.powersave) | ||
1358 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
1359 | else | ||
1360 | smps_mode = IEEE80211_SMPS_OFF; | ||
1361 | } | ||
1362 | |||
1363 | /* send SM PS frame to AP */ | ||
1364 | err = ieee80211_send_smps_action(sdata, smps_mode, | ||
1365 | ap, ap); | ||
1366 | if (err) | ||
1367 | sdata->u.mgd.req_smps = old_req; | ||
1368 | |||
1369 | return err; | ||
1370 | } | ||
1371 | |||
1327 | static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | 1372 | static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, |
1328 | bool enabled, int timeout) | 1373 | bool enabled, int timeout) |
1329 | { | 1374 | { |
@@ -1344,6 +1389,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
1344 | sdata->u.mgd.powersave = enabled; | 1389 | sdata->u.mgd.powersave = enabled; |
1345 | conf->dynamic_ps_timeout = timeout; | 1390 | conf->dynamic_ps_timeout = timeout; |
1346 | 1391 | ||
1392 | /* no change, but if automatic follow powersave */ | ||
1393 | mutex_lock(&sdata->u.mgd.mtx); | ||
1394 | __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); | ||
1395 | mutex_unlock(&sdata->u.mgd.mtx); | ||
1396 | |||
1347 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | 1397 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) |
1348 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 1398 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
1349 | 1399 | ||
@@ -1359,39 +1409,52 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1359 | { | 1409 | { |
1360 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1410 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1361 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1411 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1362 | int i, err = -EINVAL; | 1412 | int i; |
1363 | u32 target_rate; | 1413 | |
1364 | struct ieee80211_supported_band *sband; | 1414 | /* |
1415 | * This _could_ be supported by providing a hook for | ||
1416 | * drivers for this function, but at this point it | ||
1417 | * doesn't seem worth bothering. | ||
1418 | */ | ||
1419 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | ||
1420 | return -EOPNOTSUPP; | ||
1365 | 1421 | ||
1366 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1367 | 1422 | ||
1368 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates | 1423 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) |
1369 | * target_rate = X, rate->fixed = 1 means only rate X | 1424 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
1370 | * target_rate = X, rate->fixed = 0 means all rates <= X */ | ||
1371 | sdata->max_ratectrl_rateidx = -1; | ||
1372 | sdata->force_unicast_rateidx = -1; | ||
1373 | 1425 | ||
1374 | if (mask->fixed) | 1426 | return 0; |
1375 | target_rate = mask->fixed / 100; | 1427 | } |
1376 | else if (mask->maxrate) | ||
1377 | target_rate = mask->maxrate / 100; | ||
1378 | else | ||
1379 | return 0; | ||
1380 | 1428 | ||
1381 | for (i=0; i< sband->n_bitrates; i++) { | 1429 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
1382 | struct ieee80211_rate *brate = &sband->bitrates[i]; | 1430 | struct net_device *dev, |
1383 | int this_rate = brate->bitrate; | 1431 | struct ieee80211_channel *chan, |
1432 | enum nl80211_channel_type channel_type, | ||
1433 | unsigned int duration, | ||
1434 | u64 *cookie) | ||
1435 | { | ||
1436 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1384 | 1437 | ||
1385 | if (target_rate == this_rate) { | 1438 | return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, |
1386 | sdata->max_ratectrl_rateidx = i; | 1439 | duration, cookie); |
1387 | if (mask->fixed) | 1440 | } |
1388 | sdata->force_unicast_rateidx = i; | ||
1389 | err = 0; | ||
1390 | break; | ||
1391 | } | ||
1392 | } | ||
1393 | 1441 | ||
1394 | return err; | 1442 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, |
1443 | struct net_device *dev, | ||
1444 | u64 cookie) | ||
1445 | { | ||
1446 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1447 | |||
1448 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | ||
1449 | } | ||
1450 | |||
1451 | static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | ||
1452 | struct ieee80211_channel *chan, | ||
1453 | enum nl80211_channel_type channel_type, | ||
1454 | const u8 *buf, size_t len, u64 *cookie) | ||
1455 | { | ||
1456 | return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan, | ||
1457 | channel_type, buf, len, cookie); | ||
1395 | } | 1458 | } |
1396 | 1459 | ||
1397 | struct cfg80211_ops mac80211_config_ops = { | 1460 | struct cfg80211_ops mac80211_config_ops = { |
@@ -1440,4 +1503,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1440 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) | 1503 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) |
1441 | .set_power_mgmt = ieee80211_set_power_mgmt, | 1504 | .set_power_mgmt = ieee80211_set_power_mgmt, |
1442 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 1505 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
1506 | .remain_on_channel = ieee80211_remain_on_channel, | ||
1507 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | ||
1508 | .action = ieee80211_action, | ||
1443 | }; | 1509 | }; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index e4b54093d41b..637929b65ccc 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -158,6 +158,130 @@ static const struct file_operations noack_ops = { | |||
158 | .open = mac80211_open_file_generic | 158 | .open = mac80211_open_file_generic |
159 | }; | 159 | }; |
160 | 160 | ||
161 | static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf, | ||
162 | size_t count, loff_t *ppos) | ||
163 | { | ||
164 | struct ieee80211_local *local = file->private_data; | ||
165 | int res; | ||
166 | char buf[10]; | ||
167 | |||
168 | res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_queues); | ||
169 | |||
170 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
171 | } | ||
172 | |||
173 | static ssize_t uapsd_queues_write(struct file *file, | ||
174 | const char __user *user_buf, | ||
175 | size_t count, loff_t *ppos) | ||
176 | { | ||
177 | struct ieee80211_local *local = file->private_data; | ||
178 | unsigned long val; | ||
179 | char buf[10]; | ||
180 | size_t len; | ||
181 | int ret; | ||
182 | |||
183 | len = min(count, sizeof(buf) - 1); | ||
184 | if (copy_from_user(buf, user_buf, len)) | ||
185 | return -EFAULT; | ||
186 | buf[len] = '\0'; | ||
187 | |||
188 | ret = strict_strtoul(buf, 0, &val); | ||
189 | |||
190 | if (ret) | ||
191 | return -EINVAL; | ||
192 | |||
193 | if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) | ||
194 | return -ERANGE; | ||
195 | |||
196 | local->uapsd_queues = val; | ||
197 | |||
198 | return count; | ||
199 | } | ||
200 | |||
201 | static const struct file_operations uapsd_queues_ops = { | ||
202 | .read = uapsd_queues_read, | ||
203 | .write = uapsd_queues_write, | ||
204 | .open = mac80211_open_file_generic | ||
205 | }; | ||
206 | |||
207 | static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf, | ||
208 | size_t count, loff_t *ppos) | ||
209 | { | ||
210 | struct ieee80211_local *local = file->private_data; | ||
211 | int res; | ||
212 | char buf[10]; | ||
213 | |||
214 | res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_max_sp_len); | ||
215 | |||
216 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
217 | } | ||
218 | |||
219 | static ssize_t uapsd_max_sp_len_write(struct file *file, | ||
220 | const char __user *user_buf, | ||
221 | size_t count, loff_t *ppos) | ||
222 | { | ||
223 | struct ieee80211_local *local = file->private_data; | ||
224 | unsigned long val; | ||
225 | char buf[10]; | ||
226 | size_t len; | ||
227 | int ret; | ||
228 | |||
229 | len = min(count, sizeof(buf) - 1); | ||
230 | if (copy_from_user(buf, user_buf, len)) | ||
231 | return -EFAULT; | ||
232 | buf[len] = '\0'; | ||
233 | |||
234 | ret = strict_strtoul(buf, 0, &val); | ||
235 | |||
236 | if (ret) | ||
237 | return -EINVAL; | ||
238 | |||
239 | if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) | ||
240 | return -ERANGE; | ||
241 | |||
242 | local->uapsd_max_sp_len = val; | ||
243 | |||
244 | return count; | ||
245 | } | ||
246 | |||
247 | static const struct file_operations uapsd_max_sp_len_ops = { | ||
248 | .read = uapsd_max_sp_len_read, | ||
249 | .write = uapsd_max_sp_len_write, | ||
250 | .open = mac80211_open_file_generic | ||
251 | }; | ||
252 | |||
253 | static ssize_t channel_type_read(struct file *file, char __user *user_buf, | ||
254 | size_t count, loff_t *ppos) | ||
255 | { | ||
256 | struct ieee80211_local *local = file->private_data; | ||
257 | const char *buf; | ||
258 | |||
259 | switch (local->hw.conf.channel_type) { | ||
260 | case NL80211_CHAN_NO_HT: | ||
261 | buf = "no ht\n"; | ||
262 | break; | ||
263 | case NL80211_CHAN_HT20: | ||
264 | buf = "ht20\n"; | ||
265 | break; | ||
266 | case NL80211_CHAN_HT40MINUS: | ||
267 | buf = "ht40-\n"; | ||
268 | break; | ||
269 | case NL80211_CHAN_HT40PLUS: | ||
270 | buf = "ht40+\n"; | ||
271 | break; | ||
272 | default: | ||
273 | buf = "???"; | ||
274 | break; | ||
275 | } | ||
276 | |||
277 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | ||
278 | } | ||
279 | |||
280 | static const struct file_operations channel_type_ops = { | ||
281 | .read = channel_type_read, | ||
282 | .open = mac80211_open_file_generic | ||
283 | }; | ||
284 | |||
161 | static ssize_t queues_read(struct file *file, char __user *user_buf, | 285 | static ssize_t queues_read(struct file *file, char __user *user_buf, |
162 | size_t count, loff_t *ppos) | 286 | size_t count, loff_t *ppos) |
163 | { | 287 | { |
@@ -314,6 +438,9 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
314 | DEBUGFS_ADD(queues); | 438 | DEBUGFS_ADD(queues); |
315 | DEBUGFS_ADD_MODE(reset, 0200); | 439 | DEBUGFS_ADD_MODE(reset, 0200); |
316 | DEBUGFS_ADD(noack); | 440 | DEBUGFS_ADD(noack); |
441 | DEBUGFS_ADD(uapsd_queues); | ||
442 | DEBUGFS_ADD(uapsd_max_sp_len); | ||
443 | DEBUGFS_ADD(channel_type); | ||
317 | 444 | ||
318 | statsd = debugfs_create_dir("statistics", phyd); | 445 | statsd = debugfs_create_dir("statistics", phyd); |
319 | 446 | ||
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index e0f5224630da..d12e743cb4e1 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -56,7 +56,7 @@ KEY_CONF_FILE(keyidx, D); | |||
56 | KEY_CONF_FILE(hw_key_idx, D); | 56 | KEY_CONF_FILE(hw_key_idx, D); |
57 | KEY_FILE(flags, X); | 57 | KEY_FILE(flags, X); |
58 | KEY_FILE(tx_rx_count, D); | 58 | KEY_FILE(tx_rx_count, D); |
59 | KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n"); | 59 | KEY_READ(ifindex, sdata->name, IFNAMSIZ + 2, "%s\n"); |
60 | KEY_OPS(ifindex); | 60 | KEY_OPS(ifindex); |
61 | 61 | ||
62 | static ssize_t key_algorithm_read(struct file *file, | 62 | static ssize_t key_algorithm_read(struct file *file, |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 472b2039906c..9affe2cd185f 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -41,6 +41,30 @@ static ssize_t ieee80211_if_read( | |||
41 | return ret; | 41 | return ret; |
42 | } | 42 | } |
43 | 43 | ||
44 | static ssize_t ieee80211_if_write( | ||
45 | struct ieee80211_sub_if_data *sdata, | ||
46 | const char __user *userbuf, | ||
47 | size_t count, loff_t *ppos, | ||
48 | ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) | ||
49 | { | ||
50 | u8 *buf; | ||
51 | ssize_t ret = -ENODEV; | ||
52 | |||
53 | buf = kzalloc(count, GFP_KERNEL); | ||
54 | if (!buf) | ||
55 | return -ENOMEM; | ||
56 | |||
57 | if (copy_from_user(buf, userbuf, count)) | ||
58 | return -EFAULT; | ||
59 | |||
60 | rtnl_lock(); | ||
61 | if (sdata->dev->reg_state == NETREG_REGISTERED) | ||
62 | ret = (*write)(sdata, buf, count); | ||
63 | rtnl_unlock(); | ||
64 | |||
65 | return ret; | ||
66 | } | ||
67 | |||
44 | #define IEEE80211_IF_FMT(name, field, format_string) \ | 68 | #define IEEE80211_IF_FMT(name, field, format_string) \ |
45 | static ssize_t ieee80211_if_fmt_##name( \ | 69 | static ssize_t ieee80211_if_fmt_##name( \ |
46 | const struct ieee80211_sub_if_data *sdata, char *buf, \ | 70 | const struct ieee80211_sub_if_data *sdata, char *buf, \ |
@@ -71,7 +95,7 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
71 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ | 95 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ |
72 | } | 96 | } |
73 | 97 | ||
74 | #define __IEEE80211_IF_FILE(name) \ | 98 | #define __IEEE80211_IF_FILE(name, _write) \ |
75 | static ssize_t ieee80211_if_read_##name(struct file *file, \ | 99 | static ssize_t ieee80211_if_read_##name(struct file *file, \ |
76 | char __user *userbuf, \ | 100 | char __user *userbuf, \ |
77 | size_t count, loff_t *ppos) \ | 101 | size_t count, loff_t *ppos) \ |
@@ -82,22 +106,99 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ | |||
82 | } \ | 106 | } \ |
83 | static const struct file_operations name##_ops = { \ | 107 | static const struct file_operations name##_ops = { \ |
84 | .read = ieee80211_if_read_##name, \ | 108 | .read = ieee80211_if_read_##name, \ |
109 | .write = (_write), \ | ||
85 | .open = mac80211_open_file_generic, \ | 110 | .open = mac80211_open_file_generic, \ |
86 | } | 111 | } |
87 | 112 | ||
113 | #define __IEEE80211_IF_FILE_W(name) \ | ||
114 | static ssize_t ieee80211_if_write_##name(struct file *file, \ | ||
115 | const char __user *userbuf, \ | ||
116 | size_t count, loff_t *ppos) \ | ||
117 | { \ | ||
118 | return ieee80211_if_write(file->private_data, userbuf, count, \ | ||
119 | ppos, ieee80211_if_parse_##name); \ | ||
120 | } \ | ||
121 | __IEEE80211_IF_FILE(name, ieee80211_if_write_##name) | ||
122 | |||
123 | |||
88 | #define IEEE80211_IF_FILE(name, field, format) \ | 124 | #define IEEE80211_IF_FILE(name, field, format) \ |
89 | IEEE80211_IF_FMT_##format(name, field) \ | 125 | IEEE80211_IF_FMT_##format(name, field) \ |
90 | __IEEE80211_IF_FILE(name) | 126 | __IEEE80211_IF_FILE(name, NULL) |
91 | 127 | ||
92 | /* common attributes */ | 128 | /* common attributes */ |
93 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 129 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
94 | IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); | 130 | IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], |
95 | IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); | 131 | HEX); |
132 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | ||
133 | HEX); | ||
96 | 134 | ||
97 | /* STA attributes */ | 135 | /* STA attributes */ |
98 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 136 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
99 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 137 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
100 | IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); | 138 | |
139 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | ||
140 | enum ieee80211_smps_mode smps_mode) | ||
141 | { | ||
142 | struct ieee80211_local *local = sdata->local; | ||
143 | int err; | ||
144 | |||
145 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) && | ||
146 | smps_mode == IEEE80211_SMPS_STATIC) | ||
147 | return -EINVAL; | ||
148 | |||
149 | /* auto should be dynamic if in PS mode */ | ||
150 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) && | ||
151 | (smps_mode == IEEE80211_SMPS_DYNAMIC || | ||
152 | smps_mode == IEEE80211_SMPS_AUTOMATIC)) | ||
153 | return -EINVAL; | ||
154 | |||
155 | /* supported only on managed interfaces for now */ | ||
156 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
157 | return -EOPNOTSUPP; | ||
158 | |||
159 | mutex_lock(&local->iflist_mtx); | ||
160 | err = __ieee80211_request_smps(sdata, smps_mode); | ||
161 | mutex_unlock(&local->iflist_mtx); | ||
162 | |||
163 | return err; | ||
164 | } | ||
165 | |||
166 | static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { | ||
167 | [IEEE80211_SMPS_AUTOMATIC] = "auto", | ||
168 | [IEEE80211_SMPS_OFF] = "off", | ||
169 | [IEEE80211_SMPS_STATIC] = "static", | ||
170 | [IEEE80211_SMPS_DYNAMIC] = "dynamic", | ||
171 | }; | ||
172 | |||
173 | static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata, | ||
174 | char *buf, int buflen) | ||
175 | { | ||
176 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
177 | return -EOPNOTSUPP; | ||
178 | |||
179 | return snprintf(buf, buflen, "request: %s\nused: %s\n", | ||
180 | smps_modes[sdata->u.mgd.req_smps], | ||
181 | smps_modes[sdata->u.mgd.ap_smps]); | ||
182 | } | ||
183 | |||
184 | static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata, | ||
185 | const char *buf, int buflen) | ||
186 | { | ||
187 | enum ieee80211_smps_mode mode; | ||
188 | |||
189 | for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) { | ||
190 | if (strncmp(buf, smps_modes[mode], buflen) == 0) { | ||
191 | int err = ieee80211_set_smps(sdata, mode); | ||
192 | if (!err) | ||
193 | return buflen; | ||
194 | return err; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | __IEEE80211_IF_FILE_W(smps); | ||
101 | 202 | ||
102 | /* AP attributes */ | 203 | /* AP attributes */ |
103 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 204 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
@@ -109,7 +210,7 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( | |||
109 | return scnprintf(buf, buflen, "%u\n", | 210 | return scnprintf(buf, buflen, "%u\n", |
110 | skb_queue_len(&sdata->u.ap.ps_bc_buf)); | 211 | skb_queue_len(&sdata->u.ap.ps_bc_buf)); |
111 | } | 212 | } |
112 | __IEEE80211_IF_FILE(num_buffered_multicast); | 213 | __IEEE80211_IF_FILE(num_buffered_multicast, NULL); |
113 | 214 | ||
114 | /* WDS attributes */ | 215 | /* WDS attributes */ |
115 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | 216 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); |
@@ -154,46 +255,50 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, | |||
154 | #endif | 255 | #endif |
155 | 256 | ||
156 | 257 | ||
157 | #define DEBUGFS_ADD(name, type) \ | 258 | #define DEBUGFS_ADD(name) \ |
158 | debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ | 259 | debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ |
159 | sdata, &name##_ops); | 260 | sdata, &name##_ops); |
160 | 261 | ||
262 | #define DEBUGFS_ADD_MODE(name, mode) \ | ||
263 | debugfs_create_file(#name, mode, sdata->debugfs.dir, \ | ||
264 | sdata, &name##_ops); | ||
265 | |||
161 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 266 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
162 | { | 267 | { |
163 | DEBUGFS_ADD(drop_unencrypted, sta); | 268 | DEBUGFS_ADD(drop_unencrypted); |
164 | DEBUGFS_ADD(force_unicast_rateidx, sta); | 269 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
165 | DEBUGFS_ADD(max_ratectrl_rateidx, sta); | 270 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
166 | 271 | ||
167 | DEBUGFS_ADD(bssid, sta); | 272 | DEBUGFS_ADD(bssid); |
168 | DEBUGFS_ADD(aid, sta); | 273 | DEBUGFS_ADD(aid); |
169 | DEBUGFS_ADD(capab, sta); | 274 | DEBUGFS_ADD_MODE(smps, 0600); |
170 | } | 275 | } |
171 | 276 | ||
172 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 277 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
173 | { | 278 | { |
174 | DEBUGFS_ADD(drop_unencrypted, ap); | 279 | DEBUGFS_ADD(drop_unencrypted); |
175 | DEBUGFS_ADD(force_unicast_rateidx, ap); | 280 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
176 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | 281 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
177 | 282 | ||
178 | DEBUGFS_ADD(num_sta_ps, ap); | 283 | DEBUGFS_ADD(num_sta_ps); |
179 | DEBUGFS_ADD(dtim_count, ap); | 284 | DEBUGFS_ADD(dtim_count); |
180 | DEBUGFS_ADD(num_buffered_multicast, ap); | 285 | DEBUGFS_ADD(num_buffered_multicast); |
181 | } | 286 | } |
182 | 287 | ||
183 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 288 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
184 | { | 289 | { |
185 | DEBUGFS_ADD(drop_unencrypted, wds); | 290 | DEBUGFS_ADD(drop_unencrypted); |
186 | DEBUGFS_ADD(force_unicast_rateidx, wds); | 291 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
187 | DEBUGFS_ADD(max_ratectrl_rateidx, wds); | 292 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
188 | 293 | ||
189 | DEBUGFS_ADD(peer, wds); | 294 | DEBUGFS_ADD(peer); |
190 | } | 295 | } |
191 | 296 | ||
192 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 297 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) |
193 | { | 298 | { |
194 | DEBUGFS_ADD(drop_unencrypted, vlan); | 299 | DEBUGFS_ADD(drop_unencrypted); |
195 | DEBUGFS_ADD(force_unicast_rateidx, vlan); | 300 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
196 | DEBUGFS_ADD(max_ratectrl_rateidx, vlan); | 301 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
197 | } | 302 | } |
198 | 303 | ||
199 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 304 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
@@ -280,16 +385,11 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
280 | } | 385 | } |
281 | } | 386 | } |
282 | 387 | ||
283 | static int notif_registered; | ||
284 | |||
285 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) | 388 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) |
286 | { | 389 | { |
287 | char buf[10+IFNAMSIZ]; | 390 | char buf[10+IFNAMSIZ]; |
288 | 391 | ||
289 | if (!notif_registered) | 392 | sprintf(buf, "netdev:%s", sdata->name); |
290 | return; | ||
291 | |||
292 | sprintf(buf, "netdev:%s", sdata->dev->name); | ||
293 | sdata->debugfs.dir = debugfs_create_dir(buf, | 393 | sdata->debugfs.dir = debugfs_create_dir(buf, |
294 | sdata->local->hw.wiphy->debugfsdir); | 394 | sdata->local->hw.wiphy->debugfsdir); |
295 | add_files(sdata); | 395 | add_files(sdata); |
@@ -304,58 +404,18 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) | |||
304 | sdata->debugfs.dir = NULL; | 404 | sdata->debugfs.dir = NULL; |
305 | } | 405 | } |
306 | 406 | ||
307 | static int netdev_notify(struct notifier_block *nb, | 407 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) |
308 | unsigned long state, | ||
309 | void *ndev) | ||
310 | { | 408 | { |
311 | struct net_device *dev = ndev; | ||
312 | struct dentry *dir; | 409 | struct dentry *dir; |
313 | struct ieee80211_sub_if_data *sdata; | 410 | char buf[10 + IFNAMSIZ]; |
314 | char buf[10+IFNAMSIZ]; | ||
315 | |||
316 | if (state != NETDEV_CHANGENAME) | ||
317 | return 0; | ||
318 | |||
319 | if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) | ||
320 | return 0; | ||
321 | |||
322 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | ||
323 | return 0; | ||
324 | |||
325 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
326 | 411 | ||
327 | dir = sdata->debugfs.dir; | 412 | dir = sdata->debugfs.dir; |
328 | 413 | ||
329 | if (!dir) | 414 | if (!dir) |
330 | return 0; | 415 | return; |
331 | 416 | ||
332 | sprintf(buf, "netdev:%s", dev->name); | 417 | sprintf(buf, "netdev:%s", sdata->name); |
333 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) | 418 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) |
334 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " | 419 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " |
335 | "dir to %s\n", buf); | 420 | "dir to %s\n", buf); |
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static struct notifier_block mac80211_debugfs_netdev_notifier = { | ||
341 | .notifier_call = netdev_notify, | ||
342 | }; | ||
343 | |||
344 | void ieee80211_debugfs_netdev_init(void) | ||
345 | { | ||
346 | int err; | ||
347 | |||
348 | err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier); | ||
349 | if (err) { | ||
350 | printk(KERN_ERR | ||
351 | "mac80211: failed to install netdev notifier," | ||
352 | " disabling per-netdev debugfs!\n"); | ||
353 | } else | ||
354 | notif_registered = 1; | ||
355 | } | ||
356 | |||
357 | void ieee80211_debugfs_netdev_exit(void) | ||
358 | { | ||
359 | unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier); | ||
360 | notif_registered = 0; | ||
361 | } | 421 | } |
diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h index 7af731f0b731..79025e79f4d6 100644 --- a/net/mac80211/debugfs_netdev.h +++ b/net/mac80211/debugfs_netdev.h | |||
@@ -6,8 +6,7 @@ | |||
6 | #ifdef CONFIG_MAC80211_DEBUGFS | 6 | #ifdef CONFIG_MAC80211_DEBUGFS |
7 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata); | 7 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata); |
8 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); | 8 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); |
9 | void ieee80211_debugfs_netdev_init(void); | 9 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata); |
10 | void ieee80211_debugfs_netdev_exit(void); | ||
11 | #else | 10 | #else |
12 | static inline void ieee80211_debugfs_add_netdev( | 11 | static inline void ieee80211_debugfs_add_netdev( |
13 | struct ieee80211_sub_if_data *sdata) | 12 | struct ieee80211_sub_if_data *sdata) |
@@ -15,10 +14,8 @@ static inline void ieee80211_debugfs_add_netdev( | |||
15 | static inline void ieee80211_debugfs_remove_netdev( | 14 | static inline void ieee80211_debugfs_remove_netdev( |
16 | struct ieee80211_sub_if_data *sdata) | 15 | struct ieee80211_sub_if_data *sdata) |
17 | {} | 16 | {} |
18 | static inline void ieee80211_debugfs_netdev_init(void) | 17 | static inline void ieee80211_debugfs_rename_netdev( |
19 | {} | 18 | struct ieee80211_sub_if_data *sdata) |
20 | |||
21 | static inline void ieee80211_debugfs_netdev_exit(void) | ||
22 | {} | 19 | {} |
23 | #endif | 20 | #endif |
24 | 21 | ||
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 3f41608c8081..d92800bb2d2f 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -44,7 +44,7 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
44 | STA_OPS(name) | 44 | STA_OPS(name) |
45 | 45 | ||
46 | STA_FILE(aid, sta.aid, D); | 46 | STA_FILE(aid, sta.aid, D); |
47 | STA_FILE(dev, sdata->dev->name, S); | 47 | STA_FILE(dev, sdata->name, S); |
48 | STA_FILE(rx_packets, rx_packets, LU); | 48 | STA_FILE(rx_packets, rx_packets, LU); |
49 | STA_FILE(tx_packets, tx_packets, LU); | 49 | STA_FILE(tx_packets, tx_packets, LU); |
50 | STA_FILE(rx_bytes, rx_bytes, LU); | 50 | STA_FILE(rx_bytes, rx_bytes, LU); |
@@ -120,36 +120,38 @@ STA_OPS(last_seq_ctrl); | |||
120 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | 120 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, |
121 | size_t count, loff_t *ppos) | 121 | size_t count, loff_t *ppos) |
122 | { | 122 | { |
123 | char buf[30 + STA_TID_NUM * 70], *p = buf; | 123 | char buf[64 + STA_TID_NUM * 40], *p = buf; |
124 | int i; | 124 | int i; |
125 | struct sta_info *sta = file->private_data; | 125 | struct sta_info *sta = file->private_data; |
126 | 126 | ||
127 | spin_lock_bh(&sta->lock); | 127 | spin_lock_bh(&sta->lock); |
128 | p += scnprintf(p, sizeof(buf)+buf-p, "next dialog_token is %#02x\n", | 128 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", |
129 | sta->ampdu_mlme.dialog_token_allocator + 1); | 129 | sta->ampdu_mlme.dialog_token_allocator + 1); |
130 | p += scnprintf(p, sizeof(buf) + buf - p, | ||
131 | "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n"); | ||
130 | for (i = 0; i < STA_TID_NUM; i++) { | 132 | for (i = 0; i < STA_TID_NUM; i++) { |
131 | p += scnprintf(p, sizeof(buf)+buf-p, "TID %02d:", i); | 133 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); |
132 | p += scnprintf(p, sizeof(buf)+buf-p, " RX=%x", | 134 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
133 | sta->ampdu_mlme.tid_state_rx[i]); | 135 | sta->ampdu_mlme.tid_state_rx[i]); |
134 | p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x", | 136 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
135 | sta->ampdu_mlme.tid_state_rx[i] ? | 137 | sta->ampdu_mlme.tid_state_rx[i] ? |
136 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); | 138 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); |
137 | p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x", | 139 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", |
138 | sta->ampdu_mlme.tid_state_rx[i] ? | 140 | sta->ampdu_mlme.tid_state_rx[i] ? |
139 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); | 141 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); |
140 | 142 | ||
141 | p += scnprintf(p, sizeof(buf)+buf-p, " TX=%x", | 143 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
142 | sta->ampdu_mlme.tid_state_tx[i]); | 144 | sta->ampdu_mlme.tid_state_tx[i]); |
143 | p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x", | 145 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
144 | sta->ampdu_mlme.tid_state_tx[i] ? | 146 | sta->ampdu_mlme.tid_state_tx[i] ? |
145 | sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); | 147 | sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); |
146 | p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x", | 148 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", |
147 | sta->ampdu_mlme.tid_state_tx[i] ? | 149 | sta->ampdu_mlme.tid_state_tx[i] ? |
148 | sta->ampdu_mlme.tid_tx[i]->ssn : 0); | 150 | sta->ampdu_mlme.tid_tx[i]->ssn : 0); |
149 | p += scnprintf(p, sizeof(buf)+buf-p, "/pending=%03d", | 151 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d", |
150 | sta->ampdu_mlme.tid_state_tx[i] ? | 152 | sta->ampdu_mlme.tid_state_tx[i] ? |
151 | skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0); | 153 | skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0); |
152 | p += scnprintf(p, sizeof(buf)+buf-p, "\n"); | 154 | p += scnprintf(p, sizeof(buf) + buf - p, "\n"); |
153 | } | 155 | } |
154 | spin_unlock_bh(&sta->lock); | 156 | spin_unlock_bh(&sta->lock); |
155 | 157 | ||
@@ -160,7 +162,12 @@ STA_OPS(agg_status); | |||
160 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | 162 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, |
161 | size_t count, loff_t *ppos) | 163 | size_t count, loff_t *ppos) |
162 | { | 164 | { |
163 | char buf[200], *p = buf; | 165 | #define PRINT_HT_CAP(_cond, _str) \ |
166 | do { \ | ||
167 | if (_cond) \ | ||
168 | p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \ | ||
169 | } while (0) | ||
170 | char buf[512], *p = buf; | ||
164 | int i; | 171 | int i; |
165 | struct sta_info *sta = file->private_data; | 172 | struct sta_info *sta = file->private_data; |
166 | struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap; | 173 | struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap; |
@@ -168,15 +175,64 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | |||
168 | p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n", | 175 | p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n", |
169 | htc->ht_supported ? "" : "not "); | 176 | htc->ht_supported ? "" : "not "); |
170 | if (htc->ht_supported) { | 177 | if (htc->ht_supported) { |
171 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.2x\n", htc->cap); | 178 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap); |
179 | |||
180 | PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDCP"); | ||
181 | PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40"); | ||
182 | PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20"); | ||
183 | |||
184 | PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 0, "Static SM Power Save"); | ||
185 | PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 1, "Dynamic SM Power Save"); | ||
186 | PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 3, "SM Power Save disabled"); | ||
187 | |||
188 | PRINT_HT_CAP((htc->cap & BIT(4)), "RX Greenfield"); | ||
189 | PRINT_HT_CAP((htc->cap & BIT(5)), "RX HT20 SGI"); | ||
190 | PRINT_HT_CAP((htc->cap & BIT(6)), "RX HT40 SGI"); | ||
191 | PRINT_HT_CAP((htc->cap & BIT(7)), "TX STBC"); | ||
192 | |||
193 | PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 0, "No RX STBC"); | ||
194 | PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 1, "RX STBC 1-stream"); | ||
195 | PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 2, "RX STBC 2-streams"); | ||
196 | PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 3, "RX STBC 3-streams"); | ||
197 | |||
198 | PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack"); | ||
199 | |||
200 | PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: " | ||
201 | "3839 bytes"); | ||
202 | PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: " | ||
203 | "7935 bytes"); | ||
204 | |||
205 | /* | ||
206 | * For beacons and probe response this would mean the BSS | ||
207 | * does or does not allow the usage of DSSS/CCK HT40. | ||
208 | * Otherwise it means the STA does or does not use | ||
209 | * DSSS/CCK HT40. | ||
210 | */ | ||
211 | PRINT_HT_CAP((htc->cap & BIT(12)), "DSSS/CCK HT40"); | ||
212 | PRINT_HT_CAP(!(htc->cap & BIT(12)), "No DSSS/CCK HT40"); | ||
213 | |||
214 | /* BIT(13) is reserved */ | ||
215 | |||
216 | PRINT_HT_CAP((htc->cap & BIT(14)), "40 MHz Intolerant"); | ||
217 | |||
218 | PRINT_HT_CAP((htc->cap & BIT(15)), "L-SIG TXOP protection"); | ||
219 | |||
172 | p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n", | 220 | p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n", |
173 | htc->ampdu_factor, htc->ampdu_density); | 221 | htc->ampdu_factor, htc->ampdu_density); |
174 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:"); | 222 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:"); |
223 | |||
175 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) | 224 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) |
176 | p += scnprintf(p, sizeof(buf)+buf-p, " %.2x", | 225 | p += scnprintf(p, sizeof(buf)+buf-p, " %.2x", |
177 | htc->mcs.rx_mask[i]); | 226 | htc->mcs.rx_mask[i]); |
178 | p += scnprintf(p, sizeof(buf)+buf-p, "\nMCS rx highest: %d\n", | 227 | p += scnprintf(p, sizeof(buf)+buf-p, "\n"); |
179 | le16_to_cpu(htc->mcs.rx_highest)); | 228 | |
229 | /* If not set this is meaningless */ | ||
230 | if (le16_to_cpu(htc->mcs.rx_highest)) { | ||
231 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
232 | "MCS rx highest: %d Mbps\n", | ||
233 | le16_to_cpu(htc->mcs.rx_highest)); | ||
234 | } | ||
235 | |||
180 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS tx params: %x\n", | 236 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS tx params: %x\n", |
181 | htc->mcs.tx_params); | 237 | htc->mcs.tx_params); |
182 | } | 238 | } |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 921dd9c9ff62..c3d844093a2f 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -14,6 +14,8 @@ static inline int drv_start(struct ieee80211_local *local) | |||
14 | { | 14 | { |
15 | int ret; | 15 | int ret; |
16 | 16 | ||
17 | might_sleep(); | ||
18 | |||
17 | local->started = true; | 19 | local->started = true; |
18 | smp_mb(); | 20 | smp_mb(); |
19 | ret = local->ops->start(&local->hw); | 21 | ret = local->ops->start(&local->hw); |
@@ -23,6 +25,8 @@ static inline int drv_start(struct ieee80211_local *local) | |||
23 | 25 | ||
24 | static inline void drv_stop(struct ieee80211_local *local) | 26 | static inline void drv_stop(struct ieee80211_local *local) |
25 | { | 27 | { |
28 | might_sleep(); | ||
29 | |||
26 | local->ops->stop(&local->hw); | 30 | local->ops->stop(&local->hw); |
27 | trace_drv_stop(local); | 31 | trace_drv_stop(local); |
28 | 32 | ||
@@ -36,35 +40,47 @@ static inline void drv_stop(struct ieee80211_local *local) | |||
36 | } | 40 | } |
37 | 41 | ||
38 | static inline int drv_add_interface(struct ieee80211_local *local, | 42 | static inline int drv_add_interface(struct ieee80211_local *local, |
39 | struct ieee80211_if_init_conf *conf) | 43 | struct ieee80211_vif *vif) |
40 | { | 44 | { |
41 | int ret = local->ops->add_interface(&local->hw, conf); | 45 | int ret; |
42 | trace_drv_add_interface(local, conf->mac_addr, conf->vif, ret); | 46 | |
47 | might_sleep(); | ||
48 | |||
49 | ret = local->ops->add_interface(&local->hw, vif); | ||
50 | trace_drv_add_interface(local, vif_to_sdata(vif), ret); | ||
43 | return ret; | 51 | return ret; |
44 | } | 52 | } |
45 | 53 | ||
46 | static inline void drv_remove_interface(struct ieee80211_local *local, | 54 | static inline void drv_remove_interface(struct ieee80211_local *local, |
47 | struct ieee80211_if_init_conf *conf) | 55 | struct ieee80211_vif *vif) |
48 | { | 56 | { |
49 | local->ops->remove_interface(&local->hw, conf); | 57 | might_sleep(); |
50 | trace_drv_remove_interface(local, conf->mac_addr, conf->vif); | 58 | |
59 | local->ops->remove_interface(&local->hw, vif); | ||
60 | trace_drv_remove_interface(local, vif_to_sdata(vif)); | ||
51 | } | 61 | } |
52 | 62 | ||
53 | static inline int drv_config(struct ieee80211_local *local, u32 changed) | 63 | static inline int drv_config(struct ieee80211_local *local, u32 changed) |
54 | { | 64 | { |
55 | int ret = local->ops->config(&local->hw, changed); | 65 | int ret; |
66 | |||
67 | might_sleep(); | ||
68 | |||
69 | ret = local->ops->config(&local->hw, changed); | ||
56 | trace_drv_config(local, changed, ret); | 70 | trace_drv_config(local, changed, ret); |
57 | return ret; | 71 | return ret; |
58 | } | 72 | } |
59 | 73 | ||
60 | static inline void drv_bss_info_changed(struct ieee80211_local *local, | 74 | static inline void drv_bss_info_changed(struct ieee80211_local *local, |
61 | struct ieee80211_vif *vif, | 75 | struct ieee80211_sub_if_data *sdata, |
62 | struct ieee80211_bss_conf *info, | 76 | struct ieee80211_bss_conf *info, |
63 | u32 changed) | 77 | u32 changed) |
64 | { | 78 | { |
79 | might_sleep(); | ||
80 | |||
65 | if (local->ops->bss_info_changed) | 81 | if (local->ops->bss_info_changed) |
66 | local->ops->bss_info_changed(&local->hw, vif, info, changed); | 82 | local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); |
67 | trace_drv_bss_info_changed(local, vif, info, changed); | 83 | trace_drv_bss_info_changed(local, sdata, info, changed); |
68 | } | 84 | } |
69 | 85 | ||
70 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | 86 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, |
@@ -106,36 +122,53 @@ static inline int drv_set_tim(struct ieee80211_local *local, | |||
106 | } | 122 | } |
107 | 123 | ||
108 | static inline int drv_set_key(struct ieee80211_local *local, | 124 | static inline int drv_set_key(struct ieee80211_local *local, |
109 | enum set_key_cmd cmd, struct ieee80211_vif *vif, | 125 | enum set_key_cmd cmd, |
126 | struct ieee80211_sub_if_data *sdata, | ||
110 | struct ieee80211_sta *sta, | 127 | struct ieee80211_sta *sta, |
111 | struct ieee80211_key_conf *key) | 128 | struct ieee80211_key_conf *key) |
112 | { | 129 | { |
113 | int ret = local->ops->set_key(&local->hw, cmd, vif, sta, key); | 130 | int ret; |
114 | trace_drv_set_key(local, cmd, vif, sta, key, ret); | 131 | |
132 | might_sleep(); | ||
133 | |||
134 | ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); | ||
135 | trace_drv_set_key(local, cmd, sdata, sta, key, ret); | ||
115 | return ret; | 136 | return ret; |
116 | } | 137 | } |
117 | 138 | ||
118 | static inline void drv_update_tkip_key(struct ieee80211_local *local, | 139 | static inline void drv_update_tkip_key(struct ieee80211_local *local, |
140 | struct ieee80211_sub_if_data *sdata, | ||
119 | struct ieee80211_key_conf *conf, | 141 | struct ieee80211_key_conf *conf, |
120 | const u8 *address, u32 iv32, | 142 | struct sta_info *sta, u32 iv32, |
121 | u16 *phase1key) | 143 | u16 *phase1key) |
122 | { | 144 | { |
145 | struct ieee80211_sta *ista = NULL; | ||
146 | |||
147 | if (sta) | ||
148 | ista = &sta->sta; | ||
149 | |||
123 | if (local->ops->update_tkip_key) | 150 | if (local->ops->update_tkip_key) |
124 | local->ops->update_tkip_key(&local->hw, conf, address, | 151 | local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, |
125 | iv32, phase1key); | 152 | ista, iv32, phase1key); |
126 | trace_drv_update_tkip_key(local, conf, address, iv32); | 153 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); |
127 | } | 154 | } |
128 | 155 | ||
129 | static inline int drv_hw_scan(struct ieee80211_local *local, | 156 | static inline int drv_hw_scan(struct ieee80211_local *local, |
130 | struct cfg80211_scan_request *req) | 157 | struct cfg80211_scan_request *req) |
131 | { | 158 | { |
132 | int ret = local->ops->hw_scan(&local->hw, req); | 159 | int ret; |
160 | |||
161 | might_sleep(); | ||
162 | |||
163 | ret = local->ops->hw_scan(&local->hw, req); | ||
133 | trace_drv_hw_scan(local, req, ret); | 164 | trace_drv_hw_scan(local, req, ret); |
134 | return ret; | 165 | return ret; |
135 | } | 166 | } |
136 | 167 | ||
137 | static inline void drv_sw_scan_start(struct ieee80211_local *local) | 168 | static inline void drv_sw_scan_start(struct ieee80211_local *local) |
138 | { | 169 | { |
170 | might_sleep(); | ||
171 | |||
139 | if (local->ops->sw_scan_start) | 172 | if (local->ops->sw_scan_start) |
140 | local->ops->sw_scan_start(&local->hw); | 173 | local->ops->sw_scan_start(&local->hw); |
141 | trace_drv_sw_scan_start(local); | 174 | trace_drv_sw_scan_start(local); |
@@ -143,6 +176,8 @@ static inline void drv_sw_scan_start(struct ieee80211_local *local) | |||
143 | 176 | ||
144 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) | 177 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) |
145 | { | 178 | { |
179 | might_sleep(); | ||
180 | |||
146 | if (local->ops->sw_scan_complete) | 181 | if (local->ops->sw_scan_complete) |
147 | local->ops->sw_scan_complete(&local->hw); | 182 | local->ops->sw_scan_complete(&local->hw); |
148 | trace_drv_sw_scan_complete(local); | 183 | trace_drv_sw_scan_complete(local); |
@@ -153,6 +188,8 @@ static inline int drv_get_stats(struct ieee80211_local *local, | |||
153 | { | 188 | { |
154 | int ret = -EOPNOTSUPP; | 189 | int ret = -EOPNOTSUPP; |
155 | 190 | ||
191 | might_sleep(); | ||
192 | |||
156 | if (local->ops->get_stats) | 193 | if (local->ops->get_stats) |
157 | ret = local->ops->get_stats(&local->hw, stats); | 194 | ret = local->ops->get_stats(&local->hw, stats); |
158 | trace_drv_get_stats(local, stats, ret); | 195 | trace_drv_get_stats(local, stats, ret); |
@@ -172,43 +209,93 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local, | |||
172 | u32 value) | 209 | u32 value) |
173 | { | 210 | { |
174 | int ret = 0; | 211 | int ret = 0; |
212 | |||
213 | might_sleep(); | ||
214 | |||
175 | if (local->ops->set_rts_threshold) | 215 | if (local->ops->set_rts_threshold) |
176 | ret = local->ops->set_rts_threshold(&local->hw, value); | 216 | ret = local->ops->set_rts_threshold(&local->hw, value); |
177 | trace_drv_set_rts_threshold(local, value, ret); | 217 | trace_drv_set_rts_threshold(local, value, ret); |
178 | return ret; | 218 | return ret; |
179 | } | 219 | } |
180 | 220 | ||
221 | static inline int drv_set_coverage_class(struct ieee80211_local *local, | ||
222 | u8 value) | ||
223 | { | ||
224 | int ret = 0; | ||
225 | might_sleep(); | ||
226 | |||
227 | if (local->ops->set_coverage_class) | ||
228 | local->ops->set_coverage_class(&local->hw, value); | ||
229 | else | ||
230 | ret = -EOPNOTSUPP; | ||
231 | |||
232 | trace_drv_set_coverage_class(local, value, ret); | ||
233 | return ret; | ||
234 | } | ||
235 | |||
181 | static inline void drv_sta_notify(struct ieee80211_local *local, | 236 | static inline void drv_sta_notify(struct ieee80211_local *local, |
182 | struct ieee80211_vif *vif, | 237 | struct ieee80211_sub_if_data *sdata, |
183 | enum sta_notify_cmd cmd, | 238 | enum sta_notify_cmd cmd, |
184 | struct ieee80211_sta *sta) | 239 | struct ieee80211_sta *sta) |
185 | { | 240 | { |
186 | if (local->ops->sta_notify) | 241 | if (local->ops->sta_notify) |
187 | local->ops->sta_notify(&local->hw, vif, cmd, sta); | 242 | local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); |
188 | trace_drv_sta_notify(local, vif, cmd, sta); | 243 | trace_drv_sta_notify(local, sdata, cmd, sta); |
244 | } | ||
245 | |||
246 | static inline int drv_sta_add(struct ieee80211_local *local, | ||
247 | struct ieee80211_sub_if_data *sdata, | ||
248 | struct ieee80211_sta *sta) | ||
249 | { | ||
250 | int ret = 0; | ||
251 | |||
252 | might_sleep(); | ||
253 | |||
254 | if (local->ops->sta_add) | ||
255 | ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); | ||
256 | else if (local->ops->sta_notify) | ||
257 | local->ops->sta_notify(&local->hw, &sdata->vif, | ||
258 | STA_NOTIFY_ADD, sta); | ||
259 | |||
260 | trace_drv_sta_add(local, sdata, sta, ret); | ||
261 | |||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | static inline void drv_sta_remove(struct ieee80211_local *local, | ||
266 | struct ieee80211_sub_if_data *sdata, | ||
267 | struct ieee80211_sta *sta) | ||
268 | { | ||
269 | might_sleep(); | ||
270 | |||
271 | if (local->ops->sta_remove) | ||
272 | local->ops->sta_remove(&local->hw, &sdata->vif, sta); | ||
273 | else if (local->ops->sta_notify) | ||
274 | local->ops->sta_notify(&local->hw, &sdata->vif, | ||
275 | STA_NOTIFY_REMOVE, sta); | ||
276 | |||
277 | trace_drv_sta_remove(local, sdata, sta); | ||
189 | } | 278 | } |
190 | 279 | ||
191 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | 280 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, |
192 | const struct ieee80211_tx_queue_params *params) | 281 | const struct ieee80211_tx_queue_params *params) |
193 | { | 282 | { |
194 | int ret = -EOPNOTSUPP; | 283 | int ret = -EOPNOTSUPP; |
284 | |||
285 | might_sleep(); | ||
286 | |||
195 | if (local->ops->conf_tx) | 287 | if (local->ops->conf_tx) |
196 | ret = local->ops->conf_tx(&local->hw, queue, params); | 288 | ret = local->ops->conf_tx(&local->hw, queue, params); |
197 | trace_drv_conf_tx(local, queue, params, ret); | 289 | trace_drv_conf_tx(local, queue, params, ret); |
198 | return ret; | 290 | return ret; |
199 | } | 291 | } |
200 | 292 | ||
201 | static inline int drv_get_tx_stats(struct ieee80211_local *local, | ||
202 | struct ieee80211_tx_queue_stats *stats) | ||
203 | { | ||
204 | int ret = local->ops->get_tx_stats(&local->hw, stats); | ||
205 | trace_drv_get_tx_stats(local, stats, ret); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | static inline u64 drv_get_tsf(struct ieee80211_local *local) | 293 | static inline u64 drv_get_tsf(struct ieee80211_local *local) |
210 | { | 294 | { |
211 | u64 ret = -1ULL; | 295 | u64 ret = -1ULL; |
296 | |||
297 | might_sleep(); | ||
298 | |||
212 | if (local->ops->get_tsf) | 299 | if (local->ops->get_tsf) |
213 | ret = local->ops->get_tsf(&local->hw); | 300 | ret = local->ops->get_tsf(&local->hw); |
214 | trace_drv_get_tsf(local, ret); | 301 | trace_drv_get_tsf(local, ret); |
@@ -217,6 +304,8 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local) | |||
217 | 304 | ||
218 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | 305 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) |
219 | { | 306 | { |
307 | might_sleep(); | ||
308 | |||
220 | if (local->ops->set_tsf) | 309 | if (local->ops->set_tsf) |
221 | local->ops->set_tsf(&local->hw, tsf); | 310 | local->ops->set_tsf(&local->hw, tsf); |
222 | trace_drv_set_tsf(local, tsf); | 311 | trace_drv_set_tsf(local, tsf); |
@@ -224,6 +313,8 @@ static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | |||
224 | 313 | ||
225 | static inline void drv_reset_tsf(struct ieee80211_local *local) | 314 | static inline void drv_reset_tsf(struct ieee80211_local *local) |
226 | { | 315 | { |
316 | might_sleep(); | ||
317 | |||
227 | if (local->ops->reset_tsf) | 318 | if (local->ops->reset_tsf) |
228 | local->ops->reset_tsf(&local->hw); | 319 | local->ops->reset_tsf(&local->hw); |
229 | trace_drv_reset_tsf(local); | 320 | trace_drv_reset_tsf(local); |
@@ -232,6 +323,9 @@ static inline void drv_reset_tsf(struct ieee80211_local *local) | |||
232 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 323 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) |
233 | { | 324 | { |
234 | int ret = 1; | 325 | int ret = 1; |
326 | |||
327 | might_sleep(); | ||
328 | |||
235 | if (local->ops->tx_last_beacon) | 329 | if (local->ops->tx_last_beacon) |
236 | ret = local->ops->tx_last_beacon(&local->hw); | 330 | ret = local->ops->tx_last_beacon(&local->hw); |
237 | trace_drv_tx_last_beacon(local, ret); | 331 | trace_drv_tx_last_beacon(local, ret); |
@@ -239,23 +333,34 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) | |||
239 | } | 333 | } |
240 | 334 | ||
241 | static inline int drv_ampdu_action(struct ieee80211_local *local, | 335 | static inline int drv_ampdu_action(struct ieee80211_local *local, |
242 | struct ieee80211_vif *vif, | 336 | struct ieee80211_sub_if_data *sdata, |
243 | enum ieee80211_ampdu_mlme_action action, | 337 | enum ieee80211_ampdu_mlme_action action, |
244 | struct ieee80211_sta *sta, u16 tid, | 338 | struct ieee80211_sta *sta, u16 tid, |
245 | u16 *ssn) | 339 | u16 *ssn) |
246 | { | 340 | { |
247 | int ret = -EOPNOTSUPP; | 341 | int ret = -EOPNOTSUPP; |
248 | if (local->ops->ampdu_action) | 342 | if (local->ops->ampdu_action) |
249 | ret = local->ops->ampdu_action(&local->hw, vif, action, | 343 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, |
250 | sta, tid, ssn); | 344 | sta, tid, ssn); |
251 | trace_drv_ampdu_action(local, vif, action, sta, tid, ssn, ret); | 345 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, ret); |
252 | return ret; | 346 | return ret; |
253 | } | 347 | } |
254 | 348 | ||
255 | 349 | ||
256 | static inline void drv_rfkill_poll(struct ieee80211_local *local) | 350 | static inline void drv_rfkill_poll(struct ieee80211_local *local) |
257 | { | 351 | { |
352 | might_sleep(); | ||
353 | |||
258 | if (local->ops->rfkill_poll) | 354 | if (local->ops->rfkill_poll) |
259 | local->ops->rfkill_poll(&local->hw); | 355 | local->ops->rfkill_poll(&local->hw); |
260 | } | 356 | } |
357 | |||
358 | static inline void drv_flush(struct ieee80211_local *local, bool drop) | ||
359 | { | ||
360 | might_sleep(); | ||
361 | |||
362 | trace_drv_flush(local, drop); | ||
363 | if (local->ops->flush) | ||
364 | local->ops->flush(&local->hw, drop); | ||
365 | } | ||
261 | #endif /* __MAC80211_DRIVER_OPS */ | 366 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index da8497ef7063..41baf730a5c7 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -25,10 +25,12 @@ static inline void trace_ ## name(proto) {} | |||
25 | #define STA_PR_FMT " sta:%pM" | 25 | #define STA_PR_FMT " sta:%pM" |
26 | #define STA_PR_ARG __entry->sta_addr | 26 | #define STA_PR_ARG __entry->sta_addr |
27 | 27 | ||
28 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, vif) | 28 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ |
29 | #define VIF_ASSIGN __entry->vif_type = vif ? vif->type : 0; __entry->vif = vif | 29 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
30 | #define VIF_PR_FMT " vif:%p(%d)" | 30 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ |
31 | #define VIF_PR_ARG __entry->vif, __entry->vif_type | 31 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
32 | #define VIF_PR_FMT " vif:%s(%d)" | ||
33 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type | ||
32 | 34 | ||
33 | TRACE_EVENT(drv_start, | 35 | TRACE_EVENT(drv_start, |
34 | TP_PROTO(struct ieee80211_local *local, int ret), | 36 | TP_PROTO(struct ieee80211_local *local, int ret), |
@@ -70,11 +72,10 @@ TRACE_EVENT(drv_stop, | |||
70 | 72 | ||
71 | TRACE_EVENT(drv_add_interface, | 73 | TRACE_EVENT(drv_add_interface, |
72 | TP_PROTO(struct ieee80211_local *local, | 74 | TP_PROTO(struct ieee80211_local *local, |
73 | const u8 *addr, | 75 | struct ieee80211_sub_if_data *sdata, |
74 | struct ieee80211_vif *vif, | ||
75 | int ret), | 76 | int ret), |
76 | 77 | ||
77 | TP_ARGS(local, addr, vif, ret), | 78 | TP_ARGS(local, sdata, ret), |
78 | 79 | ||
79 | TP_STRUCT__entry( | 80 | TP_STRUCT__entry( |
80 | LOCAL_ENTRY | 81 | LOCAL_ENTRY |
@@ -86,7 +87,7 @@ TRACE_EVENT(drv_add_interface, | |||
86 | TP_fast_assign( | 87 | TP_fast_assign( |
87 | LOCAL_ASSIGN; | 88 | LOCAL_ASSIGN; |
88 | VIF_ASSIGN; | 89 | VIF_ASSIGN; |
89 | memcpy(__entry->addr, addr, 6); | 90 | memcpy(__entry->addr, sdata->vif.addr, 6); |
90 | __entry->ret = ret; | 91 | __entry->ret = ret; |
91 | ), | 92 | ), |
92 | 93 | ||
@@ -97,10 +98,9 @@ TRACE_EVENT(drv_add_interface, | |||
97 | ); | 98 | ); |
98 | 99 | ||
99 | TRACE_EVENT(drv_remove_interface, | 100 | TRACE_EVENT(drv_remove_interface, |
100 | TP_PROTO(struct ieee80211_local *local, | 101 | TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), |
101 | const u8 *addr, struct ieee80211_vif *vif), | ||
102 | 102 | ||
103 | TP_ARGS(local, addr, vif), | 103 | TP_ARGS(local, sdata), |
104 | 104 | ||
105 | TP_STRUCT__entry( | 105 | TP_STRUCT__entry( |
106 | LOCAL_ENTRY | 106 | LOCAL_ENTRY |
@@ -111,7 +111,7 @@ TRACE_EVENT(drv_remove_interface, | |||
111 | TP_fast_assign( | 111 | TP_fast_assign( |
112 | LOCAL_ASSIGN; | 112 | LOCAL_ASSIGN; |
113 | VIF_ASSIGN; | 113 | VIF_ASSIGN; |
114 | memcpy(__entry->addr, addr, 6); | 114 | memcpy(__entry->addr, sdata->vif.addr, 6); |
115 | ), | 115 | ), |
116 | 116 | ||
117 | TP_printk( | 117 | TP_printk( |
@@ -140,6 +140,7 @@ TRACE_EVENT(drv_config, | |||
140 | __field(u8, short_frame_max_tx_count) | 140 | __field(u8, short_frame_max_tx_count) |
141 | __field(int, center_freq) | 141 | __field(int, center_freq) |
142 | __field(int, channel_type) | 142 | __field(int, channel_type) |
143 | __field(int, smps) | ||
143 | ), | 144 | ), |
144 | 145 | ||
145 | TP_fast_assign( | 146 | TP_fast_assign( |
@@ -155,6 +156,7 @@ TRACE_EVENT(drv_config, | |||
155 | __entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count; | 156 | __entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count; |
156 | __entry->center_freq = local->hw.conf.channel->center_freq; | 157 | __entry->center_freq = local->hw.conf.channel->center_freq; |
157 | __entry->channel_type = local->hw.conf.channel_type; | 158 | __entry->channel_type = local->hw.conf.channel_type; |
159 | __entry->smps = local->hw.conf.smps_mode; | ||
158 | ), | 160 | ), |
159 | 161 | ||
160 | TP_printk( | 162 | TP_printk( |
@@ -165,11 +167,11 @@ TRACE_EVENT(drv_config, | |||
165 | 167 | ||
166 | TRACE_EVENT(drv_bss_info_changed, | 168 | TRACE_EVENT(drv_bss_info_changed, |
167 | TP_PROTO(struct ieee80211_local *local, | 169 | TP_PROTO(struct ieee80211_local *local, |
168 | struct ieee80211_vif *vif, | 170 | struct ieee80211_sub_if_data *sdata, |
169 | struct ieee80211_bss_conf *info, | 171 | struct ieee80211_bss_conf *info, |
170 | u32 changed), | 172 | u32 changed), |
171 | 173 | ||
172 | TP_ARGS(local, vif, info, changed), | 174 | TP_ARGS(local, sdata, info, changed), |
173 | 175 | ||
174 | TP_STRUCT__entry( | 176 | TP_STRUCT__entry( |
175 | LOCAL_ENTRY | 177 | LOCAL_ENTRY |
@@ -293,11 +295,11 @@ TRACE_EVENT(drv_set_tim, | |||
293 | 295 | ||
294 | TRACE_EVENT(drv_set_key, | 296 | TRACE_EVENT(drv_set_key, |
295 | TP_PROTO(struct ieee80211_local *local, | 297 | TP_PROTO(struct ieee80211_local *local, |
296 | enum set_key_cmd cmd, struct ieee80211_vif *vif, | 298 | enum set_key_cmd cmd, struct ieee80211_sub_if_data *sdata, |
297 | struct ieee80211_sta *sta, | 299 | struct ieee80211_sta *sta, |
298 | struct ieee80211_key_conf *key, int ret), | 300 | struct ieee80211_key_conf *key, int ret), |
299 | 301 | ||
300 | TP_ARGS(local, cmd, vif, sta, key, ret), | 302 | TP_ARGS(local, cmd, sdata, sta, key, ret), |
301 | 303 | ||
302 | TP_STRUCT__entry( | 304 | TP_STRUCT__entry( |
303 | LOCAL_ENTRY | 305 | LOCAL_ENTRY |
@@ -329,26 +331,29 @@ TRACE_EVENT(drv_set_key, | |||
329 | 331 | ||
330 | TRACE_EVENT(drv_update_tkip_key, | 332 | TRACE_EVENT(drv_update_tkip_key, |
331 | TP_PROTO(struct ieee80211_local *local, | 333 | TP_PROTO(struct ieee80211_local *local, |
334 | struct ieee80211_sub_if_data *sdata, | ||
332 | struct ieee80211_key_conf *conf, | 335 | struct ieee80211_key_conf *conf, |
333 | const u8 *address, u32 iv32), | 336 | struct ieee80211_sta *sta, u32 iv32), |
334 | 337 | ||
335 | TP_ARGS(local, conf, address, iv32), | 338 | TP_ARGS(local, sdata, conf, sta, iv32), |
336 | 339 | ||
337 | TP_STRUCT__entry( | 340 | TP_STRUCT__entry( |
338 | LOCAL_ENTRY | 341 | LOCAL_ENTRY |
339 | __array(u8, addr, 6) | 342 | VIF_ENTRY |
343 | STA_ENTRY | ||
340 | __field(u32, iv32) | 344 | __field(u32, iv32) |
341 | ), | 345 | ), |
342 | 346 | ||
343 | TP_fast_assign( | 347 | TP_fast_assign( |
344 | LOCAL_ASSIGN; | 348 | LOCAL_ASSIGN; |
345 | memcpy(__entry->addr, address, 6); | 349 | VIF_ASSIGN; |
350 | STA_ASSIGN; | ||
346 | __entry->iv32 = iv32; | 351 | __entry->iv32 = iv32; |
347 | ), | 352 | ), |
348 | 353 | ||
349 | TP_printk( | 354 | TP_printk( |
350 | LOCAL_PR_FMT " addr:%pM iv32:%#x", | 355 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " iv32:%#x", |
351 | LOCAL_PR_ARG, __entry->addr, __entry->iv32 | 356 | LOCAL_PR_ARG,VIF_PR_ARG,STA_PR_ARG, __entry->iv32 |
352 | ) | 357 | ) |
353 | ); | 358 | ); |
354 | 359 | ||
@@ -489,13 +494,36 @@ TRACE_EVENT(drv_set_rts_threshold, | |||
489 | ) | 494 | ) |
490 | ); | 495 | ); |
491 | 496 | ||
497 | TRACE_EVENT(drv_set_coverage_class, | ||
498 | TP_PROTO(struct ieee80211_local *local, u8 value, int ret), | ||
499 | |||
500 | TP_ARGS(local, value, ret), | ||
501 | |||
502 | TP_STRUCT__entry( | ||
503 | LOCAL_ENTRY | ||
504 | __field(u8, value) | ||
505 | __field(int, ret) | ||
506 | ), | ||
507 | |||
508 | TP_fast_assign( | ||
509 | LOCAL_ASSIGN; | ||
510 | __entry->ret = ret; | ||
511 | __entry->value = value; | ||
512 | ), | ||
513 | |||
514 | TP_printk( | ||
515 | LOCAL_PR_FMT " value:%d ret:%d", | ||
516 | LOCAL_PR_ARG, __entry->value, __entry->ret | ||
517 | ) | ||
518 | ); | ||
519 | |||
492 | TRACE_EVENT(drv_sta_notify, | 520 | TRACE_EVENT(drv_sta_notify, |
493 | TP_PROTO(struct ieee80211_local *local, | 521 | TP_PROTO(struct ieee80211_local *local, |
494 | struct ieee80211_vif *vif, | 522 | struct ieee80211_sub_if_data *sdata, |
495 | enum sta_notify_cmd cmd, | 523 | enum sta_notify_cmd cmd, |
496 | struct ieee80211_sta *sta), | 524 | struct ieee80211_sta *sta), |
497 | 525 | ||
498 | TP_ARGS(local, vif, cmd, sta), | 526 | TP_ARGS(local, sdata, cmd, sta), |
499 | 527 | ||
500 | TP_STRUCT__entry( | 528 | TP_STRUCT__entry( |
501 | LOCAL_ENTRY | 529 | LOCAL_ENTRY |
@@ -517,59 +545,88 @@ TRACE_EVENT(drv_sta_notify, | |||
517 | ) | 545 | ) |
518 | ); | 546 | ); |
519 | 547 | ||
520 | TRACE_EVENT(drv_conf_tx, | 548 | TRACE_EVENT(drv_sta_add, |
521 | TP_PROTO(struct ieee80211_local *local, u16 queue, | 549 | TP_PROTO(struct ieee80211_local *local, |
522 | const struct ieee80211_tx_queue_params *params, | 550 | struct ieee80211_sub_if_data *sdata, |
523 | int ret), | 551 | struct ieee80211_sta *sta, int ret), |
524 | 552 | ||
525 | TP_ARGS(local, queue, params, ret), | 553 | TP_ARGS(local, sdata, sta, ret), |
526 | 554 | ||
527 | TP_STRUCT__entry( | 555 | TP_STRUCT__entry( |
528 | LOCAL_ENTRY | 556 | LOCAL_ENTRY |
529 | __field(u16, queue) | 557 | VIF_ENTRY |
530 | __field(u16, txop) | 558 | STA_ENTRY |
531 | __field(u16, cw_min) | ||
532 | __field(u16, cw_max) | ||
533 | __field(u8, aifs) | ||
534 | __field(int, ret) | 559 | __field(int, ret) |
535 | ), | 560 | ), |
536 | 561 | ||
537 | TP_fast_assign( | 562 | TP_fast_assign( |
538 | LOCAL_ASSIGN; | 563 | LOCAL_ASSIGN; |
539 | __entry->queue = queue; | 564 | VIF_ASSIGN; |
565 | STA_ASSIGN; | ||
540 | __entry->ret = ret; | 566 | __entry->ret = ret; |
541 | __entry->txop = params->txop; | ||
542 | __entry->cw_max = params->cw_max; | ||
543 | __entry->cw_min = params->cw_min; | ||
544 | __entry->aifs = params->aifs; | ||
545 | ), | 567 | ), |
546 | 568 | ||
547 | TP_printk( | 569 | TP_printk( |
548 | LOCAL_PR_FMT " queue:%d ret:%d", | 570 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d", |
549 | LOCAL_PR_ARG, __entry->queue, __entry->ret | 571 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret |
550 | ) | 572 | ) |
551 | ); | 573 | ); |
552 | 574 | ||
553 | TRACE_EVENT(drv_get_tx_stats, | 575 | TRACE_EVENT(drv_sta_remove, |
554 | TP_PROTO(struct ieee80211_local *local, | 576 | TP_PROTO(struct ieee80211_local *local, |
555 | struct ieee80211_tx_queue_stats *stats, | 577 | struct ieee80211_sub_if_data *sdata, |
578 | struct ieee80211_sta *sta), | ||
579 | |||
580 | TP_ARGS(local, sdata, sta), | ||
581 | |||
582 | TP_STRUCT__entry( | ||
583 | LOCAL_ENTRY | ||
584 | VIF_ENTRY | ||
585 | STA_ENTRY | ||
586 | ), | ||
587 | |||
588 | TP_fast_assign( | ||
589 | LOCAL_ASSIGN; | ||
590 | VIF_ASSIGN; | ||
591 | STA_ASSIGN; | ||
592 | ), | ||
593 | |||
594 | TP_printk( | ||
595 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT, | ||
596 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG | ||
597 | ) | ||
598 | ); | ||
599 | |||
600 | TRACE_EVENT(drv_conf_tx, | ||
601 | TP_PROTO(struct ieee80211_local *local, u16 queue, | ||
602 | const struct ieee80211_tx_queue_params *params, | ||
556 | int ret), | 603 | int ret), |
557 | 604 | ||
558 | TP_ARGS(local, stats, ret), | 605 | TP_ARGS(local, queue, params, ret), |
559 | 606 | ||
560 | TP_STRUCT__entry( | 607 | TP_STRUCT__entry( |
561 | LOCAL_ENTRY | 608 | LOCAL_ENTRY |
609 | __field(u16, queue) | ||
610 | __field(u16, txop) | ||
611 | __field(u16, cw_min) | ||
612 | __field(u16, cw_max) | ||
613 | __field(u8, aifs) | ||
562 | __field(int, ret) | 614 | __field(int, ret) |
563 | ), | 615 | ), |
564 | 616 | ||
565 | TP_fast_assign( | 617 | TP_fast_assign( |
566 | LOCAL_ASSIGN; | 618 | LOCAL_ASSIGN; |
619 | __entry->queue = queue; | ||
567 | __entry->ret = ret; | 620 | __entry->ret = ret; |
621 | __entry->txop = params->txop; | ||
622 | __entry->cw_max = params->cw_max; | ||
623 | __entry->cw_min = params->cw_min; | ||
624 | __entry->aifs = params->aifs; | ||
568 | ), | 625 | ), |
569 | 626 | ||
570 | TP_printk( | 627 | TP_printk( |
571 | LOCAL_PR_FMT " ret:%d", | 628 | LOCAL_PR_FMT " queue:%d ret:%d", |
572 | LOCAL_PR_ARG, __entry->ret | 629 | LOCAL_PR_ARG, __entry->queue, __entry->ret |
573 | ) | 630 | ) |
574 | ); | 631 | ); |
575 | 632 | ||
@@ -656,12 +713,12 @@ TRACE_EVENT(drv_tx_last_beacon, | |||
656 | 713 | ||
657 | TRACE_EVENT(drv_ampdu_action, | 714 | TRACE_EVENT(drv_ampdu_action, |
658 | TP_PROTO(struct ieee80211_local *local, | 715 | TP_PROTO(struct ieee80211_local *local, |
659 | struct ieee80211_vif *vif, | 716 | struct ieee80211_sub_if_data *sdata, |
660 | enum ieee80211_ampdu_mlme_action action, | 717 | enum ieee80211_ampdu_mlme_action action, |
661 | struct ieee80211_sta *sta, u16 tid, | 718 | struct ieee80211_sta *sta, u16 tid, |
662 | u16 *ssn, int ret), | 719 | u16 *ssn, int ret), |
663 | 720 | ||
664 | TP_ARGS(local, vif, action, sta, tid, ssn, ret), | 721 | TP_ARGS(local, sdata, action, sta, tid, ssn, ret), |
665 | 722 | ||
666 | TP_STRUCT__entry( | 723 | TP_STRUCT__entry( |
667 | LOCAL_ENTRY | 724 | LOCAL_ENTRY |
@@ -688,6 +745,27 @@ TRACE_EVENT(drv_ampdu_action, | |||
688 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret | 745 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret |
689 | ) | 746 | ) |
690 | ); | 747 | ); |
748 | |||
749 | TRACE_EVENT(drv_flush, | ||
750 | TP_PROTO(struct ieee80211_local *local, bool drop), | ||
751 | |||
752 | TP_ARGS(local, drop), | ||
753 | |||
754 | TP_STRUCT__entry( | ||
755 | LOCAL_ENTRY | ||
756 | __field(bool, drop) | ||
757 | ), | ||
758 | |||
759 | TP_fast_assign( | ||
760 | LOCAL_ASSIGN; | ||
761 | __entry->drop = drop; | ||
762 | ), | ||
763 | |||
764 | TP_printk( | ||
765 | LOCAL_PR_FMT " drop:%d", | ||
766 | LOCAL_PR_ARG, __entry->drop | ||
767 | ) | ||
768 | ); | ||
691 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ | 769 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ |
692 | 770 | ||
693 | #undef TRACE_INCLUDE_PATH | 771 | #undef TRACE_INCLUDE_PATH |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index d7dcee680728..bb677a73b7c9 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -125,7 +125,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
125 | 125 | ||
126 | if (!skb) { | 126 | if (!skb) { |
127 | printk(KERN_ERR "%s: failed to allocate buffer " | 127 | printk(KERN_ERR "%s: failed to allocate buffer " |
128 | "for delba frame\n", sdata->dev->name); | 128 | "for delba frame\n", sdata->name); |
129 | return; | 129 | return; |
130 | } | 130 | } |
131 | 131 | ||
@@ -133,10 +133,10 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
133 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 133 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
134 | memset(mgmt, 0, 24); | 134 | memset(mgmt, 0, 24); |
135 | memcpy(mgmt->da, da, ETH_ALEN); | 135 | memcpy(mgmt->da, da, ETH_ALEN); |
136 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 136 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
137 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 137 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
138 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 138 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
139 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 139 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
140 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 140 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
141 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 141 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
142 | 142 | ||
@@ -185,3 +185,50 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
185 | spin_unlock_bh(&sta->lock); | 185 | spin_unlock_bh(&sta->lock); |
186 | } | 186 | } |
187 | } | 187 | } |
188 | |||
189 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | ||
190 | enum ieee80211_smps_mode smps, const u8 *da, | ||
191 | const u8 *bssid) | ||
192 | { | ||
193 | struct ieee80211_local *local = sdata->local; | ||
194 | struct sk_buff *skb; | ||
195 | struct ieee80211_mgmt *action_frame; | ||
196 | |||
197 | /* 27 = header + category + action + smps mode */ | ||
198 | skb = dev_alloc_skb(27 + local->hw.extra_tx_headroom); | ||
199 | if (!skb) | ||
200 | return -ENOMEM; | ||
201 | |||
202 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
203 | action_frame = (void *)skb_put(skb, 27); | ||
204 | memcpy(action_frame->da, da, ETH_ALEN); | ||
205 | memcpy(action_frame->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
206 | memcpy(action_frame->bssid, bssid, ETH_ALEN); | ||
207 | action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
208 | IEEE80211_STYPE_ACTION); | ||
209 | action_frame->u.action.category = WLAN_CATEGORY_HT; | ||
210 | action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; | ||
211 | switch (smps) { | ||
212 | case IEEE80211_SMPS_AUTOMATIC: | ||
213 | case IEEE80211_SMPS_NUM_MODES: | ||
214 | WARN_ON(1); | ||
215 | case IEEE80211_SMPS_OFF: | ||
216 | action_frame->u.action.u.ht_smps.smps_control = | ||
217 | WLAN_HT_SMPS_CONTROL_DISABLED; | ||
218 | break; | ||
219 | case IEEE80211_SMPS_STATIC: | ||
220 | action_frame->u.action.u.ht_smps.smps_control = | ||
221 | WLAN_HT_SMPS_CONTROL_STATIC; | ||
222 | break; | ||
223 | case IEEE80211_SMPS_DYNAMIC: | ||
224 | action_frame->u.action.u.ht_smps.smps_control = | ||
225 | WLAN_HT_SMPS_CONTROL_DYNAMIC; | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | /* we'll do more on status of this frame */ | ||
230 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
231 | ieee80211_tx_skb(sdata, skb); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 1f2db647bb5c..f3e942486749 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -117,7 +117,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
117 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 117 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
118 | IEEE80211_STYPE_PROBE_RESP); | 118 | IEEE80211_STYPE_PROBE_RESP); |
119 | memset(mgmt->da, 0xff, ETH_ALEN); | 119 | memset(mgmt->da, 0xff, ETH_ALEN); |
120 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 120 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
121 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); | 121 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); |
122 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); | 122 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); |
123 | mgmt->u.beacon.timestamp = cpu_to_le64(tsf); | 123 | mgmt->u.beacon.timestamp = cpu_to_le64(tsf); |
@@ -187,15 +187,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
187 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 187 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
188 | struct ieee80211_bss *bss) | 188 | struct ieee80211_bss *bss) |
189 | { | 189 | { |
190 | struct cfg80211_bss *cbss = | ||
191 | container_of((void *)bss, struct cfg80211_bss, priv); | ||
190 | struct ieee80211_supported_band *sband; | 192 | struct ieee80211_supported_band *sband; |
191 | u32 basic_rates; | 193 | u32 basic_rates; |
192 | int i, j; | 194 | int i, j; |
193 | u16 beacon_int = bss->cbss.beacon_interval; | 195 | u16 beacon_int = cbss->beacon_interval; |
194 | 196 | ||
195 | if (beacon_int < 10) | 197 | if (beacon_int < 10) |
196 | beacon_int = 10; | 198 | beacon_int = 10; |
197 | 199 | ||
198 | sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band]; | 200 | sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; |
199 | 201 | ||
200 | basic_rates = 0; | 202 | basic_rates = 0; |
201 | 203 | ||
@@ -212,12 +214,12 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
212 | } | 214 | } |
213 | } | 215 | } |
214 | 216 | ||
215 | __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, | 217 | __ieee80211_sta_join_ibss(sdata, cbss->bssid, |
216 | beacon_int, | 218 | beacon_int, |
217 | bss->cbss.channel, | 219 | cbss->channel, |
218 | basic_rates, | 220 | basic_rates, |
219 | bss->cbss.capability, | 221 | cbss->capability, |
220 | bss->cbss.tsf); | 222 | cbss->tsf); |
221 | } | 223 | } |
222 | 224 | ||
223 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 225 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
@@ -229,6 +231,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
229 | { | 231 | { |
230 | struct ieee80211_local *local = sdata->local; | 232 | struct ieee80211_local *local = sdata->local; |
231 | int freq; | 233 | int freq; |
234 | struct cfg80211_bss *cbss; | ||
232 | struct ieee80211_bss *bss; | 235 | struct ieee80211_bss *bss; |
233 | struct sta_info *sta; | 236 | struct sta_info *sta; |
234 | struct ieee80211_channel *channel; | 237 | struct ieee80211_channel *channel; |
@@ -252,7 +255,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
252 | 255 | ||
253 | rcu_read_lock(); | 256 | rcu_read_lock(); |
254 | 257 | ||
255 | sta = sta_info_get(local, mgmt->sa); | 258 | sta = sta_info_get(sdata, mgmt->sa); |
256 | if (sta) { | 259 | if (sta) { |
257 | u32 prev_rates; | 260 | u32 prev_rates; |
258 | 261 | ||
@@ -266,16 +269,18 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
266 | printk(KERN_DEBUG "%s: updated supp_rates set " | 269 | printk(KERN_DEBUG "%s: updated supp_rates set " |
267 | "for %pM based on beacon info (0x%llx | " | 270 | "for %pM based on beacon info (0x%llx | " |
268 | "0x%llx -> 0x%llx)\n", | 271 | "0x%llx -> 0x%llx)\n", |
269 | sdata->dev->name, | 272 | sdata->name, |
270 | sta->sta.addr, | 273 | sta->sta.addr, |
271 | (unsigned long long) prev_rates, | 274 | (unsigned long long) prev_rates, |
272 | (unsigned long long) supp_rates, | 275 | (unsigned long long) supp_rates, |
273 | (unsigned long long) sta->sta.supp_rates[band]); | 276 | (unsigned long long) sta->sta.supp_rates[band]); |
274 | #endif | 277 | #endif |
275 | } else | 278 | rcu_read_unlock(); |
276 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); | 279 | } else { |
277 | 280 | rcu_read_unlock(); | |
278 | rcu_read_unlock(); | 281 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
282 | supp_rates, GFP_KERNEL); | ||
283 | } | ||
279 | } | 284 | } |
280 | 285 | ||
281 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 286 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
@@ -283,25 +288,23 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
283 | if (!bss) | 288 | if (!bss) |
284 | return; | 289 | return; |
285 | 290 | ||
291 | cbss = container_of((void *)bss, struct cfg80211_bss, priv); | ||
292 | |||
286 | /* was just updated in ieee80211_bss_info_update */ | 293 | /* was just updated in ieee80211_bss_info_update */ |
287 | beacon_timestamp = bss->cbss.tsf; | 294 | beacon_timestamp = cbss->tsf; |
288 | 295 | ||
289 | /* check if we need to merge IBSS */ | 296 | /* check if we need to merge IBSS */ |
290 | 297 | ||
291 | /* merge only on beacons (???) */ | ||
292 | if (!beacon) | ||
293 | goto put_bss; | ||
294 | |||
295 | /* we use a fixed BSSID */ | 298 | /* we use a fixed BSSID */ |
296 | if (sdata->u.ibss.bssid) | 299 | if (sdata->u.ibss.fixed_bssid) |
297 | goto put_bss; | 300 | goto put_bss; |
298 | 301 | ||
299 | /* not an IBSS */ | 302 | /* not an IBSS */ |
300 | if (!(bss->cbss.capability & WLAN_CAPABILITY_IBSS)) | 303 | if (!(cbss->capability & WLAN_CAPABILITY_IBSS)) |
301 | goto put_bss; | 304 | goto put_bss; |
302 | 305 | ||
303 | /* different channel */ | 306 | /* different channel */ |
304 | if (bss->cbss.channel != local->oper_channel) | 307 | if (cbss->channel != local->oper_channel) |
305 | goto put_bss; | 308 | goto put_bss; |
306 | 309 | ||
307 | /* different SSID */ | 310 | /* different SSID */ |
@@ -311,7 +314,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
311 | goto put_bss; | 314 | goto put_bss; |
312 | 315 | ||
313 | /* same BSSID */ | 316 | /* same BSSID */ |
314 | if (memcmp(bss->cbss.bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) | 317 | if (memcmp(cbss->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) |
315 | goto put_bss; | 318 | goto put_bss; |
316 | 319 | ||
317 | if (rx_status->flag & RX_FLAG_TSFT) { | 320 | if (rx_status->flag & RX_FLAG_TSFT) { |
@@ -364,10 +367,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
364 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 367 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
365 | printk(KERN_DEBUG "%s: beacon TSF higher than " | 368 | printk(KERN_DEBUG "%s: beacon TSF higher than " |
366 | "local TSF - IBSS merge with BSSID %pM\n", | 369 | "local TSF - IBSS merge with BSSID %pM\n", |
367 | sdata->dev->name, mgmt->bssid); | 370 | sdata->name, mgmt->bssid); |
368 | #endif | 371 | #endif |
369 | ieee80211_sta_join_ibss(sdata, bss); | 372 | ieee80211_sta_join_ibss(sdata, bss); |
370 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); | 373 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
374 | supp_rates, GFP_KERNEL); | ||
371 | } | 375 | } |
372 | 376 | ||
373 | put_bss: | 377 | put_bss: |
@@ -380,7 +384,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
380 | * must be callable in atomic context. | 384 | * must be callable in atomic context. |
381 | */ | 385 | */ |
382 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 386 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
383 | u8 *bssid,u8 *addr, u32 supp_rates) | 387 | u8 *bssid,u8 *addr, u32 supp_rates, |
388 | gfp_t gfp) | ||
384 | { | 389 | { |
385 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 390 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
386 | struct ieee80211_local *local = sdata->local; | 391 | struct ieee80211_local *local = sdata->local; |
@@ -394,7 +399,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
394 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { | 399 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { |
395 | if (net_ratelimit()) | 400 | if (net_ratelimit()) |
396 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", | 401 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", |
397 | sdata->dev->name, addr); | 402 | sdata->name, addr); |
398 | return NULL; | 403 | return NULL; |
399 | } | 404 | } |
400 | 405 | ||
@@ -406,10 +411,10 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
406 | 411 | ||
407 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 412 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
408 | printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n", | 413 | printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n", |
409 | wiphy_name(local->hw.wiphy), addr, sdata->dev->name); | 414 | wiphy_name(local->hw.wiphy), addr, sdata->name); |
410 | #endif | 415 | #endif |
411 | 416 | ||
412 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | 417 | sta = sta_info_alloc(sdata, addr, gfp); |
413 | if (!sta) | 418 | if (!sta) |
414 | return NULL; | 419 | return NULL; |
415 | 420 | ||
@@ -421,9 +426,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
421 | 426 | ||
422 | rate_control_rate_init(sta); | 427 | rate_control_rate_init(sta); |
423 | 428 | ||
429 | /* If it fails, maybe we raced another insertion? */ | ||
424 | if (sta_info_insert(sta)) | 430 | if (sta_info_insert(sta)) |
425 | return NULL; | 431 | return sta_info_get(sdata, addr); |
426 | |||
427 | return sta; | 432 | return sta; |
428 | } | 433 | } |
429 | 434 | ||
@@ -449,6 +454,9 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) | |||
449 | return active; | 454 | return active; |
450 | } | 455 | } |
451 | 456 | ||
457 | /* | ||
458 | * This function is called with state == IEEE80211_IBSS_MLME_JOINED | ||
459 | */ | ||
452 | 460 | ||
453 | static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | 461 | static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) |
454 | { | 462 | { |
@@ -470,7 +478,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
470 | return; | 478 | return; |
471 | 479 | ||
472 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 480 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " |
473 | "IBSS networks with same SSID (merge)\n", sdata->dev->name); | 481 | "IBSS networks with same SSID (merge)\n", sdata->name); |
474 | 482 | ||
475 | ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); | 483 | ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); |
476 | } | 484 | } |
@@ -492,13 +500,13 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
492 | * random number generator get different BSSID. */ | 500 | * random number generator get different BSSID. */ |
493 | get_random_bytes(bssid, ETH_ALEN); | 501 | get_random_bytes(bssid, ETH_ALEN); |
494 | for (i = 0; i < ETH_ALEN; i++) | 502 | for (i = 0; i < ETH_ALEN; i++) |
495 | bssid[i] ^= sdata->dev->dev_addr[i]; | 503 | bssid[i] ^= sdata->vif.addr[i]; |
496 | bssid[0] &= ~0x01; | 504 | bssid[0] &= ~0x01; |
497 | bssid[0] |= 0x02; | 505 | bssid[0] |= 0x02; |
498 | } | 506 | } |
499 | 507 | ||
500 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", | 508 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", |
501 | sdata->dev->name, bssid); | 509 | sdata->name, bssid); |
502 | 510 | ||
503 | sband = local->hw.wiphy->bands[ifibss->channel->band]; | 511 | sband = local->hw.wiphy->bands[ifibss->channel->band]; |
504 | 512 | ||
@@ -514,11 +522,15 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
514 | capability, 0); | 522 | capability, 0); |
515 | } | 523 | } |
516 | 524 | ||
525 | /* | ||
526 | * This function is called with state == IEEE80211_IBSS_MLME_SEARCH | ||
527 | */ | ||
528 | |||
517 | static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | 529 | static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) |
518 | { | 530 | { |
519 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 531 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
520 | struct ieee80211_local *local = sdata->local; | 532 | struct ieee80211_local *local = sdata->local; |
521 | struct ieee80211_bss *bss; | 533 | struct cfg80211_bss *cbss; |
522 | struct ieee80211_channel *chan = NULL; | 534 | struct ieee80211_channel *chan = NULL; |
523 | const u8 *bssid = NULL; | 535 | const u8 *bssid = NULL; |
524 | int active_ibss; | 536 | int active_ibss; |
@@ -527,7 +539,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
527 | active_ibss = ieee80211_sta_active_ibss(sdata); | 539 | active_ibss = ieee80211_sta_active_ibss(sdata); |
528 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 540 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
529 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", | 541 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", |
530 | sdata->dev->name, active_ibss); | 542 | sdata->name, active_ibss); |
531 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 543 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
532 | 544 | ||
533 | if (active_ibss) | 545 | if (active_ibss) |
@@ -542,21 +554,23 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
542 | chan = ifibss->channel; | 554 | chan = ifibss->channel; |
543 | if (!is_zero_ether_addr(ifibss->bssid)) | 555 | if (!is_zero_ether_addr(ifibss->bssid)) |
544 | bssid = ifibss->bssid; | 556 | bssid = ifibss->bssid; |
545 | bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid, | 557 | cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid, |
546 | ifibss->ssid, ifibss->ssid_len, | 558 | ifibss->ssid, ifibss->ssid_len, |
547 | WLAN_CAPABILITY_IBSS | | 559 | WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY, |
548 | WLAN_CAPABILITY_PRIVACY, | 560 | capability); |
549 | capability); | 561 | |
562 | if (cbss) { | ||
563 | struct ieee80211_bss *bss; | ||
550 | 564 | ||
551 | if (bss) { | 565 | bss = (void *)cbss->priv; |
552 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 566 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
553 | printk(KERN_DEBUG " sta_find_ibss: selected %pM current " | 567 | printk(KERN_DEBUG " sta_find_ibss: selected %pM current " |
554 | "%pM\n", bss->cbss.bssid, ifibss->bssid); | 568 | "%pM\n", cbss->bssid, ifibss->bssid); |
555 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 569 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
556 | 570 | ||
557 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" | 571 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" |
558 | " based on configured SSID\n", | 572 | " based on configured SSID\n", |
559 | sdata->dev->name, bss->cbss.bssid); | 573 | sdata->name, cbss->bssid); |
560 | 574 | ||
561 | ieee80211_sta_join_ibss(sdata, bss); | 575 | ieee80211_sta_join_ibss(sdata, bss); |
562 | ieee80211_rx_bss_put(local, bss); | 576 | ieee80211_rx_bss_put(local, bss); |
@@ -568,18 +582,14 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
568 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 582 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
569 | 583 | ||
570 | /* Selected IBSS not found in current scan results - try to scan */ | 584 | /* Selected IBSS not found in current scan results - try to scan */ |
571 | if (ifibss->state == IEEE80211_IBSS_MLME_JOINED && | 585 | if (time_after(jiffies, ifibss->last_scan_completed + |
572 | !ieee80211_sta_active_ibss(sdata)) { | ||
573 | mod_timer(&ifibss->timer, | ||
574 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); | ||
575 | } else if (time_after(jiffies, ifibss->last_scan_completed + | ||
576 | IEEE80211_SCAN_INTERVAL)) { | 586 | IEEE80211_SCAN_INTERVAL)) { |
577 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 587 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " |
578 | "join\n", sdata->dev->name); | 588 | "join\n", sdata->name); |
579 | 589 | ||
580 | ieee80211_request_internal_scan(sdata, ifibss->ssid, | 590 | ieee80211_request_internal_scan(sdata, ifibss->ssid, |
581 | ifibss->ssid_len); | 591 | ifibss->ssid_len); |
582 | } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { | 592 | } else { |
583 | int interval = IEEE80211_SCAN_INTERVAL; | 593 | int interval = IEEE80211_SCAN_INTERVAL; |
584 | 594 | ||
585 | if (time_after(jiffies, ifibss->ibss_join_req + | 595 | if (time_after(jiffies, ifibss->ibss_join_req + |
@@ -589,7 +599,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
589 | return; | 599 | return; |
590 | } | 600 | } |
591 | printk(KERN_DEBUG "%s: IBSS not allowed on" | 601 | printk(KERN_DEBUG "%s: IBSS not allowed on" |
592 | " %d MHz\n", sdata->dev->name, | 602 | " %d MHz\n", sdata->name, |
593 | local->hw.conf.channel->center_freq); | 603 | local->hw.conf.channel->center_freq); |
594 | 604 | ||
595 | /* No IBSS found - decrease scan interval and continue | 605 | /* No IBSS found - decrease scan interval and continue |
@@ -597,7 +607,6 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
597 | interval = IEEE80211_SCAN_INTERVAL_SLOW; | 607 | interval = IEEE80211_SCAN_INTERVAL_SLOW; |
598 | } | 608 | } |
599 | 609 | ||
600 | ifibss->state = IEEE80211_IBSS_MLME_SEARCH; | ||
601 | mod_timer(&ifibss->timer, | 610 | mod_timer(&ifibss->timer, |
602 | round_jiffies(jiffies + interval)); | 611 | round_jiffies(jiffies + interval)); |
603 | } | 612 | } |
@@ -623,7 +632,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
623 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 632 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
624 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" | 633 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" |
625 | " (tx_last_beacon=%d)\n", | 634 | " (tx_last_beacon=%d)\n", |
626 | sdata->dev->name, mgmt->sa, mgmt->da, | 635 | sdata->name, mgmt->sa, mgmt->da, |
627 | mgmt->bssid, tx_last_beacon); | 636 | mgmt->bssid, tx_last_beacon); |
628 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 637 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
629 | 638 | ||
@@ -641,13 +650,13 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
641 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 650 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
642 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " | 651 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " |
643 | "from %pM\n", | 652 | "from %pM\n", |
644 | sdata->dev->name, mgmt->sa); | 653 | sdata->name, mgmt->sa); |
645 | #endif | 654 | #endif |
646 | return; | 655 | return; |
647 | } | 656 | } |
648 | if (pos[1] != 0 && | 657 | if (pos[1] != 0 && |
649 | (pos[1] != ifibss->ssid_len || | 658 | (pos[1] != ifibss->ssid_len || |
650 | !memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) { | 659 | memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) { |
651 | /* Ignore ProbeReq for foreign SSID */ | 660 | /* Ignore ProbeReq for foreign SSID */ |
652 | return; | 661 | return; |
653 | } | 662 | } |
@@ -661,7 +670,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
661 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 670 | memcpy(resp->da, mgmt->sa, ETH_ALEN); |
662 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 671 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
663 | printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", | 672 | printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", |
664 | sdata->dev->name, resp->da); | 673 | sdata->name, resp->da); |
665 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 674 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
666 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 675 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
667 | ieee80211_tx_skb(sdata, skb); | 676 | ieee80211_tx_skb(sdata, skb); |
@@ -675,7 +684,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
675 | size_t baselen; | 684 | size_t baselen; |
676 | struct ieee802_11_elems elems; | 685 | struct ieee802_11_elems elems; |
677 | 686 | ||
678 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | 687 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) |
679 | return; /* ignore ProbeResp to foreign address */ | 688 | return; /* ignore ProbeResp to foreign address */ |
680 | 689 | ||
681 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 690 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
@@ -748,7 +757,7 @@ static void ieee80211_ibss_work(struct work_struct *work) | |||
748 | if (WARN_ON(local->suspended)) | 757 | if (WARN_ON(local->suspended)) |
749 | return; | 758 | return; |
750 | 759 | ||
751 | if (!netif_running(sdata->dev)) | 760 | if (!ieee80211_sdata_running(sdata)) |
752 | return; | 761 | return; |
753 | 762 | ||
754 | if (local->scanning) | 763 | if (local->scanning) |
@@ -831,7 +840,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) | |||
831 | 840 | ||
832 | mutex_lock(&local->iflist_mtx); | 841 | mutex_lock(&local->iflist_mtx); |
833 | list_for_each_entry(sdata, &local->interfaces, list) { | 842 | list_for_each_entry(sdata, &local->interfaces, list) { |
834 | if (!netif_running(sdata->dev)) | 843 | if (!ieee80211_sdata_running(sdata)) |
835 | continue; | 844 | continue; |
836 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 845 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
837 | continue; | 846 | continue; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 91dc8636d644..241533e1bc03 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005, Devicescape Software, Inc. | 3 | * Copyright 2005, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -58,6 +58,15 @@ struct ieee80211_local; | |||
58 | 58 | ||
59 | #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) | 59 | #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) |
60 | 60 | ||
61 | #define IEEE80211_DEFAULT_UAPSD_QUEUES \ | ||
62 | (IEEE80211_WMM_IE_STA_QOSINFO_AC_BK | \ | ||
63 | IEEE80211_WMM_IE_STA_QOSINFO_AC_BE | \ | ||
64 | IEEE80211_WMM_IE_STA_QOSINFO_AC_VI | \ | ||
65 | IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) | ||
66 | |||
67 | #define IEEE80211_DEFAULT_MAX_SP_LEN \ | ||
68 | IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL | ||
69 | |||
61 | struct ieee80211_fragment_entry { | 70 | struct ieee80211_fragment_entry { |
62 | unsigned long first_frag_time; | 71 | unsigned long first_frag_time; |
63 | unsigned int seq; | 72 | unsigned int seq; |
@@ -71,9 +80,6 @@ struct ieee80211_fragment_entry { | |||
71 | 80 | ||
72 | 81 | ||
73 | struct ieee80211_bss { | 82 | struct ieee80211_bss { |
74 | /* Yes, this is a hack */ | ||
75 | struct cfg80211_bss cbss; | ||
76 | |||
77 | /* don't want to look up all the time */ | 83 | /* don't want to look up all the time */ |
78 | size_t ssid_len; | 84 | size_t ssid_len; |
79 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 85 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
@@ -81,6 +87,7 @@ struct ieee80211_bss { | |||
81 | u8 dtim_period; | 87 | u8 dtim_period; |
82 | 88 | ||
83 | bool wmm_used; | 89 | bool wmm_used; |
90 | bool uapsd_supported; | ||
84 | 91 | ||
85 | unsigned long last_probe_resp; | 92 | unsigned long last_probe_resp; |
86 | 93 | ||
@@ -140,7 +147,6 @@ typedef unsigned __bitwise__ ieee80211_tx_result; | |||
140 | 147 | ||
141 | struct ieee80211_tx_data { | 148 | struct ieee80211_tx_data { |
142 | struct sk_buff *skb; | 149 | struct sk_buff *skb; |
143 | struct net_device *dev; | ||
144 | struct ieee80211_local *local; | 150 | struct ieee80211_local *local; |
145 | struct ieee80211_sub_if_data *sdata; | 151 | struct ieee80211_sub_if_data *sdata; |
146 | struct sta_info *sta; | 152 | struct sta_info *sta; |
@@ -228,31 +234,77 @@ struct mesh_preq_queue { | |||
228 | u8 flags; | 234 | u8 flags; |
229 | }; | 235 | }; |
230 | 236 | ||
231 | enum ieee80211_mgd_state { | 237 | enum ieee80211_work_type { |
232 | IEEE80211_MGD_STATE_IDLE, | 238 | IEEE80211_WORK_ABORT, |
233 | IEEE80211_MGD_STATE_PROBE, | 239 | IEEE80211_WORK_DIRECT_PROBE, |
234 | IEEE80211_MGD_STATE_AUTH, | 240 | IEEE80211_WORK_AUTH, |
235 | IEEE80211_MGD_STATE_ASSOC, | 241 | IEEE80211_WORK_ASSOC, |
242 | IEEE80211_WORK_REMAIN_ON_CHANNEL, | ||
236 | }; | 243 | }; |
237 | 244 | ||
238 | struct ieee80211_mgd_work { | 245 | /** |
246 | * enum work_done_result - indicates what to do after work was done | ||
247 | * | ||
248 | * @WORK_DONE_DESTROY: This work item is no longer needed, destroy. | ||
249 | * @WORK_DONE_REQUEUE: This work item was reset to be reused, and | ||
250 | * should be requeued. | ||
251 | */ | ||
252 | enum work_done_result { | ||
253 | WORK_DONE_DESTROY, | ||
254 | WORK_DONE_REQUEUE, | ||
255 | }; | ||
256 | |||
257 | struct ieee80211_work { | ||
239 | struct list_head list; | 258 | struct list_head list; |
240 | struct ieee80211_bss *bss; | 259 | |
241 | int ie_len; | 260 | struct rcu_head rcu_head; |
242 | u8 prev_bssid[ETH_ALEN]; | 261 | |
243 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 262 | struct ieee80211_sub_if_data *sdata; |
244 | u8 ssid_len; | 263 | |
264 | enum work_done_result (*done)(struct ieee80211_work *wk, | ||
265 | struct sk_buff *skb); | ||
266 | |||
267 | struct ieee80211_channel *chan; | ||
268 | enum nl80211_channel_type chan_type; | ||
269 | |||
245 | unsigned long timeout; | 270 | unsigned long timeout; |
246 | enum ieee80211_mgd_state state; | 271 | enum ieee80211_work_type type; |
247 | u16 auth_alg, auth_transaction; | 272 | |
273 | u8 filter_ta[ETH_ALEN]; | ||
248 | 274 | ||
249 | int tries; | 275 | bool started; |
250 | 276 | ||
251 | u8 key[WLAN_KEY_LEN_WEP104]; | 277 | union { |
252 | u8 key_len, key_idx; | 278 | struct { |
279 | int tries; | ||
280 | u16 algorithm, transaction; | ||
281 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
282 | u8 ssid_len; | ||
283 | u8 key[WLAN_KEY_LEN_WEP104]; | ||
284 | u8 key_len, key_idx; | ||
285 | bool privacy; | ||
286 | } probe_auth; | ||
287 | struct { | ||
288 | struct cfg80211_bss *bss; | ||
289 | const u8 *supp_rates; | ||
290 | const u8 *ht_information_ie; | ||
291 | enum ieee80211_smps_mode smps; | ||
292 | int tries; | ||
293 | u16 capability; | ||
294 | u8 prev_bssid[ETH_ALEN]; | ||
295 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
296 | u8 ssid_len; | ||
297 | u8 supp_rates_len; | ||
298 | bool wmm_used, use_11n, uapsd_used; | ||
299 | } assoc; | ||
300 | struct { | ||
301 | u32 duration; | ||
302 | } remain; | ||
303 | }; | ||
253 | 304 | ||
305 | int ie_len; | ||
254 | /* must be last */ | 306 | /* must be last */ |
255 | u8 ie[0]; /* for auth or assoc frame, not probe */ | 307 | u8 ie[0]; |
256 | }; | 308 | }; |
257 | 309 | ||
258 | /* flags used in struct ieee80211_if_managed.flags */ | 310 | /* flags used in struct ieee80211_if_managed.flags */ |
@@ -260,15 +312,11 @@ enum ieee80211_sta_flags { | |||
260 | IEEE80211_STA_BEACON_POLL = BIT(0), | 312 | IEEE80211_STA_BEACON_POLL = BIT(0), |
261 | IEEE80211_STA_CONNECTION_POLL = BIT(1), | 313 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
262 | IEEE80211_STA_CONTROL_PORT = BIT(2), | 314 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
263 | IEEE80211_STA_WMM_ENABLED = BIT(3), | ||
264 | IEEE80211_STA_DISABLE_11N = BIT(4), | 315 | IEEE80211_STA_DISABLE_11N = BIT(4), |
265 | IEEE80211_STA_CSA_RECEIVED = BIT(5), | 316 | IEEE80211_STA_CSA_RECEIVED = BIT(5), |
266 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 317 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
267 | }; | 318 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
268 | 319 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | |
269 | /* flags for MLME request */ | ||
270 | enum ieee80211_sta_request { | ||
271 | IEEE80211_STA_REQ_SCAN, | ||
272 | }; | 320 | }; |
273 | 321 | ||
274 | struct ieee80211_if_managed { | 322 | struct ieee80211_if_managed { |
@@ -285,21 +333,18 @@ struct ieee80211_if_managed { | |||
285 | int probe_send_count; | 333 | int probe_send_count; |
286 | 334 | ||
287 | struct mutex mtx; | 335 | struct mutex mtx; |
288 | struct ieee80211_bss *associated; | 336 | struct cfg80211_bss *associated; |
289 | struct ieee80211_mgd_work *old_associate_work; | ||
290 | struct list_head work_list; | ||
291 | 337 | ||
292 | u8 bssid[ETH_ALEN]; | 338 | u8 bssid[ETH_ALEN]; |
293 | 339 | ||
294 | u16 aid; | 340 | u16 aid; |
295 | u16 capab; | ||
296 | 341 | ||
297 | struct sk_buff_head skb_queue; | 342 | struct sk_buff_head skb_queue; |
298 | 343 | ||
299 | unsigned long timers_running; /* used for quiesce/restart */ | 344 | unsigned long timers_running; /* used for quiesce/restart */ |
300 | bool powersave; /* powersave requested for this iface */ | 345 | bool powersave; /* powersave requested for this iface */ |
301 | 346 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | |
302 | unsigned long request; | 347 | ap_smps; /* smps mode AP thinks we're in */ |
303 | 348 | ||
304 | unsigned int flags; | 349 | unsigned int flags; |
305 | 350 | ||
@@ -433,6 +478,8 @@ struct ieee80211_sub_if_data { | |||
433 | 478 | ||
434 | int drop_unencrypted; | 479 | int drop_unencrypted; |
435 | 480 | ||
481 | char name[IFNAMSIZ]; | ||
482 | |||
436 | /* | 483 | /* |
437 | * keep track of whether the HT opmode (stored in | 484 | * keep track of whether the HT opmode (stored in |
438 | * vif.bss_info.ht_operation_mode) is valid. | 485 | * vif.bss_info.ht_operation_mode) is valid. |
@@ -458,8 +505,8 @@ struct ieee80211_sub_if_data { | |||
458 | */ | 505 | */ |
459 | struct ieee80211_if_ap *bss; | 506 | struct ieee80211_if_ap *bss; |
460 | 507 | ||
461 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | 508 | /* bitmap of allowed (non-MCS) rate indexes for rate control */ |
462 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | 509 | u32 rc_rateidx_mask[IEEE80211_NUM_BANDS]; |
463 | 510 | ||
464 | union { | 511 | union { |
465 | struct ieee80211_if_ap ap; | 512 | struct ieee80211_if_ap ap; |
@@ -565,6 +612,15 @@ struct ieee80211_local { | |||
565 | const struct ieee80211_ops *ops; | 612 | const struct ieee80211_ops *ops; |
566 | 613 | ||
567 | /* | 614 | /* |
615 | * work stuff, potentially off-channel (in the future) | ||
616 | */ | ||
617 | struct mutex work_mtx; | ||
618 | struct list_head work_list; | ||
619 | struct timer_list work_timer; | ||
620 | struct work_struct work_work; | ||
621 | struct sk_buff_head work_skb_queue; | ||
622 | |||
623 | /* | ||
568 | * private workqueue to mac80211. mac80211 makes this accessible | 624 | * private workqueue to mac80211. mac80211 makes this accessible |
569 | * via ieee80211_queue_work() | 625 | * via ieee80211_queue_work() |
570 | */ | 626 | */ |
@@ -586,6 +642,9 @@ struct ieee80211_local { | |||
586 | /* used for uploading changed mc list */ | 642 | /* used for uploading changed mc list */ |
587 | struct work_struct reconfig_filter; | 643 | struct work_struct reconfig_filter; |
588 | 644 | ||
645 | /* used to reconfigure hardware SM PS */ | ||
646 | struct work_struct recalc_smps; | ||
647 | |||
589 | /* aggregated multicast list */ | 648 | /* aggregated multicast list */ |
590 | struct dev_addr_list *mc_list; | 649 | struct dev_addr_list *mc_list; |
591 | int mc_count; | 650 | int mc_count; |
@@ -630,15 +689,18 @@ struct ieee80211_local { | |||
630 | 689 | ||
631 | /* Station data */ | 690 | /* Station data */ |
632 | /* | 691 | /* |
633 | * The lock only protects the list, hash, timer and counter | 692 | * The mutex only protects the list and counter, |
634 | * against manipulation, reads are done in RCU. Additionally, | 693 | * reads are done in RCU. |
635 | * the lock protects each BSS's TIM bitmap. | 694 | * Additionally, the lock protects the hash table, |
695 | * the pending list and each BSS's TIM bitmap. | ||
636 | */ | 696 | */ |
697 | struct mutex sta_mtx; | ||
637 | spinlock_t sta_lock; | 698 | spinlock_t sta_lock; |
638 | unsigned long num_sta; | 699 | unsigned long num_sta; |
639 | struct list_head sta_list; | 700 | struct list_head sta_list, sta_pending_list; |
640 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 701 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
641 | struct timer_list sta_cleanup; | 702 | struct timer_list sta_cleanup; |
703 | struct work_struct sta_finish_work; | ||
642 | int sta_generation; | 704 | int sta_generation; |
643 | 705 | ||
644 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; | 706 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; |
@@ -689,6 +751,10 @@ struct ieee80211_local { | |||
689 | enum nl80211_channel_type oper_channel_type; | 751 | enum nl80211_channel_type oper_channel_type; |
690 | struct ieee80211_channel *oper_channel, *csa_channel; | 752 | struct ieee80211_channel *oper_channel, *csa_channel; |
691 | 753 | ||
754 | /* Temporary remain-on-channel for off-channel operations */ | ||
755 | struct ieee80211_channel *tmp_channel; | ||
756 | enum nl80211_channel_type tmp_channel_type; | ||
757 | |||
692 | /* SNMP counters */ | 758 | /* SNMP counters */ |
693 | /* dot11CountersTable */ | 759 | /* dot11CountersTable */ |
694 | u32 dot11TransmittedFragmentCount; | 760 | u32 dot11TransmittedFragmentCount; |
@@ -708,10 +774,6 @@ struct ieee80211_local { | |||
708 | assoc_led_name[32], radio_led_name[32]; | 774 | assoc_led_name[32], radio_led_name[32]; |
709 | #endif | 775 | #endif |
710 | 776 | ||
711 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
712 | struct work_struct sta_debugfs_add; | ||
713 | #endif | ||
714 | |||
715 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 777 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
716 | /* TX/RX handler statistics */ | 778 | /* TX/RX handler statistics */ |
717 | unsigned int tx_handlers_drop; | 779 | unsigned int tx_handlers_drop; |
@@ -745,8 +807,22 @@ struct ieee80211_local { | |||
745 | int wifi_wme_noack_test; | 807 | int wifi_wme_noack_test; |
746 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ | 808 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ |
747 | 809 | ||
810 | /* | ||
811 | * Bitmask of enabled u-apsd queues, | ||
812 | * IEEE80211_WMM_IE_STA_QOSINFO_AC_BE & co. Needs a new association | ||
813 | * to take effect. | ||
814 | */ | ||
815 | unsigned int uapsd_queues; | ||
816 | |||
817 | /* | ||
818 | * Maximum number of buffered frames AP can deliver during a | ||
819 | * service period, IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL or similar. | ||
820 | * Needs a new association to take effect. | ||
821 | */ | ||
822 | unsigned int uapsd_max_sp_len; | ||
823 | |||
748 | bool pspolling; | 824 | bool pspolling; |
749 | bool scan_ps_enabled; | 825 | bool offchannel_ps_enabled; |
750 | /* | 826 | /* |
751 | * PS can only be enabled when we have exactly one managed | 827 | * PS can only be enabled when we have exactly one managed |
752 | * interface (and monitors) in PS, this then points there. | 828 | * interface (and monitors) in PS, this then points there. |
@@ -760,6 +836,8 @@ struct ieee80211_local { | |||
760 | int user_power_level; /* in dBm */ | 836 | int user_power_level; /* in dBm */ |
761 | int power_constr_level; /* in dBm */ | 837 | int power_constr_level; /* in dBm */ |
762 | 838 | ||
839 | enum ieee80211_smps_mode smps_mode; | ||
840 | |||
763 | struct work_struct restart_work; | 841 | struct work_struct restart_work; |
764 | 842 | ||
765 | #ifdef CONFIG_MAC80211_DEBUGFS | 843 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -874,6 +952,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
874 | void ieee80211_configure_filter(struct ieee80211_local *local); | 952 | void ieee80211_configure_filter(struct ieee80211_local *local); |
875 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); | 953 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
876 | 954 | ||
955 | extern bool ieee80211_disable_40mhz_24ghz; | ||
956 | |||
877 | /* STA code */ | 957 | /* STA code */ |
878 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); | 958 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); |
879 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 959 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
@@ -886,6 +966,10 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
886 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | 966 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, |
887 | struct cfg80211_disassoc_request *req, | 967 | struct cfg80211_disassoc_request *req, |
888 | void *cookie); | 968 | void *cookie); |
969 | int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | ||
970 | struct ieee80211_channel *chan, | ||
971 | enum nl80211_channel_type channel_type, | ||
972 | const u8 *buf, size_t len, u64 *cookie); | ||
889 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, | 973 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, |
890 | struct sk_buff *skb); | 974 | struct sk_buff *skb); |
891 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 975 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
@@ -905,7 +989,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); | |||
905 | ieee80211_rx_result | 989 | ieee80211_rx_result |
906 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 990 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
907 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 991 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
908 | u8 *bssid, u8 *addr, u32 supp_rates); | 992 | u8 *bssid, u8 *addr, u32 supp_rates, |
993 | gfp_t gfp); | ||
909 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 994 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
910 | struct cfg80211_ibss_params *params); | 995 | struct cfg80211_ibss_params *params); |
911 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | 996 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); |
@@ -937,7 +1022,15 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | |||
937 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 1022 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
938 | struct ieee80211_bss *bss); | 1023 | struct ieee80211_bss *bss); |
939 | 1024 | ||
1025 | /* off-channel helpers */ | ||
1026 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); | ||
1027 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local); | ||
1028 | void ieee80211_offchannel_return(struct ieee80211_local *local, | ||
1029 | bool enable_beaconing); | ||
1030 | |||
940 | /* interface handling */ | 1031 | /* interface handling */ |
1032 | int ieee80211_iface_init(void); | ||
1033 | void ieee80211_iface_exit(void); | ||
941 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 1034 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
942 | struct net_device **new_dev, enum nl80211_iftype type, | 1035 | struct net_device **new_dev, enum nl80211_iftype type, |
943 | struct vif_params *params); | 1036 | struct vif_params *params); |
@@ -948,6 +1041,11 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local); | |||
948 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); | 1041 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); |
949 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1042 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
950 | 1043 | ||
1044 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | ||
1045 | { | ||
1046 | return netif_running(sdata->dev); | ||
1047 | } | ||
1048 | |||
951 | /* tx handling */ | 1049 | /* tx handling */ |
952 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); | 1050 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); |
953 | void ieee80211_tx_pending(unsigned long data); | 1051 | void ieee80211_tx_pending(unsigned long data); |
@@ -976,6 +1074,9 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
976 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | 1074 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, |
977 | const u8 *da, u16 tid, | 1075 | const u8 *da, u16 tid, |
978 | u16 initiator, u16 reason_code); | 1076 | u16 initiator, u16 reason_code); |
1077 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | ||
1078 | enum ieee80211_smps_mode smps, const u8 *da, | ||
1079 | const u8 *bssid); | ||
979 | 1080 | ||
980 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | 1081 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, |
981 | u16 tid, u16 initiator, u16 reason); | 1082 | u16 tid, u16 initiator, u16 reason); |
@@ -1086,6 +1187,28 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
1086 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1187 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
1087 | struct ieee802_11_elems *elems, | 1188 | struct ieee802_11_elems *elems, |
1088 | enum ieee80211_band band); | 1189 | enum ieee80211_band band); |
1190 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | ||
1191 | enum ieee80211_smps_mode smps_mode); | ||
1192 | void ieee80211_recalc_smps(struct ieee80211_local *local, | ||
1193 | struct ieee80211_sub_if_data *forsdata); | ||
1194 | |||
1195 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | ||
1196 | const u8 *ids, int n_ids, size_t offset); | ||
1197 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); | ||
1198 | |||
1199 | /* internal work items */ | ||
1200 | void ieee80211_work_init(struct ieee80211_local *local); | ||
1201 | void ieee80211_add_work(struct ieee80211_work *wk); | ||
1202 | void free_work(struct ieee80211_work *wk); | ||
1203 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); | ||
1204 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | ||
1205 | struct sk_buff *skb); | ||
1206 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
1207 | struct ieee80211_channel *chan, | ||
1208 | enum nl80211_channel_type channel_type, | ||
1209 | unsigned int duration, u64 *cookie); | ||
1210 | int ieee80211_wk_cancel_remain_on_channel( | ||
1211 | struct ieee80211_sub_if_data *sdata, u64 cookie); | ||
1089 | 1212 | ||
1090 | #ifdef CONFIG_MAC80211_NOINLINE | 1213 | #ifdef CONFIG_MAC80211_NOINLINE |
1091 | #define debug_noinline noinline | 1214 | #define debug_noinline noinline |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 32abae3ce32a..0793d7a8d743 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -62,6 +62,23 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | |||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | static int ieee80211_change_mac(struct net_device *dev, void *addr) | ||
66 | { | ||
67 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
68 | struct sockaddr *sa = addr; | ||
69 | int ret; | ||
70 | |||
71 | if (ieee80211_sdata_running(sdata)) | ||
72 | return -EBUSY; | ||
73 | |||
74 | ret = eth_mac_addr(dev, sa); | ||
75 | |||
76 | if (ret == 0) | ||
77 | memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN); | ||
78 | |||
79 | return ret; | ||
80 | } | ||
81 | |||
65 | static inline int identical_mac_addr_allowed(int type1, int type2) | 82 | static inline int identical_mac_addr_allowed(int type1, int type2) |
66 | { | 83 | { |
67 | return type1 == NL80211_IFTYPE_MONITOR || | 84 | return type1 == NL80211_IFTYPE_MONITOR || |
@@ -82,7 +99,6 @@ static int ieee80211_open(struct net_device *dev) | |||
82 | struct ieee80211_sub_if_data *nsdata; | 99 | struct ieee80211_sub_if_data *nsdata; |
83 | struct ieee80211_local *local = sdata->local; | 100 | struct ieee80211_local *local = sdata->local; |
84 | struct sta_info *sta; | 101 | struct sta_info *sta; |
85 | struct ieee80211_if_init_conf conf; | ||
86 | u32 changed = 0; | 102 | u32 changed = 0; |
87 | int res; | 103 | int res; |
88 | u32 hw_reconf_flags = 0; | 104 | u32 hw_reconf_flags = 0; |
@@ -97,7 +113,7 @@ static int ieee80211_open(struct net_device *dev) | |||
97 | list_for_each_entry(nsdata, &local->interfaces, list) { | 113 | list_for_each_entry(nsdata, &local->interfaces, list) { |
98 | struct net_device *ndev = nsdata->dev; | 114 | struct net_device *ndev = nsdata->dev; |
99 | 115 | ||
100 | if (ndev != dev && netif_running(ndev)) { | 116 | if (ndev != dev && ieee80211_sdata_running(nsdata)) { |
101 | /* | 117 | /* |
102 | * Allow only a single IBSS interface to be up at any | 118 | * Allow only a single IBSS interface to be up at any |
103 | * time. This is restricted because beacon distribution | 119 | * time. This is restricted because beacon distribution |
@@ -183,7 +199,7 @@ static int ieee80211_open(struct net_device *dev) | |||
183 | struct net_device *ndev = nsdata->dev; | 199 | struct net_device *ndev = nsdata->dev; |
184 | 200 | ||
185 | /* | 201 | /* |
186 | * No need to check netif_running since we do not allow | 202 | * No need to check running since we do not allow |
187 | * it to start up with this invalid address. | 203 | * it to start up with this invalid address. |
188 | */ | 204 | */ |
189 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { | 205 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { |
@@ -234,10 +250,7 @@ static int ieee80211_open(struct net_device *dev) | |||
234 | ieee80211_configure_filter(local); | 250 | ieee80211_configure_filter(local); |
235 | break; | 251 | break; |
236 | default: | 252 | default: |
237 | conf.vif = &sdata->vif; | 253 | res = drv_add_interface(local, &sdata->vif); |
238 | conf.type = sdata->vif.type; | ||
239 | conf.mac_addr = dev->dev_addr; | ||
240 | res = drv_add_interface(local, &conf); | ||
241 | if (res) | 254 | if (res) |
242 | goto err_stop; | 255 | goto err_stop; |
243 | 256 | ||
@@ -320,7 +333,7 @@ static int ieee80211_open(struct net_device *dev) | |||
320 | 333 | ||
321 | return 0; | 334 | return 0; |
322 | err_del_interface: | 335 | err_del_interface: |
323 | drv_remove_interface(local, &conf); | 336 | drv_remove_interface(local, &sdata->vif); |
324 | err_stop: | 337 | err_stop: |
325 | if (!local->open_count) | 338 | if (!local->open_count) |
326 | drv_stop(local); | 339 | drv_stop(local); |
@@ -335,7 +348,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
335 | { | 348 | { |
336 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 349 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
337 | struct ieee80211_local *local = sdata->local; | 350 | struct ieee80211_local *local = sdata->local; |
338 | struct ieee80211_if_init_conf conf; | ||
339 | struct sta_info *sta; | 351 | struct sta_info *sta; |
340 | unsigned long flags; | 352 | unsigned long flags; |
341 | struct sk_buff *skb, *tmp; | 353 | struct sk_buff *skb, *tmp; |
@@ -348,6 +360,11 @@ static int ieee80211_stop(struct net_device *dev) | |||
348 | netif_tx_stop_all_queues(dev); | 360 | netif_tx_stop_all_queues(dev); |
349 | 361 | ||
350 | /* | 362 | /* |
363 | * Purge work for this interface. | ||
364 | */ | ||
365 | ieee80211_work_purge(sdata); | ||
366 | |||
367 | /* | ||
351 | * Now delete all active aggregation sessions. | 368 | * Now delete all active aggregation sessions. |
352 | */ | 369 | */ |
353 | rcu_read_lock(); | 370 | rcu_read_lock(); |
@@ -514,12 +531,9 @@ static int ieee80211_stop(struct net_device *dev) | |||
514 | BSS_CHANGED_BEACON_ENABLED); | 531 | BSS_CHANGED_BEACON_ENABLED); |
515 | } | 532 | } |
516 | 533 | ||
517 | conf.vif = &sdata->vif; | ||
518 | conf.type = sdata->vif.type; | ||
519 | conf.mac_addr = dev->dev_addr; | ||
520 | /* disable all keys for as long as this netdev is down */ | 534 | /* disable all keys for as long as this netdev is down */ |
521 | ieee80211_disable_keys(sdata); | 535 | ieee80211_disable_keys(sdata); |
522 | drv_remove_interface(local, &conf); | 536 | drv_remove_interface(local, &sdata->vif); |
523 | } | 537 | } |
524 | 538 | ||
525 | sdata->bss = NULL; | 539 | sdata->bss = NULL; |
@@ -659,7 +673,7 @@ static const struct net_device_ops ieee80211_dataif_ops = { | |||
659 | .ndo_start_xmit = ieee80211_subif_start_xmit, | 673 | .ndo_start_xmit = ieee80211_subif_start_xmit, |
660 | .ndo_set_multicast_list = ieee80211_set_multicast_list, | 674 | .ndo_set_multicast_list = ieee80211_set_multicast_list, |
661 | .ndo_change_mtu = ieee80211_change_mtu, | 675 | .ndo_change_mtu = ieee80211_change_mtu, |
662 | .ndo_set_mac_address = eth_mac_addr, | 676 | .ndo_set_mac_address = ieee80211_change_mac, |
663 | .ndo_select_queue = ieee80211_netdev_select_queue, | 677 | .ndo_select_queue = ieee80211_netdev_select_queue, |
664 | }; | 678 | }; |
665 | 679 | ||
@@ -681,10 +695,14 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, | |||
681 | 695 | ||
682 | hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); | 696 | hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); |
683 | 697 | ||
684 | if (!ieee80211_is_data_qos(hdr->frame_control)) { | 698 | if (!ieee80211_is_data(hdr->frame_control)) { |
685 | skb->priority = 7; | 699 | skb->priority = 7; |
686 | return ieee802_1d_to_ac[skb->priority]; | 700 | return ieee802_1d_to_ac[skb->priority]; |
687 | } | 701 | } |
702 | if (!ieee80211_is_data_qos(hdr->frame_control)) { | ||
703 | skb->priority = 0; | ||
704 | return ieee802_1d_to_ac[skb->priority]; | ||
705 | } | ||
688 | 706 | ||
689 | p = ieee80211_get_qos_ctl(hdr); | 707 | p = ieee80211_get_qos_ctl(hdr); |
690 | skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; | 708 | skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; |
@@ -779,7 +797,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
779 | * and goes into the requested mode. | 797 | * and goes into the requested mode. |
780 | */ | 798 | */ |
781 | 799 | ||
782 | if (netif_running(sdata->dev)) | 800 | if (ieee80211_sdata_running(sdata)) |
783 | return -EBUSY; | 801 | return -EBUSY; |
784 | 802 | ||
785 | /* Purge and reset type-dependent state. */ | 803 | /* Purge and reset type-dependent state. */ |
@@ -833,6 +851,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
833 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 851 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
834 | sdata = netdev_priv(ndev); | 852 | sdata = netdev_priv(ndev); |
835 | ndev->ieee80211_ptr = &sdata->wdev; | 853 | ndev->ieee80211_ptr = &sdata->wdev; |
854 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | ||
855 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | ||
836 | 856 | ||
837 | /* initialise type-independent data */ | 857 | /* initialise type-independent data */ |
838 | sdata->wdev.wiphy = local->hw.wiphy; | 858 | sdata->wdev.wiphy = local->hw.wiphy; |
@@ -844,8 +864,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
844 | 864 | ||
845 | INIT_LIST_HEAD(&sdata->key_list); | 865 | INIT_LIST_HEAD(&sdata->key_list); |
846 | 866 | ||
847 | sdata->force_unicast_rateidx = -1; | 867 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
848 | sdata->max_ratectrl_rateidx = -1; | 868 | struct ieee80211_supported_band *sband; |
869 | sband = local->hw.wiphy->bands[i]; | ||
870 | sdata->rc_rateidx_mask[i] = | ||
871 | sband ? (1 << sband->n_bitrates) - 1 : 0; | ||
872 | } | ||
849 | 873 | ||
850 | /* setup type-dependent data */ | 874 | /* setup type-dependent data */ |
851 | ieee80211_setup_sdata(sdata, type); | 875 | ieee80211_setup_sdata(sdata, type); |
@@ -938,6 +962,8 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
938 | wiphy_name(local->hw.wiphy)); | 962 | wiphy_name(local->hw.wiphy)); |
939 | #endif | 963 | #endif |
940 | 964 | ||
965 | drv_flush(local, false); | ||
966 | |||
941 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | 967 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; |
942 | return IEEE80211_CONF_CHANGE_IDLE; | 968 | return IEEE80211_CONF_CHANGE_IDLE; |
943 | } | 969 | } |
@@ -947,16 +973,18 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
947 | struct ieee80211_sub_if_data *sdata; | 973 | struct ieee80211_sub_if_data *sdata; |
948 | int count = 0; | 974 | int count = 0; |
949 | 975 | ||
976 | if (!list_empty(&local->work_list)) | ||
977 | return ieee80211_idle_off(local, "working"); | ||
978 | |||
950 | if (local->scanning) | 979 | if (local->scanning) |
951 | return ieee80211_idle_off(local, "scanning"); | 980 | return ieee80211_idle_off(local, "scanning"); |
952 | 981 | ||
953 | list_for_each_entry(sdata, &local->interfaces, list) { | 982 | list_for_each_entry(sdata, &local->interfaces, list) { |
954 | if (!netif_running(sdata->dev)) | 983 | if (!ieee80211_sdata_running(sdata)) |
955 | continue; | 984 | continue; |
956 | /* do not count disabled managed interfaces */ | 985 | /* do not count disabled managed interfaces */ |
957 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 986 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
958 | !sdata->u.mgd.associated && | 987 | !sdata->u.mgd.associated) |
959 | list_empty(&sdata->u.mgd.work_list)) | ||
960 | continue; | 988 | continue; |
961 | /* do not count unused IBSS interfaces */ | 989 | /* do not count unused IBSS interfaces */ |
962 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 990 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
@@ -984,3 +1012,41 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) | |||
984 | if (chg) | 1012 | if (chg) |
985 | ieee80211_hw_config(local, chg); | 1013 | ieee80211_hw_config(local, chg); |
986 | } | 1014 | } |
1015 | |||
1016 | static int netdev_notify(struct notifier_block *nb, | ||
1017 | unsigned long state, | ||
1018 | void *ndev) | ||
1019 | { | ||
1020 | struct net_device *dev = ndev; | ||
1021 | struct ieee80211_sub_if_data *sdata; | ||
1022 | |||
1023 | if (state != NETDEV_CHANGENAME) | ||
1024 | return 0; | ||
1025 | |||
1026 | if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) | ||
1027 | return 0; | ||
1028 | |||
1029 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | ||
1030 | return 0; | ||
1031 | |||
1032 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1033 | |||
1034 | memcpy(sdata->name, dev->name, IFNAMSIZ); | ||
1035 | |||
1036 | ieee80211_debugfs_rename_netdev(sdata); | ||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | static struct notifier_block mac80211_netdev_notifier = { | ||
1041 | .notifier_call = netdev_notify, | ||
1042 | }; | ||
1043 | |||
1044 | int ieee80211_iface_init(void) | ||
1045 | { | ||
1046 | return register_netdevice_notifier(&mac80211_netdev_notifier); | ||
1047 | } | ||
1048 | |||
1049 | void ieee80211_iface_exit(void) | ||
1050 | { | ||
1051 | unregister_netdevice_notifier(&mac80211_netdev_notifier); | ||
1052 | } | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 659a42d529e3..8160d9c5372e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -139,7 +139,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
139 | struct ieee80211_sub_if_data, | 139 | struct ieee80211_sub_if_data, |
140 | u.ap); | 140 | u.ap); |
141 | 141 | ||
142 | ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); | 142 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); |
143 | 143 | ||
144 | if (!ret) { | 144 | if (!ret) { |
145 | spin_lock_bh(&todo_lock); | 145 | spin_lock_bh(&todo_lock); |
@@ -181,7 +181,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
181 | struct ieee80211_sub_if_data, | 181 | struct ieee80211_sub_if_data, |
182 | u.ap); | 182 | u.ap); |
183 | 183 | ||
184 | ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif, | 184 | ret = drv_set_key(key->local, DISABLE_KEY, sdata, |
185 | sta, &key->conf); | 185 | sta, &key->conf); |
186 | 186 | ||
187 | if (ret) | 187 | if (ret) |
@@ -421,7 +421,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
421 | */ | 421 | */ |
422 | 422 | ||
423 | /* same here, the AP could be using QoS */ | 423 | /* same here, the AP could be using QoS */ |
424 | ap = sta_info_get(key->local, key->sdata->u.mgd.bssid); | 424 | ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); |
425 | if (ap) { | 425 | if (ap) { |
426 | if (test_sta_flags(ap, WLAN_STA_WME)) | 426 | if (test_sta_flags(ap, WLAN_STA_WME)) |
427 | key->conf.flags |= | 427 | key->conf.flags |= |
@@ -443,7 +443,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
443 | add_todo(old_key, KEY_FLAG_TODO_DELETE); | 443 | add_todo(old_key, KEY_FLAG_TODO_DELETE); |
444 | 444 | ||
445 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); | 445 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); |
446 | if (netif_running(sdata->dev)) | 446 | if (ieee80211_sdata_running(sdata)) |
447 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); | 447 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); |
448 | 448 | ||
449 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | 449 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); |
@@ -509,7 +509,7 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | |||
509 | { | 509 | { |
510 | ASSERT_RTNL(); | 510 | ASSERT_RTNL(); |
511 | 511 | ||
512 | if (WARN_ON(!netif_running(sdata->dev))) | 512 | if (WARN_ON(!ieee80211_sdata_running(sdata))) |
513 | return; | 513 | return; |
514 | 514 | ||
515 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); | 515 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index a49f93b79e92..bdc2968c2bbe 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -59,11 +59,17 @@ enum ieee80211_internal_key_flags { | |||
59 | KEY_FLAG_TODO_DEFMGMTKEY = BIT(6), | 59 | KEY_FLAG_TODO_DEFMGMTKEY = BIT(6), |
60 | }; | 60 | }; |
61 | 61 | ||
62 | enum ieee80211_internal_tkip_state { | ||
63 | TKIP_STATE_NOT_INIT, | ||
64 | TKIP_STATE_PHASE1_DONE, | ||
65 | TKIP_STATE_PHASE1_HW_UPLOADED, | ||
66 | }; | ||
67 | |||
62 | struct tkip_ctx { | 68 | struct tkip_ctx { |
63 | u32 iv32; | 69 | u32 iv32; |
64 | u16 iv16; | 70 | u16 iv16; |
65 | u16 p1k[5]; | 71 | u16 p1k[5]; |
66 | int initialized; | 72 | enum ieee80211_internal_tkip_state state; |
67 | }; | 73 | }; |
68 | 74 | ||
69 | struct ieee80211_key { | 75 | struct ieee80211_key { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0d2d94881f1f..06c33b68d8e5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
19 | #include <linux/if_arp.h> | 19 | #include <linux/if_arp.h> |
20 | #include <linux/wireless.h> | ||
21 | #include <linux/rtnetlink.h> | 20 | #include <linux/rtnetlink.h> |
22 | #include <linux/bitmap.h> | 21 | #include <linux/bitmap.h> |
23 | #include <linux/pm_qos_params.h> | 22 | #include <linux/pm_qos_params.h> |
@@ -32,7 +31,12 @@ | |||
32 | #include "led.h" | 31 | #include "led.h" |
33 | #include "cfg.h" | 32 | #include "cfg.h" |
34 | #include "debugfs.h" | 33 | #include "debugfs.h" |
35 | #include "debugfs_netdev.h" | 34 | |
35 | |||
36 | bool ieee80211_disable_40mhz_24ghz; | ||
37 | module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); | ||
38 | MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, | ||
39 | "Disable 40MHz support in the 2.4GHz band"); | ||
36 | 40 | ||
37 | void ieee80211_configure_filter(struct ieee80211_local *local) | 41 | void ieee80211_configure_filter(struct ieee80211_local *local) |
38 | { | 42 | { |
@@ -102,6 +106,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
102 | if (scan_chan) { | 106 | if (scan_chan) { |
103 | chan = scan_chan; | 107 | chan = scan_chan; |
104 | channel_type = NL80211_CHAN_NO_HT; | 108 | channel_type = NL80211_CHAN_NO_HT; |
109 | } else if (local->tmp_channel) { | ||
110 | chan = scan_chan = local->tmp_channel; | ||
111 | channel_type = local->tmp_channel_type; | ||
105 | } else { | 112 | } else { |
106 | chan = local->oper_channel; | 113 | chan = local->oper_channel; |
107 | channel_type = local->oper_channel_type; | 114 | channel_type = local->oper_channel_type; |
@@ -114,6 +121,18 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
114 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 121 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
115 | } | 122 | } |
116 | 123 | ||
124 | if (!conf_is_ht(&local->hw.conf)) { | ||
125 | /* | ||
126 | * mac80211.h documents that this is only valid | ||
127 | * when the channel is set to an HT type, and | ||
128 | * that otherwise STATIC is used. | ||
129 | */ | ||
130 | local->hw.conf.smps_mode = IEEE80211_SMPS_STATIC; | ||
131 | } else if (local->hw.conf.smps_mode != local->smps_mode) { | ||
132 | local->hw.conf.smps_mode = local->smps_mode; | ||
133 | changed |= IEEE80211_CONF_CHANGE_SMPS; | ||
134 | } | ||
135 | |||
117 | if (scan_chan) | 136 | if (scan_chan) |
118 | power = chan->max_power; | 137 | power = chan->max_power; |
119 | else | 138 | else |
@@ -173,7 +192,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
173 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 192 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
174 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; | 193 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; |
175 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | 194 | else if (sdata->vif.type == NL80211_IFTYPE_AP) |
176 | sdata->vif.bss_conf.bssid = sdata->dev->dev_addr; | 195 | sdata->vif.bss_conf.bssid = sdata->vif.addr; |
177 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 196 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
178 | sdata->vif.bss_conf.bssid = zero; | 197 | sdata->vif.bss_conf.bssid = zero; |
179 | } else { | 198 | } else { |
@@ -195,7 +214,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
195 | } | 214 | } |
196 | 215 | ||
197 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 216 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
198 | if (local->quiescing || !netif_running(sdata->dev) || | 217 | if (local->quiescing || !ieee80211_sdata_running(sdata) || |
199 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { | 218 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { |
200 | sdata->vif.bss_conf.enable_beacon = false; | 219 | sdata->vif.bss_conf.enable_beacon = false; |
201 | } else { | 220 | } else { |
@@ -223,8 +242,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
223 | } | 242 | } |
224 | } | 243 | } |
225 | 244 | ||
226 | drv_bss_info_changed(local, &sdata->vif, | 245 | drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); |
227 | &sdata->vif.bss_conf, changed); | ||
228 | } | 246 | } |
229 | 247 | ||
230 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | 248 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) |
@@ -299,6 +317,16 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
299 | } | 317 | } |
300 | EXPORT_SYMBOL(ieee80211_restart_hw); | 318 | EXPORT_SYMBOL(ieee80211_restart_hw); |
301 | 319 | ||
320 | static void ieee80211_recalc_smps_work(struct work_struct *work) | ||
321 | { | ||
322 | struct ieee80211_local *local = | ||
323 | container_of(work, struct ieee80211_local, recalc_smps); | ||
324 | |||
325 | mutex_lock(&local->iflist_mtx); | ||
326 | ieee80211_recalc_smps(local, NULL); | ||
327 | mutex_unlock(&local->iflist_mtx); | ||
328 | } | ||
329 | |||
302 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 330 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
303 | const struct ieee80211_ops *ops) | 331 | const struct ieee80211_ops *ops) |
304 | { | 332 | { |
@@ -333,9 +361,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
333 | WIPHY_FLAG_4ADDR_STATION; | 361 | WIPHY_FLAG_4ADDR_STATION; |
334 | wiphy->privid = mac80211_wiphy_privid; | 362 | wiphy->privid = mac80211_wiphy_privid; |
335 | 363 | ||
336 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ | 364 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss); |
337 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - | ||
338 | sizeof(struct cfg80211_bss); | ||
339 | 365 | ||
340 | local = wiphy_priv(wiphy); | 366 | local = wiphy_priv(wiphy); |
341 | 367 | ||
@@ -358,6 +384,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
358 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 384 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
359 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 385 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
360 | local->user_power_level = -1; | 386 | local->user_power_level = -1; |
387 | local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; | ||
388 | local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; | ||
361 | 389 | ||
362 | INIT_LIST_HEAD(&local->interfaces); | 390 | INIT_LIST_HEAD(&local->interfaces); |
363 | mutex_init(&local->iflist_mtx); | 391 | mutex_init(&local->iflist_mtx); |
@@ -369,9 +397,13 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
369 | 397 | ||
370 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 398 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
371 | 399 | ||
400 | ieee80211_work_init(local); | ||
401 | |||
372 | INIT_WORK(&local->restart_work, ieee80211_restart_work); | 402 | INIT_WORK(&local->restart_work, ieee80211_restart_work); |
373 | 403 | ||
374 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); | 404 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); |
405 | INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work); | ||
406 | local->smps_mode = IEEE80211_SMPS_OFF; | ||
375 | 407 | ||
376 | INIT_WORK(&local->dynamic_ps_enable_work, | 408 | INIT_WORK(&local->dynamic_ps_enable_work, |
377 | ieee80211_dynamic_ps_enable_work); | 409 | ieee80211_dynamic_ps_enable_work); |
@@ -461,6 +493,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
461 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 493 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
462 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; | 494 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; |
463 | 495 | ||
496 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | ||
497 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), | ||
498 | "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"); | ||
499 | |||
464 | /* | 500 | /* |
465 | * Calculate scan IE length -- we need this to alloc | 501 | * Calculate scan IE length -- we need this to alloc |
466 | * memory and to subtract from the driver limit. It | 502 | * memory and to subtract from the driver limit. It |
@@ -522,8 +558,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
522 | 558 | ||
523 | debugfs_hw_add(local); | 559 | debugfs_hw_add(local); |
524 | 560 | ||
561 | /* | ||
562 | * if the driver doesn't specify a max listen interval we | ||
563 | * use 5 which should be a safe default | ||
564 | */ | ||
525 | if (local->hw.max_listen_interval == 0) | 565 | if (local->hw.max_listen_interval == 0) |
526 | local->hw.max_listen_interval = 1; | 566 | local->hw.max_listen_interval = 5; |
527 | 567 | ||
528 | local->hw.conf.listen_interval = local->hw.max_listen_interval; | 568 | local->hw.conf.listen_interval = local->hw.max_listen_interval; |
529 | 569 | ||
@@ -674,11 +714,19 @@ static int __init ieee80211_init(void) | |||
674 | 714 | ||
675 | ret = rc80211_pid_init(); | 715 | ret = rc80211_pid_init(); |
676 | if (ret) | 716 | if (ret) |
677 | return ret; | 717 | goto err_pid; |
678 | 718 | ||
679 | ieee80211_debugfs_netdev_init(); | 719 | ret = ieee80211_iface_init(); |
720 | if (ret) | ||
721 | goto err_netdev; | ||
680 | 722 | ||
681 | return 0; | 723 | return 0; |
724 | err_netdev: | ||
725 | rc80211_pid_exit(); | ||
726 | err_pid: | ||
727 | rc80211_minstrel_exit(); | ||
728 | |||
729 | return ret; | ||
682 | } | 730 | } |
683 | 731 | ||
684 | static void __exit ieee80211_exit(void) | 732 | static void __exit ieee80211_exit(void) |
@@ -695,7 +743,7 @@ static void __exit ieee80211_exit(void) | |||
695 | if (mesh_allocated) | 743 | if (mesh_allocated) |
696 | ieee80211s_stop(); | 744 | ieee80211s_stop(); |
697 | 745 | ||
698 | ieee80211_debugfs_netdev_exit(); | 746 | ieee80211_iface_exit(); |
699 | } | 747 | } |
700 | 748 | ||
701 | 749 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6a4331429598..61080c5fad50 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -457,7 +457,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
457 | 457 | ||
458 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 458 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
459 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", | 459 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", |
460 | sdata->dev->name); | 460 | sdata->name); |
461 | #endif | 461 | #endif |
462 | 462 | ||
463 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 463 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
@@ -565,7 +565,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
565 | 565 | ||
566 | /* ignore ProbeResp to foreign address */ | 566 | /* ignore ProbeResp to foreign address */ |
567 | if (stype == IEEE80211_STYPE_PROBE_RESP && | 567 | if (stype == IEEE80211_STYPE_PROBE_RESP && |
568 | compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) | 568 | compare_ether_addr(mgmt->da, sdata->vif.addr)) |
569 | return; | 569 | return; |
570 | 570 | ||
571 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 571 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
@@ -645,7 +645,7 @@ static void ieee80211_mesh_work(struct work_struct *work) | |||
645 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 645 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
646 | struct sk_buff *skb; | 646 | struct sk_buff *skb; |
647 | 647 | ||
648 | if (!netif_running(sdata->dev)) | 648 | if (!ieee80211_sdata_running(sdata)) |
649 | return; | 649 | return; |
650 | 650 | ||
651 | if (local->scanning) | 651 | if (local->scanning) |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index d28acb6b1f81..ce84237ebad3 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -128,9 +128,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
128 | IEEE80211_STYPE_ACTION); | 128 | IEEE80211_STYPE_ACTION); |
129 | 129 | ||
130 | memcpy(mgmt->da, da, ETH_ALEN); | 130 | memcpy(mgmt->da, da, ETH_ALEN); |
131 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 131 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
132 | /* BSSID == SA */ | 132 | /* BSSID == SA */ |
133 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 133 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
134 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 134 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; |
135 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 135 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; |
136 | 136 | ||
@@ -222,7 +222,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
222 | IEEE80211_STYPE_ACTION); | 222 | IEEE80211_STYPE_ACTION); |
223 | 223 | ||
224 | memcpy(mgmt->da, ra, ETH_ALEN); | 224 | memcpy(mgmt->da, ra, ETH_ALEN); |
225 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 225 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
226 | /* BSSID is left zeroed, wildcard value */ | 226 | /* BSSID is left zeroed, wildcard value */ |
227 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 227 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; |
228 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 228 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; |
@@ -335,7 +335,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
335 | bool process = true; | 335 | bool process = true; |
336 | 336 | ||
337 | rcu_read_lock(); | 337 | rcu_read_lock(); |
338 | sta = sta_info_get(local, mgmt->sa); | 338 | sta = sta_info_get(sdata, mgmt->sa); |
339 | if (!sta) { | 339 | if (!sta) { |
340 | rcu_read_unlock(); | 340 | rcu_read_unlock(); |
341 | return 0; | 341 | return 0; |
@@ -374,7 +374,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
374 | new_metric = MAX_METRIC; | 374 | new_metric = MAX_METRIC; |
375 | exp_time = TU_TO_EXP_TIME(orig_lifetime); | 375 | exp_time = TU_TO_EXP_TIME(orig_lifetime); |
376 | 376 | ||
377 | if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { | 377 | if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) { |
378 | /* This MP is the originator, we are not interested in this | 378 | /* This MP is the originator, we are not interested in this |
379 | * frame, except for updating transmitter's path info. | 379 | * frame, except for updating transmitter's path info. |
380 | */ | 380 | */ |
@@ -486,7 +486,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
486 | 486 | ||
487 | mhwmp_dbg("received PREQ from %pM\n", orig_addr); | 487 | mhwmp_dbg("received PREQ from %pM\n", orig_addr); |
488 | 488 | ||
489 | if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { | 489 | if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { |
490 | mhwmp_dbg("PREQ is for us\n"); | 490 | mhwmp_dbg("PREQ is for us\n"); |
491 | forward = false; | 491 | forward = false; |
492 | reply = true; | 492 | reply = true; |
@@ -579,7 +579,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
579 | * replies | 579 | * replies |
580 | */ | 580 | */ |
581 | target_addr = PREP_IE_TARGET_ADDR(prep_elem); | 581 | target_addr = PREP_IE_TARGET_ADDR(prep_elem); |
582 | if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) | 582 | if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) |
583 | /* destination, no forwarding required */ | 583 | /* destination, no forwarding required */ |
584 | return; | 584 | return; |
585 | 585 | ||
@@ -890,7 +890,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
890 | target_flags = MP_F_RF; | 890 | target_flags = MP_F_RF; |
891 | 891 | ||
892 | spin_unlock_bh(&mpath->state_lock); | 892 | spin_unlock_bh(&mpath->state_lock); |
893 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, | 893 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, |
894 | cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, | 894 | cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, |
895 | cpu_to_le32(mpath->sn), broadcast_addr, 0, | 895 | cpu_to_le32(mpath->sn), broadcast_addr, 0, |
896 | ttl, cpu_to_le32(lifetime), 0, | 896 | ttl, cpu_to_le32(lifetime), 0, |
@@ -939,7 +939,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
939 | if (time_after(jiffies, | 939 | if (time_after(jiffies, |
940 | mpath->exp_time - | 940 | mpath->exp_time - |
941 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && | 941 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && |
942 | !memcmp(sdata->dev->dev_addr, hdr->addr4, ETH_ALEN) && | 942 | !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && |
943 | !(mpath->flags & MESH_PATH_RESOLVING) && | 943 | !(mpath->flags & MESH_PATH_RESOLVING) && |
944 | !(mpath->flags & MESH_PATH_FIXED)) { | 944 | !(mpath->flags & MESH_PATH_FIXED)) { |
945 | mesh_queue_preq(mpath, | 945 | mesh_queue_preq(mpath, |
@@ -1010,7 +1010,7 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | |||
1010 | { | 1010 | { |
1011 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1011 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1012 | 1012 | ||
1013 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->dev->dev_addr, | 1013 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, |
1014 | cpu_to_le32(++ifmsh->sn), | 1014 | cpu_to_le32(++ifmsh->sn), |
1015 | 0, NULL, 0, broadcast_addr, | 1015 | 0, NULL, 0, broadcast_addr, |
1016 | 0, MESH_TTL, 0, 0, 0, sdata); | 1016 | 0, MESH_TTL, 0, 0, 0, sdata); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0192cfdacae4..2312efe04c62 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -260,7 +260,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
260 | int err = 0; | 260 | int err = 0; |
261 | u32 hash_idx; | 261 | u32 hash_idx; |
262 | 262 | ||
263 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | 263 | if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0) |
264 | /* never add ourselves as neighbours */ | 264 | /* never add ourselves as neighbours */ |
265 | return -ENOTSUPP; | 265 | return -ENOTSUPP; |
266 | 266 | ||
@@ -377,7 +377,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
377 | int err = 0; | 377 | int err = 0; |
378 | u32 hash_idx; | 378 | u32 hash_idx; |
379 | 379 | ||
380 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | 380 | if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0) |
381 | /* never add ourselves as neighbours */ | 381 | /* never add ourselves as neighbours */ |
382 | return -ENOTSUPP; | 382 | return -ENOTSUPP; |
383 | 383 | ||
@@ -605,7 +605,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
605 | struct mesh_path *mpath; | 605 | struct mesh_path *mpath; |
606 | u32 sn = 0; | 606 | u32 sn = 0; |
607 | 607 | ||
608 | if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) { | 608 | if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { |
609 | u8 *ra, *da; | 609 | u8 *ra, *da; |
610 | 610 | ||
611 | da = hdr->addr3; | 611 | da = hdr->addr3; |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 54e4c8bb23e7..1a29c4a8139e 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -102,7 +102,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
102 | if (local->num_sta >= MESH_MAX_PLINKS) | 102 | if (local->num_sta >= MESH_MAX_PLINKS) |
103 | return NULL; | 103 | return NULL; |
104 | 104 | ||
105 | sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC); | 105 | sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); |
106 | if (!sta) | 106 | if (!sta) |
107 | return NULL; | 107 | return NULL; |
108 | 108 | ||
@@ -169,7 +169,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
169 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 169 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
170 | IEEE80211_STYPE_ACTION); | 170 | IEEE80211_STYPE_ACTION); |
171 | memcpy(mgmt->da, da, ETH_ALEN); | 171 | memcpy(mgmt->da, da, ETH_ALEN); |
172 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 172 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
173 | /* BSSID is left zeroed, wildcard value */ | 173 | /* BSSID is left zeroed, wildcard value */ |
174 | mgmt->u.action.category = MESH_PLINK_CATEGORY; | 174 | mgmt->u.action.category = MESH_PLINK_CATEGORY; |
175 | mgmt->u.action.u.plink_action.action_code = action; | 175 | mgmt->u.action.u.plink_action.action_code = action; |
@@ -234,14 +234,14 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data | |||
234 | 234 | ||
235 | rcu_read_lock(); | 235 | rcu_read_lock(); |
236 | 236 | ||
237 | sta = sta_info_get(local, hw_addr); | 237 | sta = sta_info_get(sdata, hw_addr); |
238 | if (!sta) { | 238 | if (!sta) { |
239 | rcu_read_unlock(); | ||
240 | |||
239 | sta = mesh_plink_alloc(sdata, hw_addr, rates); | 241 | sta = mesh_plink_alloc(sdata, hw_addr, rates); |
240 | if (!sta) { | 242 | if (!sta) |
241 | rcu_read_unlock(); | ||
242 | return; | 243 | return; |
243 | } | 244 | if (sta_info_insert_rcu(sta)) { |
244 | if (sta_info_insert(sta)) { | ||
245 | rcu_read_unlock(); | 245 | rcu_read_unlock(); |
246 | return; | 246 | return; |
247 | } | 247 | } |
@@ -455,7 +455,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
455 | 455 | ||
456 | rcu_read_lock(); | 456 | rcu_read_lock(); |
457 | 457 | ||
458 | sta = sta_info_get(local, mgmt->sa); | 458 | sta = sta_info_get(sdata, mgmt->sa); |
459 | if (!sta && ftype != PLINK_OPEN) { | 459 | if (!sta && ftype != PLINK_OPEN) { |
460 | mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); | 460 | mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); |
461 | rcu_read_unlock(); | 461 | rcu_read_unlock(); |
@@ -485,9 +485,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
485 | } else if (!sta) { | 485 | } else if (!sta) { |
486 | /* ftype == PLINK_OPEN */ | 486 | /* ftype == PLINK_OPEN */ |
487 | u32 rates; | 487 | u32 rates; |
488 | |||
489 | rcu_read_unlock(); | ||
490 | |||
488 | if (!mesh_plink_free_count(sdata)) { | 491 | if (!mesh_plink_free_count(sdata)) { |
489 | mpl_dbg("Mesh plink error: no more free plinks\n"); | 492 | mpl_dbg("Mesh plink error: no more free plinks\n"); |
490 | rcu_read_unlock(); | ||
491 | return; | 493 | return; |
492 | } | 494 | } |
493 | 495 | ||
@@ -495,10 +497,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
495 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates); | 497 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates); |
496 | if (!sta) { | 498 | if (!sta) { |
497 | mpl_dbg("Mesh plink error: plink table full\n"); | 499 | mpl_dbg("Mesh plink error: plink table full\n"); |
498 | rcu_read_unlock(); | ||
499 | return; | 500 | return; |
500 | } | 501 | } |
501 | if (sta_info_insert(sta)) { | 502 | if (sta_info_insert_rcu(sta)) { |
502 | rcu_read_unlock(); | 503 | rcu_read_unlock(); |
503 | return; | 504 | return; |
504 | } | 505 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 05a18f43e1bf..41812a15eea0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -27,10 +27,6 @@ | |||
27 | #include "rate.h" | 27 | #include "rate.h" |
28 | #include "led.h" | 28 | #include "led.h" |
29 | 29 | ||
30 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | ||
31 | #define IEEE80211_AUTH_MAX_TRIES 3 | ||
32 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | ||
33 | #define IEEE80211_ASSOC_MAX_TRIES 3 | ||
34 | #define IEEE80211_MAX_PROBE_TRIES 5 | 30 | #define IEEE80211_MAX_PROBE_TRIES 5 |
35 | 31 | ||
36 | /* | 32 | /* |
@@ -75,11 +71,8 @@ enum rx_mgmt_action { | |||
75 | /* caller must call cfg80211_send_disassoc() */ | 71 | /* caller must call cfg80211_send_disassoc() */ |
76 | RX_MGMT_CFG80211_DISASSOC, | 72 | RX_MGMT_CFG80211_DISASSOC, |
77 | 73 | ||
78 | /* caller must call cfg80211_auth_timeout() & free work */ | 74 | /* caller must tell cfg80211 about internal error */ |
79 | RX_MGMT_CFG80211_AUTH_TO, | 75 | RX_MGMT_CFG80211_ASSOC_ERROR, |
80 | |||
81 | /* caller must call cfg80211_assoc_timeout() & free work */ | ||
82 | RX_MGMT_CFG80211_ASSOC_TO, | ||
83 | }; | 76 | }; |
84 | 77 | ||
85 | /* utils */ | 78 | /* utils */ |
@@ -122,27 +115,6 @@ static int ecw2cw(int ecw) | |||
122 | return (1 << ecw) - 1; | 115 | return (1 << ecw) - 1; |
123 | } | 116 | } |
124 | 117 | ||
125 | static int ieee80211_compatible_rates(struct ieee80211_bss *bss, | ||
126 | struct ieee80211_supported_band *sband, | ||
127 | u32 *rates) | ||
128 | { | ||
129 | int i, j, count; | ||
130 | *rates = 0; | ||
131 | count = 0; | ||
132 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
133 | int rate = (bss->supp_rates[i] & 0x7F) * 5; | ||
134 | |||
135 | for (j = 0; j < sband->n_bitrates; j++) | ||
136 | if (sband->bitrates[j].bitrate == rate) { | ||
137 | *rates |= BIT(j); | ||
138 | count++; | ||
139 | break; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | return count; | ||
144 | } | ||
145 | |||
146 | /* | 118 | /* |
147 | * ieee80211_enable_ht should be called only after the operating band | 119 | * ieee80211_enable_ht should be called only after the operating band |
148 | * has been determined as ht configuration depends on the hw's | 120 | * has been determined as ht configuration depends on the hw's |
@@ -202,7 +174,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
202 | ieee80211_hw_config(local, 0); | 174 | ieee80211_hw_config(local, 0); |
203 | 175 | ||
204 | rcu_read_lock(); | 176 | rcu_read_lock(); |
205 | sta = sta_info_get(local, bssid); | 177 | sta = sta_info_get(sdata, bssid); |
206 | if (sta) | 178 | if (sta) |
207 | rate_control_rate_update(local, sband, sta, | 179 | rate_control_rate_update(local, sband, sta, |
208 | IEEE80211_RC_HT_CHANGED); | 180 | IEEE80211_RC_HT_CHANGED); |
@@ -228,209 +200,6 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
228 | 200 | ||
229 | /* frame sending functions */ | 201 | /* frame sending functions */ |
230 | 202 | ||
231 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | ||
232 | struct ieee80211_mgd_work *wk) | ||
233 | { | ||
234 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
235 | struct ieee80211_local *local = sdata->local; | ||
236 | struct sk_buff *skb; | ||
237 | struct ieee80211_mgmt *mgmt; | ||
238 | u8 *pos; | ||
239 | const u8 *ies, *ht_ie; | ||
240 | int i, len, count, rates_len, supp_rates_len; | ||
241 | u16 capab; | ||
242 | int wmm = 0; | ||
243 | struct ieee80211_supported_band *sband; | ||
244 | u32 rates = 0; | ||
245 | |||
246 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
247 | sizeof(*mgmt) + 200 + wk->ie_len + | ||
248 | wk->ssid_len); | ||
249 | if (!skb) { | ||
250 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | ||
251 | "frame\n", sdata->dev->name); | ||
252 | return; | ||
253 | } | ||
254 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
255 | |||
256 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
257 | |||
258 | capab = ifmgd->capab; | ||
259 | |||
260 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) { | ||
261 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | ||
262 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; | ||
263 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) | ||
264 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
265 | } | ||
266 | |||
267 | if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY) | ||
268 | capab |= WLAN_CAPABILITY_PRIVACY; | ||
269 | if (wk->bss->wmm_used) | ||
270 | wmm = 1; | ||
271 | |||
272 | /* get all rates supported by the device and the AP as | ||
273 | * some APs don't like getting a superset of their rates | ||
274 | * in the association request (e.g. D-Link DAP 1353 in | ||
275 | * b-only mode) */ | ||
276 | rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates); | ||
277 | |||
278 | if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && | ||
279 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) | ||
280 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; | ||
281 | |||
282 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
283 | memset(mgmt, 0, 24); | ||
284 | memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN); | ||
285 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
286 | memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN); | ||
287 | |||
288 | if (!is_zero_ether_addr(wk->prev_bssid)) { | ||
289 | skb_put(skb, 10); | ||
290 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
291 | IEEE80211_STYPE_REASSOC_REQ); | ||
292 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); | ||
293 | mgmt->u.reassoc_req.listen_interval = | ||
294 | cpu_to_le16(local->hw.conf.listen_interval); | ||
295 | memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid, | ||
296 | ETH_ALEN); | ||
297 | } else { | ||
298 | skb_put(skb, 4); | ||
299 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
300 | IEEE80211_STYPE_ASSOC_REQ); | ||
301 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | ||
302 | mgmt->u.assoc_req.listen_interval = | ||
303 | cpu_to_le16(local->hw.conf.listen_interval); | ||
304 | } | ||
305 | |||
306 | /* SSID */ | ||
307 | ies = pos = skb_put(skb, 2 + wk->ssid_len); | ||
308 | *pos++ = WLAN_EID_SSID; | ||
309 | *pos++ = wk->ssid_len; | ||
310 | memcpy(pos, wk->ssid, wk->ssid_len); | ||
311 | |||
312 | /* add all rates which were marked to be used above */ | ||
313 | supp_rates_len = rates_len; | ||
314 | if (supp_rates_len > 8) | ||
315 | supp_rates_len = 8; | ||
316 | |||
317 | len = sband->n_bitrates; | ||
318 | pos = skb_put(skb, supp_rates_len + 2); | ||
319 | *pos++ = WLAN_EID_SUPP_RATES; | ||
320 | *pos++ = supp_rates_len; | ||
321 | |||
322 | count = 0; | ||
323 | for (i = 0; i < sband->n_bitrates; i++) { | ||
324 | if (BIT(i) & rates) { | ||
325 | int rate = sband->bitrates[i].bitrate; | ||
326 | *pos++ = (u8) (rate / 5); | ||
327 | if (++count == 8) | ||
328 | break; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | if (rates_len > count) { | ||
333 | pos = skb_put(skb, rates_len - count + 2); | ||
334 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
335 | *pos++ = rates_len - count; | ||
336 | |||
337 | for (i++; i < sband->n_bitrates; i++) { | ||
338 | if (BIT(i) & rates) { | ||
339 | int rate = sband->bitrates[i].bitrate; | ||
340 | *pos++ = (u8) (rate / 5); | ||
341 | } | ||
342 | } | ||
343 | } | ||
344 | |||
345 | if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { | ||
346 | /* 1. power capabilities */ | ||
347 | pos = skb_put(skb, 4); | ||
348 | *pos++ = WLAN_EID_PWR_CAPABILITY; | ||
349 | *pos++ = 2; | ||
350 | *pos++ = 0; /* min tx power */ | ||
351 | *pos++ = local->hw.conf.channel->max_power; /* max tx power */ | ||
352 | |||
353 | /* 2. supported channels */ | ||
354 | /* TODO: get this in reg domain format */ | ||
355 | pos = skb_put(skb, 2 * sband->n_channels + 2); | ||
356 | *pos++ = WLAN_EID_SUPPORTED_CHANNELS; | ||
357 | *pos++ = 2 * sband->n_channels; | ||
358 | for (i = 0; i < sband->n_channels; i++) { | ||
359 | *pos++ = ieee80211_frequency_to_channel( | ||
360 | sband->channels[i].center_freq); | ||
361 | *pos++ = 1; /* one channel in the subband*/ | ||
362 | } | ||
363 | } | ||
364 | |||
365 | if (wk->ie_len && wk->ie) { | ||
366 | pos = skb_put(skb, wk->ie_len); | ||
367 | memcpy(pos, wk->ie, wk->ie_len); | ||
368 | } | ||
369 | |||
370 | if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) { | ||
371 | pos = skb_put(skb, 9); | ||
372 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
373 | *pos++ = 7; /* len */ | ||
374 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
375 | *pos++ = 0x50; | ||
376 | *pos++ = 0xf2; | ||
377 | *pos++ = 2; /* WME */ | ||
378 | *pos++ = 0; /* WME info */ | ||
379 | *pos++ = 1; /* WME ver */ | ||
380 | *pos++ = 0; | ||
381 | } | ||
382 | |||
383 | /* wmm support is a must to HT */ | ||
384 | /* | ||
385 | * IEEE802.11n does not allow TKIP/WEP as pairwise | ||
386 | * ciphers in HT mode. We still associate in non-ht | ||
387 | * mode (11a/b/g) if any one of these ciphers is | ||
388 | * configured as pairwise. | ||
389 | */ | ||
390 | if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && | ||
391 | sband->ht_cap.ht_supported && | ||
392 | (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) && | ||
393 | ht_ie[1] >= sizeof(struct ieee80211_ht_info) && | ||
394 | (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) { | ||
395 | struct ieee80211_ht_info *ht_info = | ||
396 | (struct ieee80211_ht_info *)(ht_ie + 2); | ||
397 | u16 cap = sband->ht_cap.cap; | ||
398 | __le16 tmp; | ||
399 | u32 flags = local->hw.conf.channel->flags; | ||
400 | |||
401 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
402 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
403 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | ||
404 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
405 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
406 | } | ||
407 | break; | ||
408 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
409 | if (flags & IEEE80211_CHAN_NO_HT40MINUS) { | ||
410 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
411 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
412 | } | ||
413 | break; | ||
414 | } | ||
415 | |||
416 | tmp = cpu_to_le16(cap); | ||
417 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); | ||
418 | *pos++ = WLAN_EID_HT_CAPABILITY; | ||
419 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
420 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | ||
421 | memcpy(pos, &tmp, sizeof(u16)); | ||
422 | pos += sizeof(u16); | ||
423 | /* TODO: needs a define here for << 2 */ | ||
424 | *pos++ = sband->ht_cap.ampdu_factor | | ||
425 | (sband->ht_cap.ampdu_density << 2); | ||
426 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | ||
427 | } | ||
428 | |||
429 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
430 | ieee80211_tx_skb(sdata, skb); | ||
431 | } | ||
432 | |||
433 | |||
434 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | 203 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, |
435 | const u8 *bssid, u16 stype, u16 reason, | 204 | const u8 *bssid, u16 stype, u16 reason, |
436 | void *cookie) | 205 | void *cookie) |
@@ -443,7 +212,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
443 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 212 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); |
444 | if (!skb) { | 213 | if (!skb) { |
445 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | 214 | printk(KERN_DEBUG "%s: failed to allocate buffer for " |
446 | "deauth/disassoc frame\n", sdata->dev->name); | 215 | "deauth/disassoc frame\n", sdata->name); |
447 | return; | 216 | return; |
448 | } | 217 | } |
449 | skb_reserve(skb, local->hw.extra_tx_headroom); | 218 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -451,7 +220,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
451 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 220 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
452 | memset(mgmt, 0, 24); | 221 | memset(mgmt, 0, 24); |
453 | memcpy(mgmt->da, bssid, ETH_ALEN); | 222 | memcpy(mgmt->da, bssid, ETH_ALEN); |
454 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 223 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
455 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | 224 | memcpy(mgmt->bssid, bssid, ETH_ALEN); |
456 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); | 225 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); |
457 | skb_put(skb, 2); | 226 | skb_put(skb, 2); |
@@ -476,30 +245,15 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
476 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 245 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
477 | struct ieee80211_sub_if_data *sdata) | 246 | struct ieee80211_sub_if_data *sdata) |
478 | { | 247 | { |
479 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
480 | struct ieee80211_pspoll *pspoll; | 248 | struct ieee80211_pspoll *pspoll; |
481 | struct sk_buff *skb; | 249 | struct sk_buff *skb; |
482 | u16 fc; | ||
483 | 250 | ||
484 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); | 251 | skb = ieee80211_pspoll_get(&local->hw, &sdata->vif); |
485 | if (!skb) { | 252 | if (!skb) |
486 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | ||
487 | "pspoll frame\n", sdata->dev->name); | ||
488 | return; | 253 | return; |
489 | } | ||
490 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
491 | |||
492 | pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll)); | ||
493 | memset(pspoll, 0, sizeof(*pspoll)); | ||
494 | fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM; | ||
495 | pspoll->frame_control = cpu_to_le16(fc); | ||
496 | pspoll->aid = cpu_to_le16(ifmgd->aid); | ||
497 | |||
498 | /* aid in PS-Poll has its two MSBs each set to 1 */ | ||
499 | pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); | ||
500 | 254 | ||
501 | memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); | 255 | pspoll = (struct ieee80211_pspoll *) skb->data; |
502 | memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN); | 256 | pspoll->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
503 | 257 | ||
504 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 258 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
505 | ieee80211_tx_skb(sdata, skb); | 259 | ieee80211_tx_skb(sdata, skb); |
@@ -510,30 +264,47 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
510 | int powersave) | 264 | int powersave) |
511 | { | 265 | { |
512 | struct sk_buff *skb; | 266 | struct sk_buff *skb; |
267 | struct ieee80211_hdr_3addr *nullfunc; | ||
268 | |||
269 | skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif); | ||
270 | if (!skb) | ||
271 | return; | ||
272 | |||
273 | nullfunc = (struct ieee80211_hdr_3addr *) skb->data; | ||
274 | if (powersave) | ||
275 | nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); | ||
276 | |||
277 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
278 | ieee80211_tx_skb(sdata, skb); | ||
279 | } | ||
280 | |||
281 | static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, | ||
282 | struct ieee80211_sub_if_data *sdata) | ||
283 | { | ||
284 | struct sk_buff *skb; | ||
513 | struct ieee80211_hdr *nullfunc; | 285 | struct ieee80211_hdr *nullfunc; |
514 | __le16 fc; | 286 | __le16 fc; |
515 | 287 | ||
516 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) | 288 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) |
517 | return; | 289 | return; |
518 | 290 | ||
519 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); | 291 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); |
520 | if (!skb) { | 292 | if (!skb) { |
521 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " | 293 | printk(KERN_DEBUG "%s: failed to allocate buffer for 4addr " |
522 | "frame\n", sdata->dev->name); | 294 | "nullfunc frame\n", sdata->name); |
523 | return; | 295 | return; |
524 | } | 296 | } |
525 | skb_reserve(skb, local->hw.extra_tx_headroom); | 297 | skb_reserve(skb, local->hw.extra_tx_headroom); |
526 | 298 | ||
527 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); | 299 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30); |
528 | memset(nullfunc, 0, 24); | 300 | memset(nullfunc, 0, 30); |
529 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | 301 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | |
530 | IEEE80211_FCTL_TODS); | 302 | IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
531 | if (powersave) | ||
532 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | ||
533 | nullfunc->frame_control = fc; | 303 | nullfunc->frame_control = fc; |
534 | memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); | 304 | memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); |
535 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | 305 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); |
536 | memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); | 306 | memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); |
307 | memcpy(nullfunc->addr4, sdata->vif.addr, ETH_ALEN); | ||
537 | 308 | ||
538 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 309 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
539 | ieee80211_tx_skb(sdata, skb); | 310 | ieee80211_tx_skb(sdata, skb); |
@@ -546,7 +317,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
546 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); | 317 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); |
547 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 318 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
548 | 319 | ||
549 | if (!netif_running(sdata->dev)) | 320 | if (!ieee80211_sdata_running(sdata)) |
550 | return; | 321 | return; |
551 | 322 | ||
552 | mutex_lock(&ifmgd->mtx); | 323 | mutex_lock(&ifmgd->mtx); |
@@ -557,7 +328,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
557 | ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL); | 328 | ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL); |
558 | 329 | ||
559 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 330 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
560 | ifmgd->associated->cbss.channel = sdata->local->oper_channel; | 331 | ifmgd->associated->channel = sdata->local->oper_channel; |
561 | 332 | ||
562 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 333 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
563 | IEEE80211_QUEUE_STOP_REASON_CSA); | 334 | IEEE80211_QUEUE_STOP_REASON_CSA); |
@@ -584,6 +355,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
584 | struct ieee80211_channel_sw_ie *sw_elem, | 355 | struct ieee80211_channel_sw_ie *sw_elem, |
585 | struct ieee80211_bss *bss) | 356 | struct ieee80211_bss *bss) |
586 | { | 357 | { |
358 | struct cfg80211_bss *cbss = | ||
359 | container_of((void *)bss, struct cfg80211_bss, priv); | ||
587 | struct ieee80211_channel *new_ch; | 360 | struct ieee80211_channel *new_ch; |
588 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 361 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
589 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); | 362 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); |
@@ -617,7 +390,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
617 | mod_timer(&ifmgd->chswitch_timer, | 390 | mod_timer(&ifmgd->chswitch_timer, |
618 | jiffies + | 391 | jiffies + |
619 | msecs_to_jiffies(sw_elem->count * | 392 | msecs_to_jiffies(sw_elem->count * |
620 | bss->cbss.beacon_interval)); | 393 | cbss->beacon_interval)); |
621 | } | 394 | } |
622 | } | 395 | } |
623 | 396 | ||
@@ -661,8 +434,11 @@ static void ieee80211_enable_ps(struct ieee80211_local *local, | |||
661 | } else { | 434 | } else { |
662 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | 435 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) |
663 | ieee80211_send_nullfunc(local, sdata, 1); | 436 | ieee80211_send_nullfunc(local, sdata, 1); |
664 | conf->flags |= IEEE80211_CONF_PS; | 437 | |
665 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 438 | if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { |
439 | conf->flags |= IEEE80211_CONF_PS; | ||
440 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
441 | } | ||
666 | } | 442 | } |
667 | } | 443 | } |
668 | 444 | ||
@@ -691,8 +467,13 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
691 | return; | 467 | return; |
692 | } | 468 | } |
693 | 469 | ||
470 | if (!list_empty(&local->work_list)) { | ||
471 | local->ps_sdata = NULL; | ||
472 | goto change; | ||
473 | } | ||
474 | |||
694 | list_for_each_entry(sdata, &local->interfaces, list) { | 475 | list_for_each_entry(sdata, &local->interfaces, list) { |
695 | if (!netif_running(sdata->dev)) | 476 | if (!ieee80211_sdata_running(sdata)) |
696 | continue; | 477 | continue; |
697 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 478 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
698 | continue; | 479 | continue; |
@@ -701,7 +482,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
701 | } | 482 | } |
702 | 483 | ||
703 | if (count == 1 && found->u.mgd.powersave && | 484 | if (count == 1 && found->u.mgd.powersave && |
704 | found->u.mgd.associated && list_empty(&found->u.mgd.work_list) && | 485 | found->u.mgd.associated && |
486 | found->u.mgd.associated->beacon_ies && | ||
705 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | | 487 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | |
706 | IEEE80211_STA_CONNECTION_POLL))) { | 488 | IEEE80211_STA_CONNECTION_POLL))) { |
707 | s32 beaconint_us; | 489 | s32 beaconint_us; |
@@ -715,20 +497,29 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
715 | if (beaconint_us > latency) { | 497 | if (beaconint_us > latency) { |
716 | local->ps_sdata = NULL; | 498 | local->ps_sdata = NULL; |
717 | } else { | 499 | } else { |
718 | u8 dtimper = found->vif.bss_conf.dtim_period; | 500 | struct ieee80211_bss *bss; |
719 | int maxslp = 1; | 501 | int maxslp = 1; |
502 | u8 dtimper; | ||
503 | |||
504 | bss = (void *)found->u.mgd.associated->priv; | ||
505 | dtimper = bss->dtim_period; | ||
720 | 506 | ||
721 | if (dtimper > 1) | 507 | /* If the TIM IE is invalid, pretend the value is 1 */ |
508 | if (!dtimper) | ||
509 | dtimper = 1; | ||
510 | else if (dtimper > 1) | ||
722 | maxslp = min_t(int, dtimper, | 511 | maxslp = min_t(int, dtimper, |
723 | latency / beaconint_us); | 512 | latency / beaconint_us); |
724 | 513 | ||
725 | local->hw.conf.max_sleep_period = maxslp; | 514 | local->hw.conf.max_sleep_period = maxslp; |
515 | local->hw.conf.ps_dtim_period = dtimper; | ||
726 | local->ps_sdata = found; | 516 | local->ps_sdata = found; |
727 | } | 517 | } |
728 | } else { | 518 | } else { |
729 | local->ps_sdata = NULL; | 519 | local->ps_sdata = NULL; |
730 | } | 520 | } |
731 | 521 | ||
522 | change: | ||
732 | ieee80211_change_ps(local); | 523 | ieee80211_change_ps(local); |
733 | } | 524 | } |
734 | 525 | ||
@@ -753,6 +544,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
753 | container_of(work, struct ieee80211_local, | 544 | container_of(work, struct ieee80211_local, |
754 | dynamic_ps_enable_work); | 545 | dynamic_ps_enable_work); |
755 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; | 546 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; |
547 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
756 | 548 | ||
757 | /* can only happen when PS was just disabled anyway */ | 549 | /* can only happen when PS was just disabled anyway */ |
758 | if (!sdata) | 550 | if (!sdata) |
@@ -761,11 +553,16 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
761 | if (local->hw.conf.flags & IEEE80211_CONF_PS) | 553 | if (local->hw.conf.flags & IEEE80211_CONF_PS) |
762 | return; | 554 | return; |
763 | 555 | ||
764 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | 556 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
557 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) | ||
765 | ieee80211_send_nullfunc(local, sdata, 1); | 558 | ieee80211_send_nullfunc(local, sdata, 1); |
766 | 559 | ||
767 | local->hw.conf.flags |= IEEE80211_CONF_PS; | 560 | if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) || |
768 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 561 | (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { |
562 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | ||
563 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
564 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
565 | } | ||
769 | } | 566 | } |
770 | 567 | ||
771 | void ieee80211_dynamic_ps_timer(unsigned long data) | 568 | void ieee80211_dynamic_ps_timer(unsigned long data) |
@@ -786,9 +583,9 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
786 | struct ieee80211_tx_queue_params params; | 583 | struct ieee80211_tx_queue_params params; |
787 | size_t left; | 584 | size_t left; |
788 | int count; | 585 | int count; |
789 | u8 *pos; | 586 | u8 *pos, uapsd_queues = 0; |
790 | 587 | ||
791 | if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) | 588 | if (local->hw.queues < 4) |
792 | return; | 589 | return; |
793 | 590 | ||
794 | if (!wmm_param) | 591 | if (!wmm_param) |
@@ -796,6 +593,10 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
796 | 593 | ||
797 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) | 594 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) |
798 | return; | 595 | return; |
596 | |||
597 | if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) | ||
598 | uapsd_queues = local->uapsd_queues; | ||
599 | |||
799 | count = wmm_param[6] & 0x0f; | 600 | count = wmm_param[6] & 0x0f; |
800 | if (count == ifmgd->wmm_last_param_set) | 601 | if (count == ifmgd->wmm_last_param_set) |
801 | return; | 602 | return; |
@@ -810,6 +611,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
810 | for (; left >= 4; left -= 4, pos += 4) { | 611 | for (; left >= 4; left -= 4, pos += 4) { |
811 | int aci = (pos[0] >> 5) & 0x03; | 612 | int aci = (pos[0] >> 5) & 0x03; |
812 | int acm = (pos[0] >> 4) & 0x01; | 613 | int acm = (pos[0] >> 4) & 0x01; |
614 | bool uapsd = false; | ||
813 | int queue; | 615 | int queue; |
814 | 616 | ||
815 | switch (aci) { | 617 | switch (aci) { |
@@ -817,22 +619,30 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
817 | queue = 3; | 619 | queue = 3; |
818 | if (acm) | 620 | if (acm) |
819 | local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ | 621 | local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ |
622 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) | ||
623 | uapsd = true; | ||
820 | break; | 624 | break; |
821 | case 2: /* AC_VI */ | 625 | case 2: /* AC_VI */ |
822 | queue = 1; | 626 | queue = 1; |
823 | if (acm) | 627 | if (acm) |
824 | local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ | 628 | local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ |
629 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) | ||
630 | uapsd = true; | ||
825 | break; | 631 | break; |
826 | case 3: /* AC_VO */ | 632 | case 3: /* AC_VO */ |
827 | queue = 0; | 633 | queue = 0; |
828 | if (acm) | 634 | if (acm) |
829 | local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ | 635 | local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ |
636 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) | ||
637 | uapsd = true; | ||
830 | break; | 638 | break; |
831 | case 0: /* AC_BE */ | 639 | case 0: /* AC_BE */ |
832 | default: | 640 | default: |
833 | queue = 2; | 641 | queue = 2; |
834 | if (acm) | 642 | if (acm) |
835 | local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ | 643 | local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ |
644 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) | ||
645 | uapsd = true; | ||
836 | break; | 646 | break; |
837 | } | 647 | } |
838 | 648 | ||
@@ -840,11 +650,14 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
840 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); | 650 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); |
841 | params.cw_min = ecw2cw(pos[1] & 0x0f); | 651 | params.cw_min = ecw2cw(pos[1] & 0x0f); |
842 | params.txop = get_unaligned_le16(pos + 2); | 652 | params.txop = get_unaligned_le16(pos + 2); |
653 | params.uapsd = uapsd; | ||
654 | |||
843 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 655 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
844 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " | 656 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " |
845 | "cWmin=%d cWmax=%d txop=%d\n", | 657 | "cWmin=%d cWmax=%d txop=%d uapsd=%d\n", |
846 | wiphy_name(local->hw.wiphy), queue, aci, acm, | 658 | wiphy_name(local->hw.wiphy), queue, aci, acm, |
847 | params.aifs, params.cw_min, params.cw_max, params.txop); | 659 | params.aifs, params.cw_min, params.cw_max, params.txop, |
660 | params.uapsd); | ||
848 | #endif | 661 | #endif |
849 | if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx) | 662 | if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx) |
850 | printk(KERN_DEBUG "%s: failed to set TX queue " | 663 | printk(KERN_DEBUG "%s: failed to set TX queue " |
@@ -871,6 +684,8 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | |||
871 | } | 684 | } |
872 | 685 | ||
873 | use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); | 686 | use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); |
687 | if (sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) | ||
688 | use_short_slot = true; | ||
874 | 689 | ||
875 | if (use_protection != bss_conf->use_cts_prot) { | 690 | if (use_protection != bss_conf->use_cts_prot) { |
876 | bss_conf->use_cts_prot = use_protection; | 691 | bss_conf->use_cts_prot = use_protection; |
@@ -891,25 +706,23 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | |||
891 | } | 706 | } |
892 | 707 | ||
893 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | 708 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, |
894 | struct ieee80211_mgd_work *wk, | 709 | struct cfg80211_bss *cbss, |
895 | u32 bss_info_changed) | 710 | u32 bss_info_changed) |
896 | { | 711 | { |
712 | struct ieee80211_bss *bss = (void *)cbss->priv; | ||
897 | struct ieee80211_local *local = sdata->local; | 713 | struct ieee80211_local *local = sdata->local; |
898 | struct ieee80211_bss *bss = wk->bss; | ||
899 | 714 | ||
900 | bss_info_changed |= BSS_CHANGED_ASSOC; | 715 | bss_info_changed |= BSS_CHANGED_ASSOC; |
901 | /* set timing information */ | 716 | /* set timing information */ |
902 | sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval; | 717 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; |
903 | sdata->vif.bss_conf.timestamp = bss->cbss.tsf; | 718 | sdata->vif.bss_conf.timestamp = cbss->tsf; |
904 | sdata->vif.bss_conf.dtim_period = bss->dtim_period; | ||
905 | 719 | ||
906 | bss_info_changed |= BSS_CHANGED_BEACON_INT; | 720 | bss_info_changed |= BSS_CHANGED_BEACON_INT; |
907 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 721 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
908 | bss->cbss.capability, bss->has_erp_value, bss->erp_value); | 722 | cbss->capability, bss->has_erp_value, bss->erp_value); |
909 | 723 | ||
910 | sdata->u.mgd.associated = bss; | 724 | sdata->u.mgd.associated = cbss; |
911 | sdata->u.mgd.old_associate_work = wk; | 725 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
912 | memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); | ||
913 | 726 | ||
914 | /* just to be sure */ | 727 | /* just to be sure */ |
915 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 728 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
@@ -940,99 +753,14 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
940 | 753 | ||
941 | mutex_lock(&local->iflist_mtx); | 754 | mutex_lock(&local->iflist_mtx); |
942 | ieee80211_recalc_ps(local, -1); | 755 | ieee80211_recalc_ps(local, -1); |
756 | ieee80211_recalc_smps(local, sdata); | ||
943 | mutex_unlock(&local->iflist_mtx); | 757 | mutex_unlock(&local->iflist_mtx); |
944 | 758 | ||
945 | netif_tx_start_all_queues(sdata->dev); | 759 | netif_tx_start_all_queues(sdata->dev); |
946 | netif_carrier_on(sdata->dev); | 760 | netif_carrier_on(sdata->dev); |
947 | } | 761 | } |
948 | 762 | ||
949 | static enum rx_mgmt_action __must_check | 763 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) |
950 | ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | ||
951 | struct ieee80211_mgd_work *wk) | ||
952 | { | ||
953 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
954 | struct ieee80211_local *local = sdata->local; | ||
955 | |||
956 | wk->tries++; | ||
957 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { | ||
958 | printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", | ||
959 | sdata->dev->name, wk->bss->cbss.bssid); | ||
960 | |||
961 | /* | ||
962 | * Most likely AP is not in the range so remove the | ||
963 | * bss struct for that AP. | ||
964 | */ | ||
965 | cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); | ||
966 | |||
967 | /* | ||
968 | * We might have a pending scan which had no chance to run yet | ||
969 | * due to work needing to be done. Hence, queue the STAs work | ||
970 | * again for that. | ||
971 | */ | ||
972 | ieee80211_queue_work(&local->hw, &ifmgd->work); | ||
973 | return RX_MGMT_CFG80211_AUTH_TO; | ||
974 | } | ||
975 | |||
976 | printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", | ||
977 | sdata->dev->name, wk->bss->cbss.bssid, | ||
978 | wk->tries); | ||
979 | |||
980 | /* | ||
981 | * Direct probe is sent to broadcast address as some APs | ||
982 | * will not answer to direct packet in unassociated state. | ||
983 | */ | ||
984 | ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); | ||
985 | |||
986 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
987 | run_again(ifmgd, wk->timeout); | ||
988 | |||
989 | return RX_MGMT_NONE; | ||
990 | } | ||
991 | |||
992 | |||
993 | static enum rx_mgmt_action __must_check | ||
994 | ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | ||
995 | struct ieee80211_mgd_work *wk) | ||
996 | { | ||
997 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
998 | struct ieee80211_local *local = sdata->local; | ||
999 | |||
1000 | wk->tries++; | ||
1001 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { | ||
1002 | printk(KERN_DEBUG "%s: authentication with AP %pM" | ||
1003 | " timed out\n", | ||
1004 | sdata->dev->name, wk->bss->cbss.bssid); | ||
1005 | |||
1006 | /* | ||
1007 | * Most likely AP is not in the range so remove the | ||
1008 | * bss struct for that AP. | ||
1009 | */ | ||
1010 | cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); | ||
1011 | |||
1012 | /* | ||
1013 | * We might have a pending scan which had no chance to run yet | ||
1014 | * due to work needing to be done. Hence, queue the STAs work | ||
1015 | * again for that. | ||
1016 | */ | ||
1017 | ieee80211_queue_work(&local->hw, &ifmgd->work); | ||
1018 | return RX_MGMT_CFG80211_AUTH_TO; | ||
1019 | } | ||
1020 | |||
1021 | printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", | ||
1022 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); | ||
1023 | |||
1024 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, | ||
1025 | wk->bss->cbss.bssid, NULL, 0, 0); | ||
1026 | wk->auth_transaction = 2; | ||
1027 | |||
1028 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
1029 | run_again(ifmgd, wk->timeout); | ||
1030 | |||
1031 | return RX_MGMT_NONE; | ||
1032 | } | ||
1033 | |||
1034 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | ||
1035 | bool deauth) | ||
1036 | { | 764 | { |
1037 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 765 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1038 | struct ieee80211_local *local = sdata->local; | 766 | struct ieee80211_local *local = sdata->local; |
@@ -1045,21 +773,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1045 | if (WARN_ON(!ifmgd->associated)) | 773 | if (WARN_ON(!ifmgd->associated)) |
1046 | return; | 774 | return; |
1047 | 775 | ||
1048 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | 776 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1049 | 777 | ||
1050 | ifmgd->associated = NULL; | 778 | ifmgd->associated = NULL; |
1051 | memset(ifmgd->bssid, 0, ETH_ALEN); | 779 | memset(ifmgd->bssid, 0, ETH_ALEN); |
1052 | 780 | ||
1053 | if (deauth) { | ||
1054 | kfree(ifmgd->old_associate_work); | ||
1055 | ifmgd->old_associate_work = NULL; | ||
1056 | } else { | ||
1057 | struct ieee80211_mgd_work *wk = ifmgd->old_associate_work; | ||
1058 | |||
1059 | wk->state = IEEE80211_MGD_STATE_IDLE; | ||
1060 | list_add(&wk->list, &ifmgd->work_list); | ||
1061 | } | ||
1062 | |||
1063 | /* | 781 | /* |
1064 | * we need to commit the associated = NULL change because the | 782 | * we need to commit the associated = NULL change because the |
1065 | * scan code uses that to determine whether this iface should | 783 | * scan code uses that to determine whether this iface should |
@@ -1078,9 +796,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1078 | netif_carrier_off(sdata->dev); | 796 | netif_carrier_off(sdata->dev); |
1079 | 797 | ||
1080 | rcu_read_lock(); | 798 | rcu_read_lock(); |
1081 | sta = sta_info_get(local, bssid); | 799 | sta = sta_info_get(sdata, bssid); |
1082 | if (sta) | 800 | if (sta) { |
801 | set_sta_flags(sta, WLAN_STA_DISASSOC); | ||
1083 | ieee80211_sta_tear_down_BA_sessions(sta); | 802 | ieee80211_sta_tear_down_BA_sessions(sta); |
803 | } | ||
1084 | rcu_read_unlock(); | 804 | rcu_read_unlock(); |
1085 | 805 | ||
1086 | changed |= ieee80211_reset_erp_info(sdata); | 806 | changed |= ieee80211_reset_erp_info(sdata); |
@@ -1113,57 +833,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1113 | changed |= BSS_CHANGED_BSSID; | 833 | changed |= BSS_CHANGED_BSSID; |
1114 | ieee80211_bss_info_change_notify(sdata, changed); | 834 | ieee80211_bss_info_change_notify(sdata, changed); |
1115 | 835 | ||
1116 | rcu_read_lock(); | 836 | sta_info_destroy_addr(sdata, bssid); |
1117 | |||
1118 | sta = sta_info_get(local, bssid); | ||
1119 | if (!sta) { | ||
1120 | rcu_read_unlock(); | ||
1121 | return; | ||
1122 | } | ||
1123 | |||
1124 | sta_info_unlink(&sta); | ||
1125 | |||
1126 | rcu_read_unlock(); | ||
1127 | |||
1128 | sta_info_destroy(sta); | ||
1129 | } | ||
1130 | |||
1131 | static enum rx_mgmt_action __must_check | ||
1132 | ieee80211_associate(struct ieee80211_sub_if_data *sdata, | ||
1133 | struct ieee80211_mgd_work *wk) | ||
1134 | { | ||
1135 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1136 | struct ieee80211_local *local = sdata->local; | ||
1137 | |||
1138 | wk->tries++; | ||
1139 | if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) { | ||
1140 | printk(KERN_DEBUG "%s: association with AP %pM" | ||
1141 | " timed out\n", | ||
1142 | sdata->dev->name, wk->bss->cbss.bssid); | ||
1143 | |||
1144 | /* | ||
1145 | * Most likely AP is not in the range so remove the | ||
1146 | * bss struct for that AP. | ||
1147 | */ | ||
1148 | cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); | ||
1149 | |||
1150 | /* | ||
1151 | * We might have a pending scan which had no chance to run yet | ||
1152 | * due to work needing to be done. Hence, queue the STAs work | ||
1153 | * again for that. | ||
1154 | */ | ||
1155 | ieee80211_queue_work(&local->hw, &ifmgd->work); | ||
1156 | return RX_MGMT_CFG80211_ASSOC_TO; | ||
1157 | } | ||
1158 | |||
1159 | printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", | ||
1160 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); | ||
1161 | ieee80211_send_assoc(sdata, wk); | ||
1162 | |||
1163 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | ||
1164 | run_again(ifmgd, wk->timeout); | ||
1165 | |||
1166 | return RX_MGMT_NONE; | ||
1167 | } | 837 | } |
1168 | 838 | ||
1169 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 839 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -1189,8 +859,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1189 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 859 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1190 | const u8 *ssid; | 860 | const u8 *ssid; |
1191 | 861 | ||
1192 | ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID); | 862 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1193 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, | 863 | ieee80211_send_probe_req(sdata, ifmgd->associated->bssid, |
1194 | ssid + 2, ssid[1], NULL, 0); | 864 | ssid + 2, ssid[1], NULL, 0); |
1195 | 865 | ||
1196 | ifmgd->probe_send_count++; | 866 | ifmgd->probe_send_count++; |
@@ -1204,12 +874,15 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1204 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 874 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1205 | bool already = false; | 875 | bool already = false; |
1206 | 876 | ||
1207 | if (!netif_running(sdata->dev)) | 877 | if (!ieee80211_sdata_running(sdata)) |
1208 | return; | 878 | return; |
1209 | 879 | ||
1210 | if (sdata->local->scanning) | 880 | if (sdata->local->scanning) |
1211 | return; | 881 | return; |
1212 | 882 | ||
883 | if (sdata->local->tmp_channel) | ||
884 | return; | ||
885 | |||
1213 | mutex_lock(&ifmgd->mtx); | 886 | mutex_lock(&ifmgd->mtx); |
1214 | 887 | ||
1215 | if (!ifmgd->associated) | 888 | if (!ifmgd->associated) |
@@ -1218,7 +891,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1218 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 891 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1219 | if (beacon && net_ratelimit()) | 892 | if (beacon && net_ratelimit()) |
1220 | printk(KERN_DEBUG "%s: detected beacon loss from AP " | 893 | printk(KERN_DEBUG "%s: detected beacon loss from AP " |
1221 | "- sending probe request\n", sdata->dev->name); | 894 | "- sending probe request\n", sdata->name); |
1222 | #endif | 895 | #endif |
1223 | 896 | ||
1224 | /* | 897 | /* |
@@ -1271,88 +944,8 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif) | |||
1271 | } | 944 | } |
1272 | EXPORT_SYMBOL(ieee80211_beacon_loss); | 945 | EXPORT_SYMBOL(ieee80211_beacon_loss); |
1273 | 946 | ||
1274 | static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, | ||
1275 | struct ieee80211_mgd_work *wk) | ||
1276 | { | ||
1277 | wk->state = IEEE80211_MGD_STATE_IDLE; | ||
1278 | printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | ||
1283 | struct ieee80211_mgd_work *wk, | ||
1284 | struct ieee80211_mgmt *mgmt, | ||
1285 | size_t len) | ||
1286 | { | ||
1287 | u8 *pos; | ||
1288 | struct ieee802_11_elems elems; | ||
1289 | |||
1290 | pos = mgmt->u.auth.variable; | ||
1291 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1292 | if (!elems.challenge) | ||
1293 | return; | ||
1294 | ieee80211_send_auth(sdata, 3, wk->auth_alg, | ||
1295 | elems.challenge - 2, elems.challenge_len + 2, | ||
1296 | wk->bss->cbss.bssid, | ||
1297 | wk->key, wk->key_len, wk->key_idx); | ||
1298 | wk->auth_transaction = 4; | ||
1299 | } | ||
1300 | |||
1301 | static enum rx_mgmt_action __must_check | ||
1302 | ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | ||
1303 | struct ieee80211_mgd_work *wk, | ||
1304 | struct ieee80211_mgmt *mgmt, size_t len) | ||
1305 | { | ||
1306 | u16 auth_alg, auth_transaction, status_code; | ||
1307 | |||
1308 | if (wk->state != IEEE80211_MGD_STATE_AUTH) | ||
1309 | return RX_MGMT_NONE; | ||
1310 | |||
1311 | if (len < 24 + 6) | ||
1312 | return RX_MGMT_NONE; | ||
1313 | |||
1314 | if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0) | ||
1315 | return RX_MGMT_NONE; | ||
1316 | |||
1317 | if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0) | ||
1318 | return RX_MGMT_NONE; | ||
1319 | |||
1320 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | ||
1321 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | ||
1322 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | ||
1323 | |||
1324 | if (auth_alg != wk->auth_alg || | ||
1325 | auth_transaction != wk->auth_transaction) | ||
1326 | return RX_MGMT_NONE; | ||
1327 | |||
1328 | if (status_code != WLAN_STATUS_SUCCESS) { | ||
1329 | list_del(&wk->list); | ||
1330 | kfree(wk); | ||
1331 | return RX_MGMT_CFG80211_AUTH; | ||
1332 | } | ||
1333 | |||
1334 | switch (wk->auth_alg) { | ||
1335 | case WLAN_AUTH_OPEN: | ||
1336 | case WLAN_AUTH_LEAP: | ||
1337 | case WLAN_AUTH_FT: | ||
1338 | ieee80211_auth_completed(sdata, wk); | ||
1339 | return RX_MGMT_CFG80211_AUTH; | ||
1340 | case WLAN_AUTH_SHARED_KEY: | ||
1341 | if (wk->auth_transaction == 4) { | ||
1342 | ieee80211_auth_completed(sdata, wk); | ||
1343 | return RX_MGMT_CFG80211_AUTH; | ||
1344 | } else | ||
1345 | ieee80211_auth_challenge(sdata, wk, mgmt, len); | ||
1346 | break; | ||
1347 | } | ||
1348 | |||
1349 | return RX_MGMT_NONE; | ||
1350 | } | ||
1351 | |||
1352 | |||
1353 | static enum rx_mgmt_action __must_check | 947 | static enum rx_mgmt_action __must_check |
1354 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | 948 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
1355 | struct ieee80211_mgd_work *wk, | ||
1356 | struct ieee80211_mgmt *mgmt, size_t len) | 949 | struct ieee80211_mgmt *mgmt, size_t len) |
1357 | { | 950 | { |
1358 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 951 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -1364,23 +957,15 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1364 | 957 | ||
1365 | ASSERT_MGD_MTX(ifmgd); | 958 | ASSERT_MGD_MTX(ifmgd); |
1366 | 959 | ||
1367 | if (wk) | 960 | bssid = ifmgd->associated->bssid; |
1368 | bssid = wk->bss->cbss.bssid; | ||
1369 | else | ||
1370 | bssid = ifmgd->associated->cbss.bssid; | ||
1371 | 961 | ||
1372 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 962 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1373 | 963 | ||
1374 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 964 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
1375 | sdata->dev->name, bssid, reason_code); | 965 | sdata->name, bssid, reason_code); |
1376 | 966 | ||
1377 | if (!wk) { | 967 | ieee80211_set_disassoc(sdata); |
1378 | ieee80211_set_disassoc(sdata, true); | 968 | ieee80211_recalc_idle(sdata->local); |
1379 | ieee80211_recalc_idle(sdata->local); | ||
1380 | } else { | ||
1381 | list_del(&wk->list); | ||
1382 | kfree(wk); | ||
1383 | } | ||
1384 | 969 | ||
1385 | return RX_MGMT_CFG80211_DEAUTH; | 970 | return RX_MGMT_CFG80211_DEAUTH; |
1386 | } | 971 | } |
@@ -1401,123 +986,72 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1401 | if (WARN_ON(!ifmgd->associated)) | 986 | if (WARN_ON(!ifmgd->associated)) |
1402 | return RX_MGMT_NONE; | 987 | return RX_MGMT_NONE; |
1403 | 988 | ||
1404 | if (WARN_ON(memcmp(ifmgd->associated->cbss.bssid, mgmt->sa, ETH_ALEN))) | 989 | if (WARN_ON(memcmp(ifmgd->associated->bssid, mgmt->sa, ETH_ALEN))) |
1405 | return RX_MGMT_NONE; | 990 | return RX_MGMT_NONE; |
1406 | 991 | ||
1407 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 992 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
1408 | 993 | ||
1409 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 994 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
1410 | sdata->dev->name, mgmt->sa, reason_code); | 995 | sdata->name, mgmt->sa, reason_code); |
1411 | 996 | ||
1412 | ieee80211_set_disassoc(sdata, false); | 997 | ieee80211_set_disassoc(sdata); |
1413 | ieee80211_recalc_idle(sdata->local); | 998 | ieee80211_recalc_idle(sdata->local); |
1414 | return RX_MGMT_CFG80211_DISASSOC; | 999 | return RX_MGMT_CFG80211_DISASSOC; |
1415 | } | 1000 | } |
1416 | 1001 | ||
1417 | 1002 | ||
1418 | static enum rx_mgmt_action __must_check | 1003 | static bool ieee80211_assoc_success(struct ieee80211_work *wk, |
1419 | ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | 1004 | struct ieee80211_mgmt *mgmt, size_t len) |
1420 | struct ieee80211_mgd_work *wk, | ||
1421 | struct ieee80211_mgmt *mgmt, size_t len, | ||
1422 | bool reassoc) | ||
1423 | { | 1005 | { |
1006 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
1424 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1007 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1425 | struct ieee80211_local *local = sdata->local; | 1008 | struct ieee80211_local *local = sdata->local; |
1426 | struct ieee80211_supported_band *sband; | 1009 | struct ieee80211_supported_band *sband; |
1427 | struct sta_info *sta; | 1010 | struct sta_info *sta; |
1011 | struct cfg80211_bss *cbss = wk->assoc.bss; | ||
1012 | u8 *pos; | ||
1428 | u32 rates, basic_rates; | 1013 | u32 rates, basic_rates; |
1429 | u16 capab_info, status_code, aid; | 1014 | u16 capab_info, aid; |
1430 | struct ieee802_11_elems elems; | 1015 | struct ieee802_11_elems elems; |
1431 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 1016 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
1432 | u8 *pos; | ||
1433 | u32 changed = 0; | 1017 | u32 changed = 0; |
1434 | int i, j; | 1018 | int i, j, err; |
1435 | bool have_higher_than_11mbit = false, newsta = false; | 1019 | bool have_higher_than_11mbit = false; |
1436 | u16 ap_ht_cap_flags; | 1020 | u16 ap_ht_cap_flags; |
1437 | 1021 | ||
1438 | /* | 1022 | /* AssocResp and ReassocResp have identical structure */ |
1439 | * AssocResp and ReassocResp have identical structure, so process both | ||
1440 | * of them in this function. | ||
1441 | */ | ||
1442 | |||
1443 | if (len < 24 + 6) | ||
1444 | return RX_MGMT_NONE; | ||
1445 | |||
1446 | if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0) | ||
1447 | return RX_MGMT_NONE; | ||
1448 | 1023 | ||
1449 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | ||
1450 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | ||
1451 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | 1024 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); |
1452 | 1025 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | |
1453 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | ||
1454 | "status=%d aid=%d)\n", | ||
1455 | sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa, | ||
1456 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | ||
1457 | |||
1458 | pos = mgmt->u.assoc_resp.variable; | ||
1459 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1460 | |||
1461 | if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && | ||
1462 | elems.timeout_int && elems.timeout_int_len == 5 && | ||
1463 | elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { | ||
1464 | u32 tu, ms; | ||
1465 | tu = get_unaligned_le32(elems.timeout_int + 1); | ||
1466 | ms = tu * 1024 / 1000; | ||
1467 | printk(KERN_DEBUG "%s: AP rejected association temporarily; " | ||
1468 | "comeback duration %u TU (%u ms)\n", | ||
1469 | sdata->dev->name, tu, ms); | ||
1470 | wk->timeout = jiffies + msecs_to_jiffies(ms); | ||
1471 | if (ms > IEEE80211_ASSOC_TIMEOUT) | ||
1472 | run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); | ||
1473 | return RX_MGMT_NONE; | ||
1474 | } | ||
1475 | |||
1476 | if (status_code != WLAN_STATUS_SUCCESS) { | ||
1477 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", | ||
1478 | sdata->dev->name, status_code); | ||
1479 | wk->state = IEEE80211_MGD_STATE_IDLE; | ||
1480 | return RX_MGMT_CFG80211_ASSOC; | ||
1481 | } | ||
1482 | 1026 | ||
1483 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1027 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
1484 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " | 1028 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " |
1485 | "set\n", sdata->dev->name, aid); | 1029 | "set\n", sdata->name, aid); |
1486 | aid &= ~(BIT(15) | BIT(14)); | 1030 | aid &= ~(BIT(15) | BIT(14)); |
1487 | 1031 | ||
1032 | pos = mgmt->u.assoc_resp.variable; | ||
1033 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1034 | |||
1488 | if (!elems.supp_rates) { | 1035 | if (!elems.supp_rates) { |
1489 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 1036 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", |
1490 | sdata->dev->name); | 1037 | sdata->name); |
1491 | return RX_MGMT_NONE; | 1038 | return false; |
1492 | } | 1039 | } |
1493 | 1040 | ||
1494 | printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); | ||
1495 | ifmgd->aid = aid; | 1041 | ifmgd->aid = aid; |
1496 | 1042 | ||
1497 | rcu_read_lock(); | 1043 | sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); |
1498 | |||
1499 | /* Add STA entry for the AP */ | ||
1500 | sta = sta_info_get(local, wk->bss->cbss.bssid); | ||
1501 | if (!sta) { | 1044 | if (!sta) { |
1502 | newsta = true; | 1045 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" |
1503 | 1046 | " the AP\n", sdata->name); | |
1504 | rcu_read_unlock(); | 1047 | return false; |
1505 | |||
1506 | sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); | ||
1507 | if (!sta) { | ||
1508 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" | ||
1509 | " the AP\n", sdata->dev->name); | ||
1510 | return RX_MGMT_NONE; | ||
1511 | } | ||
1512 | |||
1513 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | ||
1514 | WLAN_STA_ASSOC_AP); | ||
1515 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | ||
1516 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | ||
1517 | |||
1518 | rcu_read_lock(); | ||
1519 | } | 1048 | } |
1520 | 1049 | ||
1050 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | ||
1051 | WLAN_STA_ASSOC_AP); | ||
1052 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | ||
1053 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | ||
1054 | |||
1521 | rates = 0; | 1055 | rates = 0; |
1522 | basic_rates = 0; | 1056 | basic_rates = 0; |
1523 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1057 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
@@ -1580,40 +1114,40 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1580 | if (elems.wmm_param) | 1114 | if (elems.wmm_param) |
1581 | set_sta_flags(sta, WLAN_STA_WME); | 1115 | set_sta_flags(sta, WLAN_STA_WME); |
1582 | 1116 | ||
1583 | if (newsta) { | 1117 | err = sta_info_insert(sta); |
1584 | int err = sta_info_insert(sta); | 1118 | sta = NULL; |
1585 | if (err) { | 1119 | if (err) { |
1586 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | 1120 | printk(KERN_DEBUG "%s: failed to insert STA entry for" |
1587 | " the AP (error %d)\n", sdata->dev->name, err); | 1121 | " the AP (error %d)\n", sdata->name, err); |
1588 | rcu_read_unlock(); | 1122 | return false; |
1589 | return RX_MGMT_NONE; | ||
1590 | } | ||
1591 | } | 1123 | } |
1592 | 1124 | ||
1593 | rcu_read_unlock(); | ||
1594 | |||
1595 | if (elems.wmm_param) | 1125 | if (elems.wmm_param) |
1596 | ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, | 1126 | ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, |
1597 | elems.wmm_param_len); | 1127 | elems.wmm_param_len); |
1598 | else | 1128 | else |
1599 | ieee80211_set_wmm_default(sdata); | 1129 | ieee80211_set_wmm_default(sdata); |
1600 | 1130 | ||
1131 | local->oper_channel = wk->chan; | ||
1132 | |||
1601 | if (elems.ht_info_elem && elems.wmm_param && | 1133 | if (elems.ht_info_elem && elems.wmm_param && |
1602 | (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && | 1134 | (sdata->local->hw.queues >= 4) && |
1603 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 1135 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
1604 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 1136 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, |
1605 | wk->bss->cbss.bssid, | 1137 | cbss->bssid, ap_ht_cap_flags); |
1606 | ap_ht_cap_flags); | ||
1607 | |||
1608 | /* delete work item -- must be before set_associated for PS */ | ||
1609 | list_del(&wk->list); | ||
1610 | 1138 | ||
1611 | /* set AID and assoc capability, | 1139 | /* set AID and assoc capability, |
1612 | * ieee80211_set_associated() will tell the driver */ | 1140 | * ieee80211_set_associated() will tell the driver */ |
1613 | bss_conf->aid = aid; | 1141 | bss_conf->aid = aid; |
1614 | bss_conf->assoc_capability = capab_info; | 1142 | bss_conf->assoc_capability = capab_info; |
1615 | /* this will take ownership of wk */ | 1143 | ieee80211_set_associated(sdata, cbss, changed); |
1616 | ieee80211_set_associated(sdata, wk, changed); | 1144 | |
1145 | /* | ||
1146 | * If we're using 4-addr mode, let the AP know that we're | ||
1147 | * doing so, so that it can create the STA VLAN on its side | ||
1148 | */ | ||
1149 | if (ifmgd->use_4addr) | ||
1150 | ieee80211_send_4addr_nullfunc(local, sdata); | ||
1617 | 1151 | ||
1618 | /* | 1152 | /* |
1619 | * Start timer to probe the connection to the AP now. | 1153 | * Start timer to probe the connection to the AP now. |
@@ -1622,7 +1156,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1622 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | 1156 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
1623 | mod_beacon_timer(sdata); | 1157 | mod_beacon_timer(sdata); |
1624 | 1158 | ||
1625 | return RX_MGMT_CFG80211_ASSOC; | 1159 | return true; |
1626 | } | 1160 | } |
1627 | 1161 | ||
1628 | 1162 | ||
@@ -1637,6 +1171,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1637 | int freq; | 1171 | int freq; |
1638 | struct ieee80211_bss *bss; | 1172 | struct ieee80211_bss *bss; |
1639 | struct ieee80211_channel *channel; | 1173 | struct ieee80211_channel *channel; |
1174 | bool need_ps = false; | ||
1175 | |||
1176 | if (sdata->u.mgd.associated) { | ||
1177 | bss = (void *)sdata->u.mgd.associated->priv; | ||
1178 | /* not previously set so we may need to recalc */ | ||
1179 | need_ps = !bss->dtim_period; | ||
1180 | } | ||
1640 | 1181 | ||
1641 | if (elems->ds_params && elems->ds_params_len == 1) | 1182 | if (elems->ds_params && elems->ds_params_len == 1) |
1642 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); | 1183 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); |
@@ -1656,8 +1197,14 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1656 | if (!sdata->u.mgd.associated) | 1197 | if (!sdata->u.mgd.associated) |
1657 | return; | 1198 | return; |
1658 | 1199 | ||
1200 | if (need_ps) { | ||
1201 | mutex_lock(&local->iflist_mtx); | ||
1202 | ieee80211_recalc_ps(local, -1); | ||
1203 | mutex_unlock(&local->iflist_mtx); | ||
1204 | } | ||
1205 | |||
1659 | if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && | 1206 | if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && |
1660 | (memcmp(mgmt->bssid, sdata->u.mgd.associated->cbss.bssid, | 1207 | (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, |
1661 | ETH_ALEN) == 0)) { | 1208 | ETH_ALEN) == 0)) { |
1662 | struct ieee80211_channel_sw_ie *sw_elem = | 1209 | struct ieee80211_channel_sw_ie *sw_elem = |
1663 | (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; | 1210 | (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; |
@@ -1667,19 +1214,19 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1667 | 1214 | ||
1668 | 1215 | ||
1669 | static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | 1216 | static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, |
1670 | struct ieee80211_mgd_work *wk, | 1217 | struct sk_buff *skb) |
1671 | struct ieee80211_mgmt *mgmt, size_t len, | ||
1672 | struct ieee80211_rx_status *rx_status) | ||
1673 | { | 1218 | { |
1219 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | ||
1674 | struct ieee80211_if_managed *ifmgd; | 1220 | struct ieee80211_if_managed *ifmgd; |
1675 | size_t baselen; | 1221 | struct ieee80211_rx_status *rx_status = (void *) skb->cb; |
1222 | size_t baselen, len = skb->len; | ||
1676 | struct ieee802_11_elems elems; | 1223 | struct ieee802_11_elems elems; |
1677 | 1224 | ||
1678 | ifmgd = &sdata->u.mgd; | 1225 | ifmgd = &sdata->u.mgd; |
1679 | 1226 | ||
1680 | ASSERT_MGD_MTX(ifmgd); | 1227 | ASSERT_MGD_MTX(ifmgd); |
1681 | 1228 | ||
1682 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | 1229 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) |
1683 | return; /* ignore ProbeResp to foreign address */ | 1230 | return; /* ignore ProbeResp to foreign address */ |
1684 | 1231 | ||
1685 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 1232 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
@@ -1691,17 +1238,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1691 | 1238 | ||
1692 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); | 1239 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); |
1693 | 1240 | ||
1694 | /* direct probe may be part of the association flow */ | ||
1695 | if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) { | ||
1696 | printk(KERN_DEBUG "%s: direct probe responded\n", | ||
1697 | sdata->dev->name); | ||
1698 | wk->tries = 0; | ||
1699 | wk->state = IEEE80211_MGD_STATE_AUTH; | ||
1700 | WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE); | ||
1701 | } | ||
1702 | |||
1703 | if (ifmgd->associated && | 1241 | if (ifmgd->associated && |
1704 | memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 && | 1242 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 && |
1705 | ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 1243 | ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
1706 | IEEE80211_STA_CONNECTION_POLL)) { | 1244 | IEEE80211_STA_CONNECTION_POLL)) { |
1707 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 1245 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
@@ -1774,7 +1312,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1774 | if (!ifmgd->associated) | 1312 | if (!ifmgd->associated) |
1775 | return; | 1313 | return; |
1776 | 1314 | ||
1777 | bssid = ifmgd->associated->cbss.bssid; | 1315 | bssid = ifmgd->associated->bssid; |
1778 | 1316 | ||
1779 | /* | 1317 | /* |
1780 | * And in theory even frames from a different AP we were just | 1318 | * And in theory even frames from a different AP we were just |
@@ -1787,7 +1325,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1787 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1325 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1788 | if (net_ratelimit()) { | 1326 | if (net_ratelimit()) { |
1789 | printk(KERN_DEBUG "%s: cancelling probereq poll due " | 1327 | printk(KERN_DEBUG "%s: cancelling probereq poll due " |
1790 | "to a received beacon\n", sdata->dev->name); | 1328 | "to a received beacon\n", sdata->name); |
1791 | } | 1329 | } |
1792 | #endif | 1330 | #endif |
1793 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; | 1331 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; |
@@ -1865,7 +1403,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1865 | 1403 | ||
1866 | rcu_read_lock(); | 1404 | rcu_read_lock(); |
1867 | 1405 | ||
1868 | sta = sta_info_get(local, bssid); | 1406 | sta = sta_info_get(sdata, bssid); |
1869 | if (WARN_ON(!sta)) { | 1407 | if (WARN_ON(!sta)) { |
1870 | rcu_read_unlock(); | 1408 | rcu_read_unlock(); |
1871 | return; | 1409 | return; |
@@ -1913,9 +1451,6 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1913 | switch (fc & IEEE80211_FCTL_STYPE) { | 1451 | switch (fc & IEEE80211_FCTL_STYPE) { |
1914 | case IEEE80211_STYPE_PROBE_RESP: | 1452 | case IEEE80211_STYPE_PROBE_RESP: |
1915 | case IEEE80211_STYPE_BEACON: | 1453 | case IEEE80211_STYPE_BEACON: |
1916 | case IEEE80211_STYPE_AUTH: | ||
1917 | case IEEE80211_STYPE_ASSOC_RESP: | ||
1918 | case IEEE80211_STYPE_REASSOC_RESP: | ||
1919 | case IEEE80211_STYPE_DEAUTH: | 1454 | case IEEE80211_STYPE_DEAUTH: |
1920 | case IEEE80211_STYPE_DISASSOC: | 1455 | case IEEE80211_STYPE_DISASSOC: |
1921 | case IEEE80211_STYPE_ACTION: | 1456 | case IEEE80211_STYPE_ACTION: |
@@ -1933,7 +1468,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1933 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1468 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1934 | struct ieee80211_rx_status *rx_status; | 1469 | struct ieee80211_rx_status *rx_status; |
1935 | struct ieee80211_mgmt *mgmt; | 1470 | struct ieee80211_mgmt *mgmt; |
1936 | struct ieee80211_mgd_work *wk; | ||
1937 | enum rx_mgmt_action rma = RX_MGMT_NONE; | 1471 | enum rx_mgmt_action rma = RX_MGMT_NONE; |
1938 | u16 fc; | 1472 | u16 fc; |
1939 | 1473 | ||
@@ -1944,20 +1478,17 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1944 | mutex_lock(&ifmgd->mtx); | 1478 | mutex_lock(&ifmgd->mtx); |
1945 | 1479 | ||
1946 | if (ifmgd->associated && | 1480 | if (ifmgd->associated && |
1947 | memcmp(ifmgd->associated->cbss.bssid, mgmt->bssid, | 1481 | memcmp(ifmgd->associated->bssid, mgmt->bssid, ETH_ALEN) == 0) { |
1948 | ETH_ALEN) == 0) { | ||
1949 | switch (fc & IEEE80211_FCTL_STYPE) { | 1482 | switch (fc & IEEE80211_FCTL_STYPE) { |
1950 | case IEEE80211_STYPE_BEACON: | 1483 | case IEEE80211_STYPE_BEACON: |
1951 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, | 1484 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, |
1952 | rx_status); | 1485 | rx_status); |
1953 | break; | 1486 | break; |
1954 | case IEEE80211_STYPE_PROBE_RESP: | 1487 | case IEEE80211_STYPE_PROBE_RESP: |
1955 | ieee80211_rx_mgmt_probe_resp(sdata, NULL, mgmt, | 1488 | ieee80211_rx_mgmt_probe_resp(sdata, skb); |
1956 | skb->len, rx_status); | ||
1957 | break; | 1489 | break; |
1958 | case IEEE80211_STYPE_DEAUTH: | 1490 | case IEEE80211_STYPE_DEAUTH: |
1959 | rma = ieee80211_rx_mgmt_deauth(sdata, NULL, | 1491 | rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); |
1960 | mgmt, skb->len); | ||
1961 | break; | 1492 | break; |
1962 | case IEEE80211_STYPE_DISASSOC: | 1493 | case IEEE80211_STYPE_DISASSOC: |
1963 | rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); | 1494 | rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); |
@@ -1968,7 +1499,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1968 | 1499 | ||
1969 | ieee80211_sta_process_chanswitch(sdata, | 1500 | ieee80211_sta_process_chanswitch(sdata, |
1970 | &mgmt->u.action.u.chan_switch.sw_elem, | 1501 | &mgmt->u.action.u.chan_switch.sw_elem, |
1971 | ifmgd->associated); | 1502 | (void *)ifmgd->associated->priv); |
1972 | break; | 1503 | break; |
1973 | } | 1504 | } |
1974 | mutex_unlock(&ifmgd->mtx); | 1505 | mutex_unlock(&ifmgd->mtx); |
@@ -1989,58 +1520,11 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1989 | goto out; | 1520 | goto out; |
1990 | } | 1521 | } |
1991 | 1522 | ||
1992 | list_for_each_entry(wk, &ifmgd->work_list, list) { | ||
1993 | if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0) | ||
1994 | continue; | ||
1995 | |||
1996 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
1997 | case IEEE80211_STYPE_PROBE_RESP: | ||
1998 | ieee80211_rx_mgmt_probe_resp(sdata, wk, mgmt, skb->len, | ||
1999 | rx_status); | ||
2000 | break; | ||
2001 | case IEEE80211_STYPE_AUTH: | ||
2002 | rma = ieee80211_rx_mgmt_auth(sdata, wk, mgmt, skb->len); | ||
2003 | break; | ||
2004 | case IEEE80211_STYPE_ASSOC_RESP: | ||
2005 | rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt, | ||
2006 | skb->len, false); | ||
2007 | break; | ||
2008 | case IEEE80211_STYPE_REASSOC_RESP: | ||
2009 | rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt, | ||
2010 | skb->len, true); | ||
2011 | break; | ||
2012 | case IEEE80211_STYPE_DEAUTH: | ||
2013 | rma = ieee80211_rx_mgmt_deauth(sdata, wk, mgmt, | ||
2014 | skb->len); | ||
2015 | break; | ||
2016 | } | ||
2017 | /* | ||
2018 | * We've processed this frame for that work, so it can't | ||
2019 | * belong to another work struct. | ||
2020 | * NB: this is also required for correctness because the | ||
2021 | * called functions can free 'wk', and for 'rma'! | ||
2022 | */ | ||
2023 | break; | ||
2024 | } | ||
2025 | |||
2026 | mutex_unlock(&ifmgd->mtx); | 1523 | mutex_unlock(&ifmgd->mtx); |
2027 | 1524 | ||
2028 | switch (rma) { | 1525 | if (skb->len >= 24 + 2 /* mgmt + deauth reason */ && |
2029 | case RX_MGMT_NONE: | 1526 | (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) |
2030 | /* no action */ | ||
2031 | break; | ||
2032 | case RX_MGMT_CFG80211_AUTH: | ||
2033 | cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, skb->len); | ||
2034 | break; | ||
2035 | case RX_MGMT_CFG80211_ASSOC: | ||
2036 | cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len); | ||
2037 | break; | ||
2038 | case RX_MGMT_CFG80211_DEAUTH: | ||
2039 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | 1527 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); |
2040 | break; | ||
2041 | default: | ||
2042 | WARN(1, "unexpected: %d", rma); | ||
2043 | } | ||
2044 | 1528 | ||
2045 | out: | 1529 | out: |
2046 | kfree_skb(skb); | 1530 | kfree_skb(skb); |
@@ -2068,12 +1552,8 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2068 | struct ieee80211_local *local = sdata->local; | 1552 | struct ieee80211_local *local = sdata->local; |
2069 | struct ieee80211_if_managed *ifmgd; | 1553 | struct ieee80211_if_managed *ifmgd; |
2070 | struct sk_buff *skb; | 1554 | struct sk_buff *skb; |
2071 | struct ieee80211_mgd_work *wk, *tmp; | ||
2072 | LIST_HEAD(free_work); | ||
2073 | enum rx_mgmt_action rma; | ||
2074 | bool anybusy = false; | ||
2075 | 1555 | ||
2076 | if (!netif_running(sdata->dev)) | 1556 | if (!ieee80211_sdata_running(sdata)) |
2077 | return; | 1557 | return; |
2078 | 1558 | ||
2079 | if (local->scanning) | 1559 | if (local->scanning) |
@@ -2104,7 +1584,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2104 | ifmgd->associated) { | 1584 | ifmgd->associated) { |
2105 | u8 bssid[ETH_ALEN]; | 1585 | u8 bssid[ETH_ALEN]; |
2106 | 1586 | ||
2107 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | 1587 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
2108 | if (time_is_after_jiffies(ifmgd->probe_timeout)) | 1588 | if (time_is_after_jiffies(ifmgd->probe_timeout)) |
2109 | run_again(ifmgd, ifmgd->probe_timeout); | 1589 | run_again(ifmgd, ifmgd->probe_timeout); |
2110 | 1590 | ||
@@ -2126,7 +1606,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2126 | printk(KERN_DEBUG "No probe response from AP %pM" | 1606 | printk(KERN_DEBUG "No probe response from AP %pM" |
2127 | " after %dms, disconnecting.\n", | 1607 | " after %dms, disconnecting.\n", |
2128 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1608 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
2129 | ieee80211_set_disassoc(sdata, true); | 1609 | ieee80211_set_disassoc(sdata); |
2130 | ieee80211_recalc_idle(local); | 1610 | ieee80211_recalc_idle(local); |
2131 | mutex_unlock(&ifmgd->mtx); | 1611 | mutex_unlock(&ifmgd->mtx); |
2132 | /* | 1612 | /* |
@@ -2141,87 +1621,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2141 | } | 1621 | } |
2142 | } | 1622 | } |
2143 | 1623 | ||
2144 | |||
2145 | ieee80211_recalc_idle(local); | ||
2146 | |||
2147 | list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) { | ||
2148 | if (time_is_after_jiffies(wk->timeout)) { | ||
2149 | /* | ||
2150 | * This work item isn't supposed to be worked on | ||
2151 | * right now, but take care to adjust the timer | ||
2152 | * properly. | ||
2153 | */ | ||
2154 | run_again(ifmgd, wk->timeout); | ||
2155 | continue; | ||
2156 | } | ||
2157 | |||
2158 | switch (wk->state) { | ||
2159 | default: | ||
2160 | WARN_ON(1); | ||
2161 | /* fall through */ | ||
2162 | case IEEE80211_MGD_STATE_IDLE: | ||
2163 | /* nothing */ | ||
2164 | rma = RX_MGMT_NONE; | ||
2165 | break; | ||
2166 | case IEEE80211_MGD_STATE_PROBE: | ||
2167 | rma = ieee80211_direct_probe(sdata, wk); | ||
2168 | break; | ||
2169 | case IEEE80211_MGD_STATE_AUTH: | ||
2170 | rma = ieee80211_authenticate(sdata, wk); | ||
2171 | break; | ||
2172 | case IEEE80211_MGD_STATE_ASSOC: | ||
2173 | rma = ieee80211_associate(sdata, wk); | ||
2174 | break; | ||
2175 | } | ||
2176 | |||
2177 | switch (rma) { | ||
2178 | case RX_MGMT_NONE: | ||
2179 | /* no action required */ | ||
2180 | break; | ||
2181 | case RX_MGMT_CFG80211_AUTH_TO: | ||
2182 | case RX_MGMT_CFG80211_ASSOC_TO: | ||
2183 | list_del(&wk->list); | ||
2184 | list_add(&wk->list, &free_work); | ||
2185 | wk->tries = rma; /* small abuse but only local */ | ||
2186 | break; | ||
2187 | default: | ||
2188 | WARN(1, "unexpected: %d", rma); | ||
2189 | } | ||
2190 | } | ||
2191 | |||
2192 | list_for_each_entry(wk, &ifmgd->work_list, list) { | ||
2193 | if (wk->state != IEEE80211_MGD_STATE_IDLE) { | ||
2194 | anybusy = true; | ||
2195 | break; | ||
2196 | } | ||
2197 | } | ||
2198 | if (!anybusy && | ||
2199 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) | ||
2200 | ieee80211_queue_delayed_work(&local->hw, | ||
2201 | &local->scan_work, | ||
2202 | round_jiffies_relative(0)); | ||
2203 | |||
2204 | mutex_unlock(&ifmgd->mtx); | 1624 | mutex_unlock(&ifmgd->mtx); |
2205 | |||
2206 | list_for_each_entry_safe(wk, tmp, &free_work, list) { | ||
2207 | switch (wk->tries) { | ||
2208 | case RX_MGMT_CFG80211_AUTH_TO: | ||
2209 | cfg80211_send_auth_timeout(sdata->dev, | ||
2210 | wk->bss->cbss.bssid); | ||
2211 | break; | ||
2212 | case RX_MGMT_CFG80211_ASSOC_TO: | ||
2213 | cfg80211_send_assoc_timeout(sdata->dev, | ||
2214 | wk->bss->cbss.bssid); | ||
2215 | break; | ||
2216 | default: | ||
2217 | WARN(1, "unexpected: %d", wk->tries); | ||
2218 | } | ||
2219 | |||
2220 | list_del(&wk->list); | ||
2221 | kfree(wk); | ||
2222 | } | ||
2223 | |||
2224 | ieee80211_recalc_idle(local); | ||
2225 | } | 1625 | } |
2226 | 1626 | ||
2227 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) | 1627 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) |
@@ -2330,14 +1730,14 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2330 | (unsigned long) sdata); | 1730 | (unsigned long) sdata); |
2331 | skb_queue_head_init(&ifmgd->skb_queue); | 1731 | skb_queue_head_init(&ifmgd->skb_queue); |
2332 | 1732 | ||
2333 | INIT_LIST_HEAD(&ifmgd->work_list); | ||
2334 | |||
2335 | ifmgd->capab = WLAN_CAPABILITY_ESS; | ||
2336 | ifmgd->flags = 0; | 1733 | ifmgd->flags = 0; |
2337 | if (sdata->local->hw.queues >= 4) | ||
2338 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; | ||
2339 | 1734 | ||
2340 | mutex_init(&ifmgd->mtx); | 1735 | mutex_init(&ifmgd->mtx); |
1736 | |||
1737 | if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) | ||
1738 | ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC; | ||
1739 | else | ||
1740 | ifmgd->req_smps = IEEE80211_SMPS_OFF; | ||
2341 | } | 1741 | } |
2342 | 1742 | ||
2343 | /* scan finished notification */ | 1743 | /* scan finished notification */ |
@@ -2368,12 +1768,34 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
2368 | } | 1768 | } |
2369 | 1769 | ||
2370 | /* config hooks */ | 1770 | /* config hooks */ |
1771 | static enum work_done_result | ||
1772 | ieee80211_probe_auth_done(struct ieee80211_work *wk, | ||
1773 | struct sk_buff *skb) | ||
1774 | { | ||
1775 | if (!skb) { | ||
1776 | cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); | ||
1777 | return WORK_DONE_DESTROY; | ||
1778 | } | ||
1779 | |||
1780 | if (wk->type == IEEE80211_WORK_AUTH) { | ||
1781 | cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); | ||
1782 | return WORK_DONE_DESTROY; | ||
1783 | } | ||
1784 | |||
1785 | mutex_lock(&wk->sdata->u.mgd.mtx); | ||
1786 | ieee80211_rx_mgmt_probe_resp(wk->sdata, skb); | ||
1787 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
1788 | |||
1789 | wk->type = IEEE80211_WORK_AUTH; | ||
1790 | wk->probe_auth.tries = 0; | ||
1791 | return WORK_DONE_REQUEUE; | ||
1792 | } | ||
1793 | |||
2371 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 1794 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
2372 | struct cfg80211_auth_request *req) | 1795 | struct cfg80211_auth_request *req) |
2373 | { | 1796 | { |
2374 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2375 | const u8 *ssid; | 1797 | const u8 *ssid; |
2376 | struct ieee80211_mgd_work *wk; | 1798 | struct ieee80211_work *wk; |
2377 | u16 auth_alg; | 1799 | u16 auth_alg; |
2378 | 1800 | ||
2379 | switch (req->auth_type) { | 1801 | switch (req->auth_type) { |
@@ -2397,7 +1819,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2397 | if (!wk) | 1819 | if (!wk) |
2398 | return -ENOMEM; | 1820 | return -ENOMEM; |
2399 | 1821 | ||
2400 | wk->bss = (void *)req->bss; | 1822 | memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); |
2401 | 1823 | ||
2402 | if (req->ie && req->ie_len) { | 1824 | if (req->ie && req->ie_len) { |
2403 | memcpy(wk->ie, req->ie, req->ie_len); | 1825 | memcpy(wk->ie, req->ie, req->ie_len); |
@@ -2405,68 +1827,83 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2405 | } | 1827 | } |
2406 | 1828 | ||
2407 | if (req->key && req->key_len) { | 1829 | if (req->key && req->key_len) { |
2408 | wk->key_len = req->key_len; | 1830 | wk->probe_auth.key_len = req->key_len; |
2409 | wk->key_idx = req->key_idx; | 1831 | wk->probe_auth.key_idx = req->key_idx; |
2410 | memcpy(wk->key, req->key, req->key_len); | 1832 | memcpy(wk->probe_auth.key, req->key, req->key_len); |
2411 | } | 1833 | } |
2412 | 1834 | ||
2413 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | 1835 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); |
2414 | memcpy(wk->ssid, ssid + 2, ssid[1]); | 1836 | memcpy(wk->probe_auth.ssid, ssid + 2, ssid[1]); |
2415 | wk->ssid_len = ssid[1]; | 1837 | wk->probe_auth.ssid_len = ssid[1]; |
2416 | |||
2417 | wk->state = IEEE80211_MGD_STATE_PROBE; | ||
2418 | wk->auth_alg = auth_alg; | ||
2419 | wk->timeout = jiffies; /* run right away */ | ||
2420 | 1838 | ||
2421 | /* | 1839 | wk->probe_auth.algorithm = auth_alg; |
2422 | * XXX: if still associated need to tell AP that we're going | 1840 | wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; |
2423 | * to sleep and then change channel etc. | ||
2424 | */ | ||
2425 | sdata->local->oper_channel = req->bss->channel; | ||
2426 | ieee80211_hw_config(sdata->local, 0); | ||
2427 | 1841 | ||
2428 | mutex_lock(&ifmgd->mtx); | 1842 | /* if we already have a probe, don't probe again */ |
2429 | list_add(&wk->list, &sdata->u.mgd.work_list); | 1843 | if (req->bss->proberesp_ies) |
2430 | mutex_unlock(&ifmgd->mtx); | 1844 | wk->type = IEEE80211_WORK_AUTH; |
1845 | else | ||
1846 | wk->type = IEEE80211_WORK_DIRECT_PROBE; | ||
1847 | wk->chan = req->bss->channel; | ||
1848 | wk->sdata = sdata; | ||
1849 | wk->done = ieee80211_probe_auth_done; | ||
2431 | 1850 | ||
2432 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work); | 1851 | ieee80211_add_work(wk); |
2433 | return 0; | 1852 | return 0; |
2434 | } | 1853 | } |
2435 | 1854 | ||
2436 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | 1855 | static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, |
2437 | struct cfg80211_assoc_request *req) | 1856 | struct sk_buff *skb) |
2438 | { | 1857 | { |
2439 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1858 | struct ieee80211_mgmt *mgmt; |
2440 | struct ieee80211_mgd_work *wk, *found = NULL; | 1859 | u16 status; |
2441 | int i, err; | ||
2442 | 1860 | ||
2443 | mutex_lock(&ifmgd->mtx); | 1861 | if (!skb) { |
1862 | cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); | ||
1863 | return WORK_DONE_DESTROY; | ||
1864 | } | ||
2444 | 1865 | ||
2445 | list_for_each_entry(wk, &ifmgd->work_list, list) { | 1866 | mgmt = (void *)skb->data; |
2446 | if (&wk->bss->cbss == req->bss && | 1867 | status = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
2447 | wk->state == IEEE80211_MGD_STATE_IDLE) { | 1868 | |
2448 | found = wk; | 1869 | if (status == WLAN_STATUS_SUCCESS) { |
2449 | break; | 1870 | mutex_lock(&wk->sdata->u.mgd.mtx); |
1871 | if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { | ||
1872 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
1873 | /* oops -- internal error -- send timeout for now */ | ||
1874 | cfg80211_send_assoc_timeout(wk->sdata->dev, | ||
1875 | wk->filter_ta); | ||
1876 | return WORK_DONE_DESTROY; | ||
2450 | } | 1877 | } |
1878 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
2451 | } | 1879 | } |
2452 | 1880 | ||
2453 | if (!found) { | 1881 | cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); |
2454 | err = -ENOLINK; | 1882 | return WORK_DONE_DESTROY; |
2455 | goto out; | 1883 | } |
2456 | } | ||
2457 | 1884 | ||
2458 | list_del(&found->list); | 1885 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, |
1886 | struct cfg80211_assoc_request *req) | ||
1887 | { | ||
1888 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1889 | struct ieee80211_bss *bss = (void *)req->bss->priv; | ||
1890 | struct ieee80211_work *wk; | ||
1891 | const u8 *ssid; | ||
1892 | int i; | ||
2459 | 1893 | ||
2460 | wk = krealloc(found, sizeof(*wk) + req->ie_len, GFP_KERNEL); | 1894 | mutex_lock(&ifmgd->mtx); |
2461 | if (!wk) { | 1895 | if (ifmgd->associated) { |
2462 | list_add(&found->list, &ifmgd->work_list); | 1896 | mutex_unlock(&ifmgd->mtx); |
2463 | err = -ENOMEM; | 1897 | return -EALREADY; |
2464 | goto out; | ||
2465 | } | 1898 | } |
1899 | mutex_unlock(&ifmgd->mtx); | ||
2466 | 1900 | ||
2467 | list_add(&wk->list, &ifmgd->work_list); | 1901 | wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); |
1902 | if (!wk) | ||
1903 | return -ENOMEM; | ||
2468 | 1904 | ||
2469 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; | 1905 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; |
1906 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | ||
2470 | 1907 | ||
2471 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) | 1908 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) |
2472 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 1909 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
@@ -2474,8 +1911,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2474 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) | 1911 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) |
2475 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 1912 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
2476 | 1913 | ||
2477 | sdata->local->oper_channel = req->bss->channel; | ||
2478 | ieee80211_hw_config(sdata->local, 0); | ||
2479 | 1914 | ||
2480 | if (req->ie && req->ie_len) { | 1915 | if (req->ie && req->ie_len) { |
2481 | memcpy(wk->ie, req->ie, req->ie_len); | 1916 | memcpy(wk->ie, req->ie, req->ie_len); |
@@ -2483,12 +1918,55 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2483 | } else | 1918 | } else |
2484 | wk->ie_len = 0; | 1919 | wk->ie_len = 0; |
2485 | 1920 | ||
1921 | wk->assoc.bss = req->bss; | ||
1922 | |||
1923 | memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); | ||
1924 | |||
1925 | /* new association always uses requested smps mode */ | ||
1926 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { | ||
1927 | if (ifmgd->powersave) | ||
1928 | ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; | ||
1929 | else | ||
1930 | ifmgd->ap_smps = IEEE80211_SMPS_OFF; | ||
1931 | } else | ||
1932 | ifmgd->ap_smps = ifmgd->req_smps; | ||
1933 | |||
1934 | wk->assoc.smps = ifmgd->ap_smps; | ||
1935 | /* | ||
1936 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. | ||
1937 | * We still associate in non-HT mode (11a/b/g) if any one of these | ||
1938 | * ciphers is configured as pairwise. | ||
1939 | * We can set this to true for non-11n hardware, that'll be checked | ||
1940 | * separately along with the peer capabilities. | ||
1941 | */ | ||
1942 | wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N); | ||
1943 | wk->assoc.capability = req->bss->capability; | ||
1944 | wk->assoc.wmm_used = bss->wmm_used; | ||
1945 | wk->assoc.supp_rates = bss->supp_rates; | ||
1946 | wk->assoc.supp_rates_len = bss->supp_rates_len; | ||
1947 | wk->assoc.ht_information_ie = | ||
1948 | ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); | ||
1949 | |||
1950 | if (bss->wmm_used && bss->uapsd_supported && | ||
1951 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | ||
1952 | wk->assoc.uapsd_used = true; | ||
1953 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; | ||
1954 | } else { | ||
1955 | wk->assoc.uapsd_used = false; | ||
1956 | ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; | ||
1957 | } | ||
1958 | |||
1959 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | ||
1960 | memcpy(wk->assoc.ssid, ssid + 2, ssid[1]); | ||
1961 | wk->assoc.ssid_len = ssid[1]; | ||
1962 | |||
2486 | if (req->prev_bssid) | 1963 | if (req->prev_bssid) |
2487 | memcpy(wk->prev_bssid, req->prev_bssid, ETH_ALEN); | 1964 | memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); |
2488 | 1965 | ||
2489 | wk->state = IEEE80211_MGD_STATE_ASSOC; | 1966 | wk->type = IEEE80211_WORK_ASSOC; |
2490 | wk->tries = 0; | 1967 | wk->chan = req->bss->channel; |
2491 | wk->timeout = jiffies; /* run right away */ | 1968 | wk->sdata = sdata; |
1969 | wk->done = ieee80211_assoc_done; | ||
2492 | 1970 | ||
2493 | if (req->use_mfp) { | 1971 | if (req->use_mfp) { |
2494 | ifmgd->mfp = IEEE80211_MFP_REQUIRED; | 1972 | ifmgd->mfp = IEEE80211_MFP_REQUIRED; |
@@ -2503,69 +1981,65 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2503 | else | 1981 | else |
2504 | ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; | 1982 | ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; |
2505 | 1983 | ||
2506 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work); | 1984 | ieee80211_add_work(wk); |
2507 | 1985 | return 0; | |
2508 | err = 0; | ||
2509 | |||
2510 | out: | ||
2511 | mutex_unlock(&ifmgd->mtx); | ||
2512 | return err; | ||
2513 | } | 1986 | } |
2514 | 1987 | ||
2515 | int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | 1988 | int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, |
2516 | struct cfg80211_deauth_request *req, | 1989 | struct cfg80211_deauth_request *req, |
2517 | void *cookie) | 1990 | void *cookie) |
2518 | { | 1991 | { |
1992 | struct ieee80211_local *local = sdata->local; | ||
2519 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1993 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2520 | struct ieee80211_mgd_work *wk; | 1994 | struct ieee80211_work *wk; |
2521 | const u8 *bssid = NULL; | 1995 | const u8 *bssid = req->bss->bssid; |
2522 | bool not_auth_yet = false; | ||
2523 | 1996 | ||
2524 | mutex_lock(&ifmgd->mtx); | 1997 | mutex_lock(&ifmgd->mtx); |
2525 | 1998 | ||
2526 | if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { | 1999 | if (ifmgd->associated == req->bss) { |
2527 | bssid = req->bss->bssid; | 2000 | bssid = req->bss->bssid; |
2528 | ieee80211_set_disassoc(sdata, true); | 2001 | ieee80211_set_disassoc(sdata); |
2529 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { | ||
2530 | if (&wk->bss->cbss == req->bss) { | ||
2531 | bssid = req->bss->bssid; | ||
2532 | if (wk->state == IEEE80211_MGD_STATE_PROBE) | ||
2533 | not_auth_yet = true; | ||
2534 | list_del(&wk->list); | ||
2535 | kfree(wk); | ||
2536 | break; | ||
2537 | } | ||
2538 | } | ||
2539 | |||
2540 | /* | ||
2541 | * If somebody requests authentication and we haven't | ||
2542 | * sent out an auth frame yet there's no need to send | ||
2543 | * out a deauth frame either. If the state was PROBE, | ||
2544 | * then this is the case. If it's AUTH we have sent a | ||
2545 | * frame, and if it's IDLE we have completed the auth | ||
2546 | * process already. | ||
2547 | */ | ||
2548 | if (not_auth_yet) { | ||
2549 | mutex_unlock(&ifmgd->mtx); | 2002 | mutex_unlock(&ifmgd->mtx); |
2550 | __cfg80211_auth_canceled(sdata->dev, bssid); | 2003 | } else { |
2551 | return 0; | 2004 | bool not_auth_yet = false; |
2552 | } | ||
2553 | 2005 | ||
2554 | /* | ||
2555 | * cfg80211 should catch this ... but it's racy since | ||
2556 | * we can receive a deauth frame, process it, hand it | ||
2557 | * to cfg80211 while that's in a locked section already | ||
2558 | * trying to tell us that the user wants to disconnect. | ||
2559 | */ | ||
2560 | if (!bssid) { | ||
2561 | mutex_unlock(&ifmgd->mtx); | 2006 | mutex_unlock(&ifmgd->mtx); |
2562 | return -ENOLINK; | ||
2563 | } | ||
2564 | 2007 | ||
2565 | mutex_unlock(&ifmgd->mtx); | 2008 | mutex_lock(&local->work_mtx); |
2009 | list_for_each_entry(wk, &local->work_list, list) { | ||
2010 | if (wk->sdata != sdata) | ||
2011 | continue; | ||
2012 | |||
2013 | if (wk->type != IEEE80211_WORK_DIRECT_PROBE && | ||
2014 | wk->type != IEEE80211_WORK_AUTH) | ||
2015 | continue; | ||
2016 | |||
2017 | if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) | ||
2018 | continue; | ||
2019 | |||
2020 | not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE; | ||
2021 | list_del_rcu(&wk->list); | ||
2022 | free_work(wk); | ||
2023 | break; | ||
2024 | } | ||
2025 | mutex_unlock(&local->work_mtx); | ||
2026 | |||
2027 | /* | ||
2028 | * If somebody requests authentication and we haven't | ||
2029 | * sent out an auth frame yet there's no need to send | ||
2030 | * out a deauth frame either. If the state was PROBE, | ||
2031 | * then this is the case. If it's AUTH we have sent a | ||
2032 | * frame, and if it's IDLE we have completed the auth | ||
2033 | * process already. | ||
2034 | */ | ||
2035 | if (not_auth_yet) { | ||
2036 | __cfg80211_auth_canceled(sdata->dev, bssid); | ||
2037 | return 0; | ||
2038 | } | ||
2039 | } | ||
2566 | 2040 | ||
2567 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 2041 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", |
2568 | sdata->dev->name, bssid, req->reason_code); | 2042 | sdata->name, bssid, req->reason_code); |
2569 | 2043 | ||
2570 | ieee80211_send_deauth_disassoc(sdata, bssid, | 2044 | ieee80211_send_deauth_disassoc(sdata, bssid, |
2571 | IEEE80211_STYPE_DEAUTH, req->reason_code, | 2045 | IEEE80211_STYPE_DEAUTH, req->reason_code, |
@@ -2590,15 +2064,15 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2590 | * to cfg80211 while that's in a locked section already | 2064 | * to cfg80211 while that's in a locked section already |
2591 | * trying to tell us that the user wants to disconnect. | 2065 | * trying to tell us that the user wants to disconnect. |
2592 | */ | 2066 | */ |
2593 | if (&ifmgd->associated->cbss != req->bss) { | 2067 | if (ifmgd->associated != req->bss) { |
2594 | mutex_unlock(&ifmgd->mtx); | 2068 | mutex_unlock(&ifmgd->mtx); |
2595 | return -ENOLINK; | 2069 | return -ENOLINK; |
2596 | } | 2070 | } |
2597 | 2071 | ||
2598 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 2072 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", |
2599 | sdata->dev->name, req->bss->bssid, req->reason_code); | 2073 | sdata->name, req->bss->bssid, req->reason_code); |
2600 | 2074 | ||
2601 | ieee80211_set_disassoc(sdata, false); | 2075 | ieee80211_set_disassoc(sdata); |
2602 | 2076 | ||
2603 | mutex_unlock(&ifmgd->mtx); | 2077 | mutex_unlock(&ifmgd->mtx); |
2604 | 2078 | ||
@@ -2610,3 +2084,38 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2610 | 2084 | ||
2611 | return 0; | 2085 | return 0; |
2612 | } | 2086 | } |
2087 | |||
2088 | int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | ||
2089 | struct ieee80211_channel *chan, | ||
2090 | enum nl80211_channel_type channel_type, | ||
2091 | const u8 *buf, size_t len, u64 *cookie) | ||
2092 | { | ||
2093 | struct ieee80211_local *local = sdata->local; | ||
2094 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2095 | struct sk_buff *skb; | ||
2096 | |||
2097 | /* Check that we are on the requested channel for transmission */ | ||
2098 | if ((chan != local->tmp_channel || | ||
2099 | channel_type != local->tmp_channel_type) && | ||
2100 | (chan != local->oper_channel || | ||
2101 | channel_type != local->oper_channel_type)) | ||
2102 | return -EBUSY; | ||
2103 | |||
2104 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | ||
2105 | if (!skb) | ||
2106 | return -ENOMEM; | ||
2107 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
2108 | |||
2109 | memcpy(skb_put(skb, len), buf, len); | ||
2110 | |||
2111 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) | ||
2112 | IEEE80211_SKB_CB(skb)->flags |= | ||
2113 | IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
2114 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX | | ||
2115 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
2116 | skb->dev = sdata->dev; | ||
2117 | ieee80211_tx_skb(sdata, skb); | ||
2118 | |||
2119 | *cookie = (unsigned long) skb; | ||
2120 | return 0; | ||
2121 | } | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c new file mode 100644 index 000000000000..c36b1911987a --- /dev/null +++ b/net/mac80211/offchannel.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * Off-channel operation helpers | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2004, Instant802 Networks, Inc. | ||
6 | * Copyright 2005, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | #include <net/mac80211.h> | ||
16 | #include "ieee80211_i.h" | ||
17 | |||
18 | /* | ||
19 | * inform AP that we will go to sleep so that it will buffer the frames | ||
20 | * while we scan | ||
21 | */ | ||
22 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | ||
23 | { | ||
24 | struct ieee80211_local *local = sdata->local; | ||
25 | |||
26 | local->offchannel_ps_enabled = false; | ||
27 | |||
28 | /* FIXME: what to do when local->pspolling is true? */ | ||
29 | |||
30 | del_timer_sync(&local->dynamic_ps_timer); | ||
31 | cancel_work_sync(&local->dynamic_ps_enable_work); | ||
32 | |||
33 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
34 | local->offchannel_ps_enabled = true; | ||
35 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
36 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
37 | } | ||
38 | |||
39 | if (!(local->offchannel_ps_enabled) || | ||
40 | !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) | ||
41 | /* | ||
42 | * If power save was enabled, no need to send a nullfunc | ||
43 | * frame because AP knows that we are sleeping. But if the | ||
44 | * hardware is creating the nullfunc frame for power save | ||
45 | * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not | ||
46 | * enabled) and power save was enabled, the firmware just | ||
47 | * sent a null frame with power save disabled. So we need | ||
48 | * to send a new nullfunc frame to inform the AP that we | ||
49 | * are again sleeping. | ||
50 | */ | ||
51 | ieee80211_send_nullfunc(local, sdata, 1); | ||
52 | } | ||
53 | |||
54 | /* inform AP that we are awake again, unless power save is enabled */ | ||
55 | static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | ||
56 | { | ||
57 | struct ieee80211_local *local = sdata->local; | ||
58 | |||
59 | if (!local->ps_sdata) | ||
60 | ieee80211_send_nullfunc(local, sdata, 0); | ||
61 | else if (local->offchannel_ps_enabled) { | ||
62 | /* | ||
63 | * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware | ||
64 | * will send a nullfunc frame with the powersave bit set | ||
65 | * even though the AP already knows that we are sleeping. | ||
66 | * This could be avoided by sending a null frame with power | ||
67 | * save bit disabled before enabling the power save, but | ||
68 | * this doesn't gain anything. | ||
69 | * | ||
70 | * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need | ||
71 | * to send a nullfunc frame because AP already knows that | ||
72 | * we are sleeping, let's just enable power save mode in | ||
73 | * hardware. | ||
74 | */ | ||
75 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
76 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
77 | } else if (local->hw.conf.dynamic_ps_timeout > 0) { | ||
78 | /* | ||
79 | * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer | ||
80 | * had been running before leaving the operating channel, | ||
81 | * restart the timer now and send a nullfunc frame to inform | ||
82 | * the AP that we are awake. | ||
83 | */ | ||
84 | ieee80211_send_nullfunc(local, sdata, 0); | ||
85 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
86 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) | ||
91 | { | ||
92 | struct ieee80211_sub_if_data *sdata; | ||
93 | |||
94 | mutex_lock(&local->iflist_mtx); | ||
95 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
96 | if (!ieee80211_sdata_running(sdata)) | ||
97 | continue; | ||
98 | |||
99 | /* disable beaconing */ | ||
100 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
101 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
102 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
103 | ieee80211_bss_info_change_notify( | ||
104 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
105 | |||
106 | /* | ||
107 | * only handle non-STA interfaces here, STA interfaces | ||
108 | * are handled in ieee80211_offchannel_stop_station(), | ||
109 | * e.g., from the background scan state machine. | ||
110 | * | ||
111 | * In addition, do not stop monitor interface to allow it to be | ||
112 | * used from user space controlled off-channel operations. | ||
113 | */ | ||
114 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
115 | sdata->vif.type != NL80211_IFTYPE_MONITOR) | ||
116 | netif_tx_stop_all_queues(sdata->dev); | ||
117 | } | ||
118 | mutex_unlock(&local->iflist_mtx); | ||
119 | } | ||
120 | |||
121 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local) | ||
122 | { | ||
123 | struct ieee80211_sub_if_data *sdata; | ||
124 | |||
125 | /* | ||
126 | * notify the AP about us leaving the channel and stop all STA interfaces | ||
127 | */ | ||
128 | mutex_lock(&local->iflist_mtx); | ||
129 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
130 | if (!ieee80211_sdata_running(sdata)) | ||
131 | continue; | ||
132 | |||
133 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
134 | netif_tx_stop_all_queues(sdata->dev); | ||
135 | if (sdata->u.mgd.associated) | ||
136 | ieee80211_offchannel_ps_enable(sdata); | ||
137 | } | ||
138 | } | ||
139 | mutex_unlock(&local->iflist_mtx); | ||
140 | } | ||
141 | |||
142 | void ieee80211_offchannel_return(struct ieee80211_local *local, | ||
143 | bool enable_beaconing) | ||
144 | { | ||
145 | struct ieee80211_sub_if_data *sdata; | ||
146 | |||
147 | mutex_lock(&local->iflist_mtx); | ||
148 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
149 | if (!ieee80211_sdata_running(sdata)) | ||
150 | continue; | ||
151 | |||
152 | /* Tell AP we're back */ | ||
153 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
154 | if (sdata->u.mgd.associated) | ||
155 | ieee80211_offchannel_ps_disable(sdata); | ||
156 | } | ||
157 | |||
158 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | ||
159 | netif_tx_wake_all_queues(sdata->dev); | ||
160 | |||
161 | /* re-enable beaconing */ | ||
162 | if (enable_beaconing && | ||
163 | (sdata->vif.type == NL80211_IFTYPE_AP || | ||
164 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
165 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT)) | ||
166 | ieee80211_bss_info_change_notify( | ||
167 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
168 | } | ||
169 | mutex_unlock(&local->iflist_mtx); | ||
170 | } | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index e535f1c988fe..0e64484e861c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -10,9 +10,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
10 | { | 10 | { |
11 | struct ieee80211_local *local = hw_to_local(hw); | 11 | struct ieee80211_local *local = hw_to_local(hw); |
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
13 | struct ieee80211_if_init_conf conf; | ||
14 | struct sta_info *sta; | 13 | struct sta_info *sta; |
15 | unsigned long flags; | ||
16 | 14 | ||
17 | ieee80211_scan_cancel(local); | 15 | ieee80211_scan_cancel(local); |
18 | 16 | ||
@@ -56,22 +54,21 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
56 | rcu_read_unlock(); | 54 | rcu_read_unlock(); |
57 | 55 | ||
58 | /* remove STAs */ | 56 | /* remove STAs */ |
59 | spin_lock_irqsave(&local->sta_lock, flags); | 57 | mutex_lock(&local->sta_mtx); |
60 | list_for_each_entry(sta, &local->sta_list, list) { | 58 | list_for_each_entry(sta, &local->sta_list, list) { |
61 | if (local->ops->sta_notify) { | 59 | if (sta->uploaded) { |
62 | sdata = sta->sdata; | 60 | sdata = sta->sdata; |
63 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 61 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
64 | sdata = container_of(sdata->bss, | 62 | sdata = container_of(sdata->bss, |
65 | struct ieee80211_sub_if_data, | 63 | struct ieee80211_sub_if_data, |
66 | u.ap); | 64 | u.ap); |
67 | 65 | ||
68 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, | 66 | drv_sta_remove(local, sdata, &sta->sta); |
69 | &sta->sta); | ||
70 | } | 67 | } |
71 | 68 | ||
72 | mesh_plink_quiesce(sta); | 69 | mesh_plink_quiesce(sta); |
73 | } | 70 | } |
74 | spin_unlock_irqrestore(&local->sta_lock, flags); | 71 | mutex_unlock(&local->sta_mtx); |
75 | 72 | ||
76 | /* remove all interfaces */ | 73 | /* remove all interfaces */ |
77 | list_for_each_entry(sdata, &local->interfaces, list) { | 74 | list_for_each_entry(sdata, &local->interfaces, list) { |
@@ -93,17 +90,14 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
93 | break; | 90 | break; |
94 | } | 91 | } |
95 | 92 | ||
96 | if (!netif_running(sdata->dev)) | 93 | if (!ieee80211_sdata_running(sdata)) |
97 | continue; | 94 | continue; |
98 | 95 | ||
99 | /* disable beaconing */ | 96 | /* disable beaconing */ |
100 | ieee80211_bss_info_change_notify(sdata, | 97 | ieee80211_bss_info_change_notify(sdata, |
101 | BSS_CHANGED_BEACON_ENABLED); | 98 | BSS_CHANGED_BEACON_ENABLED); |
102 | 99 | ||
103 | conf.vif = &sdata->vif; | 100 | drv_remove_interface(local, &sdata->vif); |
104 | conf.type = sdata->vif.type; | ||
105 | conf.mac_addr = sdata->dev->dev_addr; | ||
106 | drv_remove_interface(local, &conf); | ||
107 | } | 101 | } |
108 | 102 | ||
109 | /* stop hardware - this must stop RX */ | 103 | /* stop hardware - this must stop RX */ |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index b9007f80cb92..0b299d236fa1 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -145,7 +145,7 @@ static const struct file_operations rcname_ops = { | |||
145 | }; | 145 | }; |
146 | #endif | 146 | #endif |
147 | 147 | ||
148 | struct rate_control_ref *rate_control_alloc(const char *name, | 148 | static struct rate_control_ref *rate_control_alloc(const char *name, |
149 | struct ieee80211_local *local) | 149 | struct ieee80211_local *local) |
150 | { | 150 | { |
151 | struct dentry *debugfsdir = NULL; | 151 | struct dentry *debugfsdir = NULL; |
@@ -207,6 +207,27 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) | |||
207 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); | 207 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); |
208 | } | 208 | } |
209 | 209 | ||
210 | static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx) | ||
211 | { | ||
212 | u8 i; | ||
213 | |||
214 | if (basic_rates == 0) | ||
215 | return; /* assume basic rates unknown and accept rate */ | ||
216 | if (*idx < 0) | ||
217 | return; | ||
218 | if (basic_rates & (1 << *idx)) | ||
219 | return; /* selected rate is a basic rate */ | ||
220 | |||
221 | for (i = *idx + 1; i <= max_rate_idx; i++) { | ||
222 | if (basic_rates & (1 << i)) { | ||
223 | *idx = i; | ||
224 | return; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | /* could not find a basic rate; use original selection */ | ||
229 | } | ||
230 | |||
210 | bool rate_control_send_low(struct ieee80211_sta *sta, | 231 | bool rate_control_send_low(struct ieee80211_sta *sta, |
211 | void *priv_sta, | 232 | void *priv_sta, |
212 | struct ieee80211_tx_rate_control *txrc) | 233 | struct ieee80211_tx_rate_control *txrc) |
@@ -218,12 +239,48 @@ bool rate_control_send_low(struct ieee80211_sta *sta, | |||
218 | info->control.rates[0].count = | 239 | info->control.rates[0].count = |
219 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | 240 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
220 | 1 : txrc->hw->max_rate_tries; | 241 | 1 : txrc->hw->max_rate_tries; |
242 | if (!sta && txrc->ap) | ||
243 | rc_send_low_broadcast(&info->control.rates[0].idx, | ||
244 | txrc->bss_conf->basic_rates, | ||
245 | txrc->sband->n_bitrates); | ||
221 | return true; | 246 | return true; |
222 | } | 247 | } |
223 | return false; | 248 | return false; |
224 | } | 249 | } |
225 | EXPORT_SYMBOL(rate_control_send_low); | 250 | EXPORT_SYMBOL(rate_control_send_low); |
226 | 251 | ||
252 | static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | ||
253 | int n_bitrates, u32 mask) | ||
254 | { | ||
255 | int j; | ||
256 | |||
257 | /* See whether the selected rate or anything below it is allowed. */ | ||
258 | for (j = rate->idx; j >= 0; j--) { | ||
259 | if (mask & (1 << j)) { | ||
260 | /* Okay, found a suitable rate. Use it. */ | ||
261 | rate->idx = j; | ||
262 | return; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | /* Try to find a higher rate that would be allowed */ | ||
267 | for (j = rate->idx + 1; j < n_bitrates; j++) { | ||
268 | if (mask & (1 << j)) { | ||
269 | /* Okay, found a suitable rate. Use it. */ | ||
270 | rate->idx = j; | ||
271 | return; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | /* | ||
276 | * Uh.. No suitable rate exists. This should not really happen with | ||
277 | * sane TX rate mask configurations. However, should someone manage to | ||
278 | * configure supported rates and TX rate mask in incompatible way, | ||
279 | * allow the frame to be transmitted with whatever the rate control | ||
280 | * selected. | ||
281 | */ | ||
282 | } | ||
283 | |||
227 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | 284 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
228 | struct sta_info *sta, | 285 | struct sta_info *sta, |
229 | struct ieee80211_tx_rate_control *txrc) | 286 | struct ieee80211_tx_rate_control *txrc) |
@@ -233,6 +290,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
233 | struct ieee80211_sta *ista = NULL; | 290 | struct ieee80211_sta *ista = NULL; |
234 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); | 291 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); |
235 | int i; | 292 | int i; |
293 | u32 mask; | ||
236 | 294 | ||
237 | if (sta) { | 295 | if (sta) { |
238 | ista = &sta->sta; | 296 | ista = &sta->sta; |
@@ -245,23 +303,34 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
245 | info->control.rates[i].count = 1; | 303 | info->control.rates[i].count = 1; |
246 | } | 304 | } |
247 | 305 | ||
248 | if (sta && sdata->force_unicast_rateidx > -1) { | 306 | if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) |
249 | info->control.rates[0].idx = sdata->force_unicast_rateidx; | 307 | return; |
250 | } else { | 308 | |
251 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); | 309 | ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); |
252 | info->flags |= IEEE80211_TX_INTFL_RCALGO; | ||
253 | } | ||
254 | 310 | ||
255 | /* | 311 | /* |
256 | * try to enforce the maximum rate the user wanted | 312 | * Try to enforce the rateidx mask the user wanted. skip this if the |
313 | * default mask (allow all rates) is used to save some processing for | ||
314 | * the common case. | ||
257 | */ | 315 | */ |
258 | if (sdata->max_ratectrl_rateidx > -1) | 316 | mask = sdata->rc_rateidx_mask[info->band]; |
317 | if (mask != (1 << txrc->sband->n_bitrates) - 1) { | ||
318 | if (sta) { | ||
319 | /* Filter out rates that the STA does not support */ | ||
320 | mask &= sta->sta.supp_rates[info->band]; | ||
321 | } | ||
322 | /* | ||
323 | * Make sure the rate index selected for each TX rate is | ||
324 | * included in the configured mask and change the rate indexes | ||
325 | * if needed. | ||
326 | */ | ||
259 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 327 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
328 | /* Rate masking supports only legacy rates for now */ | ||
260 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) | 329 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) |
261 | continue; | 330 | continue; |
262 | info->control.rates[i].idx = | 331 | rate_idx_match_mask(&info->control.rates[i], |
263 | min_t(s8, info->control.rates[i].idx, | 332 | txrc->sband->n_bitrates, mask); |
264 | sdata->max_ratectrl_rateidx); | 333 | } |
265 | } | 334 | } |
266 | 335 | ||
267 | BUG_ON(info->control.rates[0].idx < 0); | 336 | BUG_ON(info->control.rates[0].idx < 0); |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index cb9bd1f65e27..b6108bca96d4 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -26,10 +26,6 @@ struct rate_control_ref { | |||
26 | struct kref kref; | 26 | struct kref kref; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the | ||
30 | * first available algorithm. */ | ||
31 | struct rate_control_ref *rate_control_alloc(const char *name, | ||
32 | struct ieee80211_local *local); | ||
33 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | 29 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
34 | struct sta_info *sta, | 30 | struct sta_info *sta, |
35 | struct ieee80211_tx_rate_control *txrc); | 31 | struct ieee80211_tx_rate_control *txrc); |
@@ -44,10 +40,11 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, | |||
44 | struct rate_control_ref *ref = local->rate_ctrl; | 40 | struct rate_control_ref *ref = local->rate_ctrl; |
45 | struct ieee80211_sta *ista = &sta->sta; | 41 | struct ieee80211_sta *ista = &sta->sta; |
46 | void *priv_sta = sta->rate_ctrl_priv; | 42 | void *priv_sta = sta->rate_ctrl_priv; |
47 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
48 | 43 | ||
49 | if (likely(info->flags & IEEE80211_TX_INTFL_RCALGO)) | 44 | if (!ref) |
50 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); | 45 | return; |
46 | |||
47 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); | ||
51 | } | 48 | } |
52 | 49 | ||
53 | 50 | ||
@@ -115,7 +112,8 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) | |||
115 | #endif | 112 | #endif |
116 | } | 113 | } |
117 | 114 | ||
118 | /* functions for rate control related to a device */ | 115 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the |
116 | * first available algorithm. */ | ||
119 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 117 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
120 | const char *name); | 118 | const char *name); |
121 | void rate_control_deinitialize(struct ieee80211_local *local); | 119 | void rate_control_deinitialize(struct ieee80211_local *local); |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 29bc4c516238..2652a374974e 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -157,9 +157,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
157 | 157 | ||
158 | /* In case nothing happened during the previous control interval, turn | 158 | /* In case nothing happened during the previous control interval, turn |
159 | * the sharpening factor on. */ | 159 | * the sharpening factor on. */ |
160 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 160 | period = msecs_to_jiffies(pinfo->sampling_period); |
161 | if (!period) | ||
162 | period = 1; | ||
163 | if (jiffies - spinfo->last_sample > 2 * period) | 161 | if (jiffies - spinfo->last_sample > 2 * period) |
164 | spinfo->sharp_cnt = pinfo->sharpen_duration; | 162 | spinfo->sharp_cnt = pinfo->sharpen_duration; |
165 | 163 | ||
@@ -252,9 +250,7 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba | |||
252 | } | 250 | } |
253 | 251 | ||
254 | /* Update PID controller state. */ | 252 | /* Update PID controller state. */ |
255 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 253 | period = msecs_to_jiffies(pinfo->sampling_period); |
256 | if (!period) | ||
257 | period = 1; | ||
258 | if (time_after(jiffies, spinfo->last_sample + period)) | 254 | if (time_after(jiffies, spinfo->last_sample + period)) |
259 | rate_control_pid_sample(pinfo, sband, sta, spinfo); | 255 | rate_control_pid_sample(pinfo, sband, sta, spinfo); |
260 | } | 256 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 82a30c1bf3ab..b5c48de81d8b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -283,15 +283,15 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
283 | skb->protocol = htons(ETH_P_802_2); | 283 | skb->protocol = htons(ETH_P_802_2); |
284 | 284 | ||
285 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 285 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
286 | if (!netif_running(sdata->dev)) | ||
287 | continue; | ||
288 | |||
289 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 286 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
290 | continue; | 287 | continue; |
291 | 288 | ||
292 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) | 289 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) |
293 | continue; | 290 | continue; |
294 | 291 | ||
292 | if (!ieee80211_sdata_running(sdata)) | ||
293 | continue; | ||
294 | |||
295 | if (prev_dev) { | 295 | if (prev_dev) { |
296 | skb2 = skb_clone(skb, GFP_ATOMIC); | 296 | skb2 = skb_clone(skb, GFP_ATOMIC); |
297 | if (skb2) { | 297 | if (skb2) { |
@@ -361,7 +361,9 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
361 | * boundary. In the case of regular frames, this simply means aligning the | 361 | * boundary. In the case of regular frames, this simply means aligning the |
362 | * payload to a four-byte boundary (because either the IP header is directly | 362 | * payload to a four-byte boundary (because either the IP header is directly |
363 | * contained, or IV/RFC1042 headers that have a length divisible by four are | 363 | * contained, or IV/RFC1042 headers that have a length divisible by four are |
364 | * in front of it). | 364 | * in front of it). If the payload data is not properly aligned and the |
365 | * architecture doesn't support efficient unaligned operations, mac80211 | ||
366 | * will align the data. | ||
365 | * | 367 | * |
366 | * With A-MSDU frames, however, the payload data address must yield two modulo | 368 | * With A-MSDU frames, however, the payload data address must yield two modulo |
367 | * four because there are 14-byte 802.3 headers within the A-MSDU frames that | 369 | * four because there are 14-byte 802.3 headers within the A-MSDU frames that |
@@ -375,25 +377,10 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
375 | */ | 377 | */ |
376 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) | 378 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) |
377 | { | 379 | { |
378 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 380 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
379 | int hdrlen; | 381 | WARN_ONCE((unsigned long)rx->skb->data & 1, |
380 | 382 | "unaligned packet at 0x%p\n", rx->skb->data); | |
381 | #ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT | ||
382 | return; | ||
383 | #endif | 383 | #endif |
384 | |||
385 | if (WARN_ONCE((unsigned long)rx->skb->data & 1, | ||
386 | "unaligned packet at 0x%p\n", rx->skb->data)) | ||
387 | return; | ||
388 | |||
389 | if (!ieee80211_is_data_present(hdr->frame_control)) | ||
390 | return; | ||
391 | |||
392 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
393 | if (rx->flags & IEEE80211_RX_AMSDU) | ||
394 | hdrlen += ETH_HLEN; | ||
395 | WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3, | ||
396 | "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen); | ||
397 | } | 384 | } |
398 | 385 | ||
399 | 386 | ||
@@ -476,7 +463,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
476 | { | 463 | { |
477 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 464 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
478 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); | 465 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); |
479 | char *dev_addr = rx->sdata->dev->dev_addr; | 466 | char *dev_addr = rx->sdata->vif.addr; |
480 | 467 | ||
481 | if (ieee80211_is_data(hdr->frame_control)) { | 468 | if (ieee80211_is_data(hdr->frame_control)) { |
482 | if (is_multicast_ether_addr(hdr->addr1)) { | 469 | if (is_multicast_ether_addr(hdr->addr1)) { |
@@ -1021,10 +1008,10 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
1021 | 1008 | ||
1022 | atomic_inc(&sdata->bss->num_sta_ps); | 1009 | atomic_inc(&sdata->bss->num_sta_ps); |
1023 | set_sta_flags(sta, WLAN_STA_PS_STA); | 1010 | set_sta_flags(sta, WLAN_STA_PS_STA); |
1024 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); | 1011 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); |
1025 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1012 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1026 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 1013 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", |
1027 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 1014 | sdata->name, sta->sta.addr, sta->sta.aid); |
1028 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1015 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1029 | } | 1016 | } |
1030 | 1017 | ||
@@ -1038,13 +1025,13 @@ static void ap_sta_ps_end(struct sta_info *sta) | |||
1038 | 1025 | ||
1039 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1026 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1040 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", | 1027 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", |
1041 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 1028 | sdata->name, sta->sta.addr, sta->sta.aid); |
1042 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1029 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1043 | 1030 | ||
1044 | if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) { | 1031 | if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) { |
1045 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1032 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1046 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", | 1033 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", |
1047 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 1034 | sdata->name, sta->sta.addr, sta->sta.aid); |
1048 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1035 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1049 | return; | 1036 | return; |
1050 | } | 1037 | } |
@@ -1124,6 +1111,18 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1124 | if (ieee80211_is_nullfunc(hdr->frame_control) || | 1111 | if (ieee80211_is_nullfunc(hdr->frame_control) || |
1125 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { | 1112 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { |
1126 | I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); | 1113 | I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); |
1114 | |||
1115 | /* | ||
1116 | * If we receive a 4-addr nullfunc frame from a STA | ||
1117 | * that was not moved to a 4-addr STA vlan yet, drop | ||
1118 | * the frame to the monitor interface, to make sure | ||
1119 | * that hostapd sees it | ||
1120 | */ | ||
1121 | if (ieee80211_has_a4(hdr->frame_control) && | ||
1122 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | ||
1123 | (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | ||
1124 | !rx->sdata->u.vlan.sta))) | ||
1125 | return RX_DROP_MONITOR; | ||
1127 | /* | 1126 | /* |
1128 | * Update counter and free packet here to avoid | 1127 | * Update counter and free packet here to avoid |
1129 | * counting this as a dropped packed. | 1128 | * counting this as a dropped packed. |
@@ -1156,7 +1155,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, | |||
1156 | printk(KERN_DEBUG "%s: RX reassembly removed oldest " | 1155 | printk(KERN_DEBUG "%s: RX reassembly removed oldest " |
1157 | "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " | 1156 | "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " |
1158 | "addr1=%pM addr2=%pM\n", | 1157 | "addr1=%pM addr2=%pM\n", |
1159 | sdata->dev->name, idx, | 1158 | sdata->name, idx, |
1160 | jiffies - entry->first_frag_time, entry->seq, | 1159 | jiffies - entry->first_frag_time, entry->seq, |
1161 | entry->last_frag, hdr->addr1, hdr->addr2); | 1160 | entry->last_frag, hdr->addr1, hdr->addr2); |
1162 | #endif | 1161 | #endif |
@@ -1398,6 +1397,21 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1398 | ieee80211_is_data(fc) && | 1397 | ieee80211_is_data(fc) && |
1399 | (rx->key || rx->sdata->drop_unencrypted))) | 1398 | (rx->key || rx->sdata->drop_unencrypted))) |
1400 | return -EACCES; | 1399 | return -EACCES; |
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static int | ||
1405 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | ||
1406 | { | ||
1407 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
1408 | __le16 fc = hdr->frame_control; | ||
1409 | int res; | ||
1410 | |||
1411 | res = ieee80211_drop_unencrypted(rx, fc); | ||
1412 | if (unlikely(res)) | ||
1413 | return res; | ||
1414 | |||
1401 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1415 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1402 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1416 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && |
1403 | rx->key)) | 1417 | rx->key)) |
@@ -1424,7 +1438,6 @@ static int | |||
1424 | __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | 1438 | __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) |
1425 | { | 1439 | { |
1426 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1440 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1427 | struct net_device *dev = sdata->dev; | ||
1428 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1441 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1429 | 1442 | ||
1430 | if (ieee80211_has_a4(hdr->frame_control) && | 1443 | if (ieee80211_has_a4(hdr->frame_control) && |
@@ -1436,7 +1449,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1436 | (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr))) | 1449 | (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr))) |
1437 | return -1; | 1450 | return -1; |
1438 | 1451 | ||
1439 | return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); | 1452 | return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); |
1440 | } | 1453 | } |
1441 | 1454 | ||
1442 | /* | 1455 | /* |
@@ -1453,7 +1466,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) | |||
1453 | * of whether the frame was encrypted or not. | 1466 | * of whether the frame was encrypted or not. |
1454 | */ | 1467 | */ |
1455 | if (ehdr->h_proto == htons(ETH_P_PAE) && | 1468 | if (ehdr->h_proto == htons(ETH_P_PAE) && |
1456 | (compare_ether_addr(ehdr->h_dest, rx->sdata->dev->dev_addr) == 0 || | 1469 | (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 || |
1457 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) | 1470 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) |
1458 | return true; | 1471 | return true; |
1459 | 1472 | ||
@@ -1472,7 +1485,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1472 | { | 1485 | { |
1473 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1486 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1474 | struct net_device *dev = sdata->dev; | 1487 | struct net_device *dev = sdata->dev; |
1475 | struct ieee80211_local *local = rx->local; | ||
1476 | struct sk_buff *skb, *xmit_skb; | 1488 | struct sk_buff *skb, *xmit_skb; |
1477 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; | 1489 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; |
1478 | struct sta_info *dsta; | 1490 | struct sta_info *dsta; |
@@ -1495,8 +1507,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1495 | printk(KERN_DEBUG "%s: failed to clone " | 1507 | printk(KERN_DEBUG "%s: failed to clone " |
1496 | "multicast frame\n", dev->name); | 1508 | "multicast frame\n", dev->name); |
1497 | } else { | 1509 | } else { |
1498 | dsta = sta_info_get(local, skb->data); | 1510 | dsta = sta_info_get(sdata, skb->data); |
1499 | if (dsta && dsta->sdata->dev == dev) { | 1511 | if (dsta) { |
1500 | /* | 1512 | /* |
1501 | * The destination station is associated to | 1513 | * The destination station is associated to |
1502 | * this AP (in this VLAN), so send the frame | 1514 | * this AP (in this VLAN), so send the frame |
@@ -1512,7 +1524,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1512 | if (skb) { | 1524 | if (skb) { |
1513 | int align __maybe_unused; | 1525 | int align __maybe_unused; |
1514 | 1526 | ||
1515 | #if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 1527 | #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
1516 | /* | 1528 | /* |
1517 | * 'align' will only take the values 0 or 2 here | 1529 | * 'align' will only take the values 0 or 2 here |
1518 | * since all frames are required to be aligned | 1530 | * since all frames are required to be aligned |
@@ -1556,16 +1568,10 @@ static ieee80211_rx_result debug_noinline | |||
1556 | ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | 1568 | ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) |
1557 | { | 1569 | { |
1558 | struct net_device *dev = rx->sdata->dev; | 1570 | struct net_device *dev = rx->sdata->dev; |
1559 | struct ieee80211_local *local = rx->local; | 1571 | struct sk_buff *skb = rx->skb; |
1560 | u16 ethertype; | ||
1561 | u8 *payload; | ||
1562 | struct sk_buff *skb = rx->skb, *frame = NULL; | ||
1563 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1572 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1564 | __le16 fc = hdr->frame_control; | 1573 | __le16 fc = hdr->frame_control; |
1565 | const struct ethhdr *eth; | 1574 | struct sk_buff_head frame_list; |
1566 | int remaining, err; | ||
1567 | u8 dst[ETH_ALEN]; | ||
1568 | u8 src[ETH_ALEN]; | ||
1569 | 1575 | ||
1570 | if (unlikely(!ieee80211_is_data(fc))) | 1576 | if (unlikely(!ieee80211_is_data(fc))) |
1571 | return RX_CONTINUE; | 1577 | return RX_CONTINUE; |
@@ -1576,94 +1582,34 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1576 | if (!(rx->flags & IEEE80211_RX_AMSDU)) | 1582 | if (!(rx->flags & IEEE80211_RX_AMSDU)) |
1577 | return RX_CONTINUE; | 1583 | return RX_CONTINUE; |
1578 | 1584 | ||
1579 | err = __ieee80211_data_to_8023(rx); | 1585 | if (ieee80211_has_a4(hdr->frame_control) && |
1580 | if (unlikely(err)) | 1586 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && |
1587 | !rx->sdata->u.vlan.sta) | ||
1581 | return RX_DROP_UNUSABLE; | 1588 | return RX_DROP_UNUSABLE; |
1582 | 1589 | ||
1583 | skb->dev = dev; | 1590 | if (is_multicast_ether_addr(hdr->addr1) && |
1584 | 1591 | ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | |
1585 | dev->stats.rx_packets++; | 1592 | rx->sdata->u.vlan.sta) || |
1586 | dev->stats.rx_bytes += skb->len; | 1593 | (rx->sdata->vif.type == NL80211_IFTYPE_STATION && |
1587 | 1594 | rx->sdata->u.mgd.use_4addr))) | |
1588 | /* skip the wrapping header */ | ||
1589 | eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); | ||
1590 | if (!eth) | ||
1591 | return RX_DROP_UNUSABLE; | 1595 | return RX_DROP_UNUSABLE; |
1592 | 1596 | ||
1593 | while (skb != frame) { | 1597 | skb->dev = dev; |
1594 | u8 padding; | 1598 | __skb_queue_head_init(&frame_list); |
1595 | __be16 len = eth->h_proto; | ||
1596 | unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len); | ||
1597 | |||
1598 | remaining = skb->len; | ||
1599 | memcpy(dst, eth->h_dest, ETH_ALEN); | ||
1600 | memcpy(src, eth->h_source, ETH_ALEN); | ||
1601 | |||
1602 | padding = ((4 - subframe_len) & 0x3); | ||
1603 | /* the last MSDU has no padding */ | ||
1604 | if (subframe_len > remaining) | ||
1605 | return RX_DROP_UNUSABLE; | ||
1606 | 1599 | ||
1607 | skb_pull(skb, sizeof(struct ethhdr)); | 1600 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, |
1608 | /* if last subframe reuse skb */ | 1601 | rx->sdata->vif.type, |
1609 | if (remaining <= subframe_len + padding) | 1602 | rx->local->hw.extra_tx_headroom); |
1610 | frame = skb; | ||
1611 | else { | ||
1612 | /* | ||
1613 | * Allocate and reserve two bytes more for payload | ||
1614 | * alignment since sizeof(struct ethhdr) is 14. | ||
1615 | */ | ||
1616 | frame = dev_alloc_skb( | ||
1617 | ALIGN(local->hw.extra_tx_headroom, 4) + | ||
1618 | subframe_len + 2); | ||
1619 | |||
1620 | if (frame == NULL) | ||
1621 | return RX_DROP_UNUSABLE; | ||
1622 | |||
1623 | skb_reserve(frame, | ||
1624 | ALIGN(local->hw.extra_tx_headroom, 4) + | ||
1625 | sizeof(struct ethhdr) + 2); | ||
1626 | memcpy(skb_put(frame, ntohs(len)), skb->data, | ||
1627 | ntohs(len)); | ||
1628 | |||
1629 | eth = (struct ethhdr *) skb_pull(skb, ntohs(len) + | ||
1630 | padding); | ||
1631 | if (!eth) { | ||
1632 | dev_kfree_skb(frame); | ||
1633 | return RX_DROP_UNUSABLE; | ||
1634 | } | ||
1635 | } | ||
1636 | 1603 | ||
1637 | skb_reset_network_header(frame); | 1604 | while (!skb_queue_empty(&frame_list)) { |
1638 | frame->dev = dev; | 1605 | rx->skb = __skb_dequeue(&frame_list); |
1639 | frame->priority = skb->priority; | ||
1640 | rx->skb = frame; | ||
1641 | |||
1642 | payload = frame->data; | ||
1643 | ethertype = (payload[6] << 8) | payload[7]; | ||
1644 | |||
1645 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && | ||
1646 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || | ||
1647 | compare_ether_addr(payload, | ||
1648 | bridge_tunnel_header) == 0)) { | ||
1649 | /* remove RFC1042 or Bridge-Tunnel | ||
1650 | * encapsulation and replace EtherType */ | ||
1651 | skb_pull(frame, 6); | ||
1652 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | ||
1653 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | ||
1654 | } else { | ||
1655 | memcpy(skb_push(frame, sizeof(__be16)), | ||
1656 | &len, sizeof(__be16)); | ||
1657 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | ||
1658 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | ||
1659 | } | ||
1660 | 1606 | ||
1661 | if (!ieee80211_frame_allowed(rx, fc)) { | 1607 | if (!ieee80211_frame_allowed(rx, fc)) { |
1662 | if (skb == frame) /* last frame */ | 1608 | dev_kfree_skb(rx->skb); |
1663 | return RX_DROP_UNUSABLE; | ||
1664 | dev_kfree_skb(frame); | ||
1665 | continue; | 1609 | continue; |
1666 | } | 1610 | } |
1611 | dev->stats.rx_packets++; | ||
1612 | dev->stats.rx_bytes += rx->skb->len; | ||
1667 | 1613 | ||
1668 | ieee80211_deliver_skb(rx); | 1614 | ieee80211_deliver_skb(rx); |
1669 | } | 1615 | } |
@@ -1721,7 +1667,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1721 | 1667 | ||
1722 | /* Frame has reached destination. Don't forward */ | 1668 | /* Frame has reached destination. Don't forward */ |
1723 | if (!is_multicast_ether_addr(hdr->addr1) && | 1669 | if (!is_multicast_ether_addr(hdr->addr1) && |
1724 | compare_ether_addr(sdata->dev->dev_addr, hdr->addr3) == 0) | 1670 | compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0) |
1725 | return RX_CONTINUE; | 1671 | return RX_CONTINUE; |
1726 | 1672 | ||
1727 | mesh_hdr->ttl--; | 1673 | mesh_hdr->ttl--; |
@@ -1738,10 +1684,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1738 | 1684 | ||
1739 | if (!fwd_skb && net_ratelimit()) | 1685 | if (!fwd_skb && net_ratelimit()) |
1740 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | 1686 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", |
1741 | sdata->dev->name); | 1687 | sdata->name); |
1742 | 1688 | ||
1743 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | 1689 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; |
1744 | memcpy(fwd_hdr->addr2, sdata->dev->dev_addr, ETH_ALEN); | 1690 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); |
1745 | info = IEEE80211_SKB_CB(fwd_skb); | 1691 | info = IEEE80211_SKB_CB(fwd_skb); |
1746 | memset(info, 0, sizeof(*info)); | 1692 | memset(info, 0, sizeof(*info)); |
1747 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1693 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
@@ -1788,6 +1734,7 @@ static ieee80211_rx_result debug_noinline | |||
1788 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | 1734 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) |
1789 | { | 1735 | { |
1790 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1736 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1737 | struct ieee80211_local *local = rx->local; | ||
1791 | struct net_device *dev = sdata->dev; | 1738 | struct net_device *dev = sdata->dev; |
1792 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1739 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1793 | __le16 fc = hdr->frame_control; | 1740 | __le16 fc = hdr->frame_control; |
@@ -1819,6 +1766,13 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
1819 | dev->stats.rx_packets++; | 1766 | dev->stats.rx_packets++; |
1820 | dev->stats.rx_bytes += rx->skb->len; | 1767 | dev->stats.rx_bytes += rx->skb->len; |
1821 | 1768 | ||
1769 | if (ieee80211_is_data(hdr->frame_control) && | ||
1770 | !is_multicast_ether_addr(hdr->addr1) && | ||
1771 | local->hw.conf.dynamic_ps_timeout > 0 && local->ps_sdata) { | ||
1772 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
1773 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | ||
1774 | } | ||
1775 | |||
1822 | ieee80211_deliver_skb(rx); | 1776 | ieee80211_deliver_skb(rx); |
1823 | 1777 | ||
1824 | return RX_QUEUED; | 1778 | return RX_QUEUED; |
@@ -1872,7 +1826,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | |||
1872 | struct sk_buff *skb; | 1826 | struct sk_buff *skb; |
1873 | struct ieee80211_mgmt *resp; | 1827 | struct ieee80211_mgmt *resp; |
1874 | 1828 | ||
1875 | if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) { | 1829 | if (compare_ether_addr(mgmt->da, sdata->vif.addr) != 0) { |
1876 | /* Not to own unicast address */ | 1830 | /* Not to own unicast address */ |
1877 | return; | 1831 | return; |
1878 | } | 1832 | } |
@@ -1896,7 +1850,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | |||
1896 | resp = (struct ieee80211_mgmt *) skb_put(skb, 24); | 1850 | resp = (struct ieee80211_mgmt *) skb_put(skb, 24); |
1897 | memset(resp, 0, 24); | 1851 | memset(resp, 0, 24); |
1898 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 1852 | memcpy(resp->da, mgmt->sa, ETH_ALEN); |
1899 | memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN); | 1853 | memcpy(resp->sa, sdata->vif.addr, ETH_ALEN); |
1900 | memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 1854 | memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
1901 | resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 1855 | resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1902 | IEEE80211_STYPE_ACTION); | 1856 | IEEE80211_STYPE_ACTION); |
@@ -1916,23 +1870,25 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1916 | struct ieee80211_local *local = rx->local; | 1870 | struct ieee80211_local *local = rx->local; |
1917 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1871 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1918 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1872 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1873 | struct sk_buff *nskb; | ||
1874 | struct ieee80211_rx_status *status; | ||
1919 | int len = rx->skb->len; | 1875 | int len = rx->skb->len; |
1920 | 1876 | ||
1921 | if (!ieee80211_is_action(mgmt->frame_control)) | 1877 | if (!ieee80211_is_action(mgmt->frame_control)) |
1922 | return RX_CONTINUE; | 1878 | return RX_CONTINUE; |
1923 | 1879 | ||
1924 | if (!rx->sta) | 1880 | /* drop too small frames */ |
1925 | return RX_DROP_MONITOR; | 1881 | if (len < IEEE80211_MIN_ACTION_SIZE) |
1882 | return RX_DROP_UNUSABLE; | ||
1926 | 1883 | ||
1927 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1884 | if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) |
1928 | return RX_DROP_MONITOR; | 1885 | return RX_DROP_UNUSABLE; |
1929 | 1886 | ||
1930 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | 1887 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1931 | return RX_DROP_MONITOR; | 1888 | return RX_DROP_UNUSABLE; |
1932 | 1889 | ||
1933 | /* all categories we currently handle have action_code */ | 1890 | if (ieee80211_drop_unencrypted_mgmt(rx)) |
1934 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 1891 | return RX_DROP_UNUSABLE; |
1935 | return RX_DROP_MONITOR; | ||
1936 | 1892 | ||
1937 | switch (mgmt->u.action.category) { | 1893 | switch (mgmt->u.action.category) { |
1938 | case WLAN_CATEGORY_BACK: | 1894 | case WLAN_CATEGORY_BACK: |
@@ -1945,7 +1901,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1945 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1901 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
1946 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1902 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
1947 | sdata->vif.type != NL80211_IFTYPE_AP) | 1903 | sdata->vif.type != NL80211_IFTYPE_AP) |
1948 | return RX_DROP_MONITOR; | 1904 | break; |
1905 | |||
1906 | /* verify action_code is present */ | ||
1907 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
1908 | break; | ||
1949 | 1909 | ||
1950 | switch (mgmt->u.action.u.addba_req.action_code) { | 1910 | switch (mgmt->u.action.u.addba_req.action_code) { |
1951 | case WLAN_ACTION_ADDBA_REQ: | 1911 | case WLAN_ACTION_ADDBA_REQ: |
@@ -1953,45 +1913,49 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1953 | sizeof(mgmt->u.action.u.addba_req))) | 1913 | sizeof(mgmt->u.action.u.addba_req))) |
1954 | return RX_DROP_MONITOR; | 1914 | return RX_DROP_MONITOR; |
1955 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); | 1915 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); |
1956 | break; | 1916 | goto handled; |
1957 | case WLAN_ACTION_ADDBA_RESP: | 1917 | case WLAN_ACTION_ADDBA_RESP: |
1958 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1918 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1959 | sizeof(mgmt->u.action.u.addba_resp))) | 1919 | sizeof(mgmt->u.action.u.addba_resp))) |
1960 | return RX_DROP_MONITOR; | 1920 | break; |
1961 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); | 1921 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); |
1962 | break; | 1922 | goto handled; |
1963 | case WLAN_ACTION_DELBA: | 1923 | case WLAN_ACTION_DELBA: |
1964 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1924 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1965 | sizeof(mgmt->u.action.u.delba))) | 1925 | sizeof(mgmt->u.action.u.delba))) |
1966 | return RX_DROP_MONITOR; | 1926 | break; |
1967 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); | 1927 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); |
1968 | break; | 1928 | goto handled; |
1969 | } | 1929 | } |
1970 | break; | 1930 | break; |
1971 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 1931 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
1972 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | 1932 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) |
1973 | return RX_DROP_MONITOR; | 1933 | break; |
1974 | 1934 | ||
1975 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1935 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1976 | return RX_DROP_MONITOR; | 1936 | break; |
1937 | |||
1938 | /* verify action_code is present */ | ||
1939 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
1940 | break; | ||
1977 | 1941 | ||
1978 | switch (mgmt->u.action.u.measurement.action_code) { | 1942 | switch (mgmt->u.action.u.measurement.action_code) { |
1979 | case WLAN_ACTION_SPCT_MSR_REQ: | 1943 | case WLAN_ACTION_SPCT_MSR_REQ: |
1980 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1944 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1981 | sizeof(mgmt->u.action.u.measurement))) | 1945 | sizeof(mgmt->u.action.u.measurement))) |
1982 | return RX_DROP_MONITOR; | 1946 | break; |
1983 | ieee80211_process_measurement_req(sdata, mgmt, len); | 1947 | ieee80211_process_measurement_req(sdata, mgmt, len); |
1984 | break; | 1948 | goto handled; |
1985 | case WLAN_ACTION_SPCT_CHL_SWITCH: | 1949 | case WLAN_ACTION_SPCT_CHL_SWITCH: |
1986 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1950 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1987 | sizeof(mgmt->u.action.u.chan_switch))) | 1951 | sizeof(mgmt->u.action.u.chan_switch))) |
1988 | return RX_DROP_MONITOR; | 1952 | break; |
1989 | 1953 | ||
1990 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1954 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1991 | return RX_DROP_MONITOR; | 1955 | break; |
1992 | 1956 | ||
1993 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) | 1957 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) |
1994 | return RX_DROP_MONITOR; | 1958 | break; |
1995 | 1959 | ||
1996 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); | 1960 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); |
1997 | } | 1961 | } |
@@ -1999,30 +1963,64 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1999 | case WLAN_CATEGORY_SA_QUERY: | 1963 | case WLAN_CATEGORY_SA_QUERY: |
2000 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1964 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
2001 | sizeof(mgmt->u.action.u.sa_query))) | 1965 | sizeof(mgmt->u.action.u.sa_query))) |
2002 | return RX_DROP_MONITOR; | 1966 | break; |
1967 | |||
2003 | switch (mgmt->u.action.u.sa_query.action) { | 1968 | switch (mgmt->u.action.u.sa_query.action) { |
2004 | case WLAN_ACTION_SA_QUERY_REQUEST: | 1969 | case WLAN_ACTION_SA_QUERY_REQUEST: |
2005 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1970 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
2006 | return RX_DROP_MONITOR; | 1971 | break; |
2007 | ieee80211_process_sa_query_req(sdata, mgmt, len); | 1972 | ieee80211_process_sa_query_req(sdata, mgmt, len); |
2008 | break; | 1973 | goto handled; |
2009 | case WLAN_ACTION_SA_QUERY_RESPONSE: | ||
2010 | /* | ||
2011 | * SA Query response is currently only used in AP mode | ||
2012 | * and it is processed in user space. | ||
2013 | */ | ||
2014 | return RX_CONTINUE; | ||
2015 | } | 1974 | } |
2016 | break; | 1975 | break; |
2017 | default: | 1976 | } |
2018 | /* do not process rejected action frames */ | ||
2019 | if (mgmt->u.action.category & 0x80) | ||
2020 | return RX_DROP_MONITOR; | ||
2021 | 1977 | ||
2022 | return RX_CONTINUE; | 1978 | /* |
1979 | * For AP mode, hostapd is responsible for handling any action | ||
1980 | * frames that we didn't handle, including returning unknown | ||
1981 | * ones. For all other modes we will return them to the sender, | ||
1982 | * setting the 0x80 bit in the action category, as required by | ||
1983 | * 802.11-2007 7.3.1.11. | ||
1984 | */ | ||
1985 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
1986 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1987 | return RX_DROP_MONITOR; | ||
1988 | |||
1989 | /* | ||
1990 | * Getting here means the kernel doesn't know how to handle | ||
1991 | * it, but maybe userspace does ... include returned frames | ||
1992 | * so userspace can register for those to know whether ones | ||
1993 | * it transmitted were processed or returned. | ||
1994 | */ | ||
1995 | status = IEEE80211_SKB_RXCB(rx->skb); | ||
1996 | |||
1997 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
1998 | cfg80211_rx_action(rx->sdata->dev, status->freq, | ||
1999 | rx->skb->data, rx->skb->len, | ||
2000 | GFP_ATOMIC)) | ||
2001 | goto handled; | ||
2002 | |||
2003 | /* do not return rejected action frames */ | ||
2004 | if (mgmt->u.action.category & 0x80) | ||
2005 | return RX_DROP_UNUSABLE; | ||
2006 | |||
2007 | nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0, | ||
2008 | GFP_ATOMIC); | ||
2009 | if (nskb) { | ||
2010 | struct ieee80211_mgmt *mgmt = (void *)nskb->data; | ||
2011 | |||
2012 | mgmt->u.action.category |= 0x80; | ||
2013 | memcpy(mgmt->da, mgmt->sa, ETH_ALEN); | ||
2014 | memcpy(mgmt->sa, rx->sdata->vif.addr, ETH_ALEN); | ||
2015 | |||
2016 | memset(nskb->cb, 0, sizeof(nskb->cb)); | ||
2017 | |||
2018 | ieee80211_tx_skb(rx->sdata, nskb); | ||
2023 | } | 2019 | } |
2024 | 2020 | ||
2025 | rx->sta->rx_packets++; | 2021 | handled: |
2022 | if (rx->sta) | ||
2023 | rx->sta->rx_packets++; | ||
2026 | dev_kfree_skb(rx->skb); | 2024 | dev_kfree_skb(rx->skb); |
2027 | return RX_QUEUED; | 2025 | return RX_QUEUED; |
2028 | } | 2026 | } |
@@ -2031,13 +2029,17 @@ static ieee80211_rx_result debug_noinline | |||
2031 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 2029 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
2032 | { | 2030 | { |
2033 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 2031 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
2034 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 2032 | ieee80211_rx_result rxs; |
2035 | 2033 | ||
2036 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 2034 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
2037 | return RX_DROP_MONITOR; | 2035 | return RX_DROP_MONITOR; |
2038 | 2036 | ||
2039 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | 2037 | if (ieee80211_drop_unencrypted_mgmt(rx)) |
2040 | return RX_DROP_MONITOR; | 2038 | return RX_DROP_UNUSABLE; |
2039 | |||
2040 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); | ||
2041 | if (rxs != RX_CONTINUE) | ||
2042 | return rxs; | ||
2041 | 2043 | ||
2042 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2044 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
2043 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | 2045 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); |
@@ -2143,7 +2145,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2143 | skb->protocol = htons(ETH_P_802_2); | 2145 | skb->protocol = htons(ETH_P_802_2); |
2144 | 2146 | ||
2145 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2147 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2146 | if (!netif_running(sdata->dev)) | 2148 | if (!ieee80211_sdata_running(sdata)) |
2147 | continue; | 2149 | continue; |
2148 | 2150 | ||
2149 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || | 2151 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || |
@@ -2280,7 +2282,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2280 | if (!bssid && !sdata->u.mgd.use_4addr) | 2282 | if (!bssid && !sdata->u.mgd.use_4addr) |
2281 | return 0; | 2283 | return 0; |
2282 | if (!multicast && | 2284 | if (!multicast && |
2283 | compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { | 2285 | compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) { |
2284 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2286 | if (!(sdata->dev->flags & IFF_PROMISC)) |
2285 | return 0; | 2287 | return 0; |
2286 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2288 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
@@ -2297,7 +2299,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2297 | return 0; | 2299 | return 0; |
2298 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2300 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
2299 | } else if (!multicast && | 2301 | } else if (!multicast && |
2300 | compare_ether_addr(sdata->dev->dev_addr, | 2302 | compare_ether_addr(sdata->vif.addr, |
2301 | hdr->addr1) != 0) { | 2303 | hdr->addr1) != 0) { |
2302 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2304 | if (!(sdata->dev->flags & IFF_PROMISC)) |
2303 | return 0; | 2305 | return 0; |
@@ -2308,13 +2310,13 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2308 | rate_idx = 0; /* TODO: HT rates */ | 2310 | rate_idx = 0; /* TODO: HT rates */ |
2309 | else | 2311 | else |
2310 | rate_idx = status->rate_idx; | 2312 | rate_idx = status->rate_idx; |
2311 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, | 2313 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, |
2312 | BIT(rate_idx)); | 2314 | hdr->addr2, BIT(rate_idx), GFP_ATOMIC); |
2313 | } | 2315 | } |
2314 | break; | 2316 | break; |
2315 | case NL80211_IFTYPE_MESH_POINT: | 2317 | case NL80211_IFTYPE_MESH_POINT: |
2316 | if (!multicast && | 2318 | if (!multicast && |
2317 | compare_ether_addr(sdata->dev->dev_addr, | 2319 | compare_ether_addr(sdata->vif.addr, |
2318 | hdr->addr1) != 0) { | 2320 | hdr->addr1) != 0) { |
2319 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2321 | if (!(sdata->dev->flags & IFF_PROMISC)) |
2320 | return 0; | 2322 | return 0; |
@@ -2325,11 +2327,11 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2325 | case NL80211_IFTYPE_AP_VLAN: | 2327 | case NL80211_IFTYPE_AP_VLAN: |
2326 | case NL80211_IFTYPE_AP: | 2328 | case NL80211_IFTYPE_AP: |
2327 | if (!bssid) { | 2329 | if (!bssid) { |
2328 | if (compare_ether_addr(sdata->dev->dev_addr, | 2330 | if (compare_ether_addr(sdata->vif.addr, |
2329 | hdr->addr1)) | 2331 | hdr->addr1)) |
2330 | return 0; | 2332 | return 0; |
2331 | } else if (!ieee80211_bssid_match(bssid, | 2333 | } else if (!ieee80211_bssid_match(bssid, |
2332 | sdata->dev->dev_addr)) { | 2334 | sdata->vif.addr)) { |
2333 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) | 2335 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) |
2334 | return 0; | 2336 | return 0; |
2335 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2337 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
@@ -2368,6 +2370,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2368 | int prepares; | 2370 | int prepares; |
2369 | struct ieee80211_sub_if_data *prev = NULL; | 2371 | struct ieee80211_sub_if_data *prev = NULL; |
2370 | struct sk_buff *skb_new; | 2372 | struct sk_buff *skb_new; |
2373 | struct sta_info *sta, *tmp; | ||
2374 | bool found_sta = false; | ||
2371 | 2375 | ||
2372 | hdr = (struct ieee80211_hdr *)skb->data; | 2376 | hdr = (struct ieee80211_hdr *)skb->data; |
2373 | memset(&rx, 0, sizeof(rx)); | 2377 | memset(&rx, 0, sizeof(rx)); |
@@ -2384,68 +2388,87 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2384 | ieee80211_parse_qos(&rx); | 2388 | ieee80211_parse_qos(&rx); |
2385 | ieee80211_verify_alignment(&rx); | 2389 | ieee80211_verify_alignment(&rx); |
2386 | 2390 | ||
2387 | rx.sta = sta_info_get(local, hdr->addr2); | 2391 | if (ieee80211_is_data(hdr->frame_control)) { |
2388 | if (rx.sta) | 2392 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2389 | rx.sdata = rx.sta->sdata; | 2393 | rx.sta = sta; |
2390 | 2394 | found_sta = true; | |
2391 | if (rx.sdata && ieee80211_is_data(hdr->frame_control)) { | 2395 | rx.sdata = sta->sdata; |
2392 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2396 | |
2393 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); | 2397 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2394 | if (prepares) { | 2398 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); |
2395 | if (status->flag & RX_FLAG_MMIC_ERROR) { | 2399 | if (prepares) { |
2396 | if (rx.flags & IEEE80211_RX_RA_MATCH) | 2400 | if (status->flag & RX_FLAG_MMIC_ERROR) { |
2397 | ieee80211_rx_michael_mic_report(hdr, &rx); | 2401 | if (rx.flags & IEEE80211_RX_RA_MATCH) |
2398 | } else | 2402 | ieee80211_rx_michael_mic_report(hdr, &rx); |
2399 | prev = rx.sdata; | 2403 | } else |
2404 | prev = rx.sdata; | ||
2405 | } | ||
2400 | } | 2406 | } |
2401 | } else list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2407 | } |
2402 | if (!netif_running(sdata->dev)) | 2408 | if (!found_sta) { |
2403 | continue; | 2409 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2410 | if (!ieee80211_sdata_running(sdata)) | ||
2411 | continue; | ||
2404 | 2412 | ||
2405 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 2413 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
2406 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 2414 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
2407 | continue; | 2415 | continue; |
2408 | 2416 | ||
2409 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2417 | /* |
2410 | prepares = prepare_for_handlers(sdata, &rx, hdr); | 2418 | * frame is destined for this interface, but if it's |
2419 | * not also for the previous one we handle that after | ||
2420 | * the loop to avoid copying the SKB once too much | ||
2421 | */ | ||
2411 | 2422 | ||
2412 | if (!prepares) | 2423 | if (!prev) { |
2413 | continue; | 2424 | prev = sdata; |
2425 | continue; | ||
2426 | } | ||
2414 | 2427 | ||
2415 | if (status->flag & RX_FLAG_MMIC_ERROR) { | 2428 | rx.sta = sta_info_get_bss(prev, hdr->addr2); |
2416 | rx.sdata = sdata; | ||
2417 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2418 | ieee80211_rx_michael_mic_report(hdr, &rx); | ||
2419 | continue; | ||
2420 | } | ||
2421 | 2429 | ||
2422 | /* | 2430 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2423 | * frame is destined for this interface, but if it's not | 2431 | prepares = prepare_for_handlers(prev, &rx, hdr); |
2424 | * also for the previous one we handle that after the | 2432 | |
2425 | * loop to avoid copying the SKB once too much | 2433 | if (!prepares) |
2426 | */ | 2434 | goto next; |
2427 | 2435 | ||
2428 | if (!prev) { | 2436 | if (status->flag & RX_FLAG_MMIC_ERROR) { |
2437 | rx.sdata = prev; | ||
2438 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2439 | ieee80211_rx_michael_mic_report(hdr, | ||
2440 | &rx); | ||
2441 | goto next; | ||
2442 | } | ||
2443 | |||
2444 | /* | ||
2445 | * frame was destined for the previous interface | ||
2446 | * so invoke RX handlers for it | ||
2447 | */ | ||
2448 | |||
2449 | skb_new = skb_copy(skb, GFP_ATOMIC); | ||
2450 | if (!skb_new) { | ||
2451 | if (net_ratelimit()) | ||
2452 | printk(KERN_DEBUG "%s: failed to copy " | ||
2453 | "multicast frame for %s\n", | ||
2454 | wiphy_name(local->hw.wiphy), | ||
2455 | prev->name); | ||
2456 | goto next; | ||
2457 | } | ||
2458 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); | ||
2459 | next: | ||
2429 | prev = sdata; | 2460 | prev = sdata; |
2430 | continue; | ||
2431 | } | 2461 | } |
2432 | 2462 | ||
2433 | /* | 2463 | if (prev) { |
2434 | * frame was destined for the previous interface | 2464 | rx.sta = sta_info_get_bss(prev, hdr->addr2); |
2435 | * so invoke RX handlers for it | ||
2436 | */ | ||
2437 | 2465 | ||
2438 | skb_new = skb_copy(skb, GFP_ATOMIC); | 2466 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2439 | if (!skb_new) { | 2467 | prepares = prepare_for_handlers(prev, &rx, hdr); |
2440 | if (net_ratelimit()) | 2468 | |
2441 | printk(KERN_DEBUG "%s: failed to copy " | 2469 | if (!prepares) |
2442 | "multicast frame for %s\n", | 2470 | prev = NULL; |
2443 | wiphy_name(local->hw.wiphy), | ||
2444 | prev->dev->name); | ||
2445 | continue; | ||
2446 | } | 2471 | } |
2447 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); | ||
2448 | prev = sdata; | ||
2449 | } | 2472 | } |
2450 | if (prev) | 2473 | if (prev) |
2451 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); | 2474 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f934c9620b73..b822dce97867 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/wireless.h> | ||
16 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
17 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
18 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
@@ -29,16 +28,19 @@ struct ieee80211_bss * | |||
29 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | 28 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, |
30 | u8 *ssid, u8 ssid_len) | 29 | u8 *ssid, u8 ssid_len) |
31 | { | 30 | { |
32 | return (void *)cfg80211_get_bss(local->hw.wiphy, | 31 | struct cfg80211_bss *cbss; |
33 | ieee80211_get_channel(local->hw.wiphy, | 32 | |
34 | freq), | 33 | cbss = cfg80211_get_bss(local->hw.wiphy, |
35 | bssid, ssid, ssid_len, | 34 | ieee80211_get_channel(local->hw.wiphy, freq), |
36 | 0, 0); | 35 | bssid, ssid, ssid_len, 0, 0); |
36 | if (!cbss) | ||
37 | return NULL; | ||
38 | return (void *)cbss->priv; | ||
37 | } | 39 | } |
38 | 40 | ||
39 | static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) | 41 | static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) |
40 | { | 42 | { |
41 | struct ieee80211_bss *bss = (void *)cbss; | 43 | struct ieee80211_bss *bss = (void *)cbss->priv; |
42 | 44 | ||
43 | kfree(bss_mesh_id(bss)); | 45 | kfree(bss_mesh_id(bss)); |
44 | kfree(bss_mesh_cfg(bss)); | 46 | kfree(bss_mesh_cfg(bss)); |
@@ -47,7 +49,26 @@ static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) | |||
47 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 49 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
48 | struct ieee80211_bss *bss) | 50 | struct ieee80211_bss *bss) |
49 | { | 51 | { |
50 | cfg80211_put_bss((struct cfg80211_bss *)bss); | 52 | if (!bss) |
53 | return; | ||
54 | cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv)); | ||
55 | } | ||
56 | |||
57 | static bool is_uapsd_supported(struct ieee802_11_elems *elems) | ||
58 | { | ||
59 | u8 qos_info; | ||
60 | |||
61 | if (elems->wmm_info && elems->wmm_info_len == 7 | ||
62 | && elems->wmm_info[5] == 1) | ||
63 | qos_info = elems->wmm_info[6]; | ||
64 | else if (elems->wmm_param && elems->wmm_param_len == 24 | ||
65 | && elems->wmm_param[5] == 1) | ||
66 | qos_info = elems->wmm_param[6]; | ||
67 | else | ||
68 | /* no valid wmm information or parameter element found */ | ||
69 | return false; | ||
70 | |||
71 | return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD; | ||
51 | } | 72 | } |
52 | 73 | ||
53 | struct ieee80211_bss * | 74 | struct ieee80211_bss * |
@@ -59,6 +80,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
59 | struct ieee80211_channel *channel, | 80 | struct ieee80211_channel *channel, |
60 | bool beacon) | 81 | bool beacon) |
61 | { | 82 | { |
83 | struct cfg80211_bss *cbss; | ||
62 | struct ieee80211_bss *bss; | 84 | struct ieee80211_bss *bss; |
63 | int clen; | 85 | int clen; |
64 | s32 signal = 0; | 86 | s32 signal = 0; |
@@ -68,13 +90,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
68 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 90 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
69 | signal = (rx_status->signal * 100) / local->hw.max_signal; | 91 | signal = (rx_status->signal * 100) / local->hw.max_signal; |
70 | 92 | ||
71 | bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel, | 93 | cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel, |
72 | mgmt, len, signal, GFP_ATOMIC); | 94 | mgmt, len, signal, GFP_ATOMIC); |
73 | 95 | ||
74 | if (!bss) | 96 | if (!cbss) |
75 | return NULL; | 97 | return NULL; |
76 | 98 | ||
77 | bss->cbss.free_priv = ieee80211_rx_bss_free; | 99 | cbss->free_priv = ieee80211_rx_bss_free; |
100 | bss = (void *)cbss->priv; | ||
78 | 101 | ||
79 | /* save the ERP value so that it is available at association time */ | 102 | /* save the ERP value so that it is available at association time */ |
80 | if (elems->erp_info && elems->erp_info_len >= 1) { | 103 | if (elems->erp_info && elems->erp_info_len >= 1) { |
@@ -88,10 +111,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
88 | bss->dtim_period = tim_ie->dtim_period; | 111 | bss->dtim_period = tim_ie->dtim_period; |
89 | } | 112 | } |
90 | 113 | ||
91 | /* set default value for buggy AP/no TIM element */ | ||
92 | if (bss->dtim_period == 0) | ||
93 | bss->dtim_period = 1; | ||
94 | |||
95 | bss->supp_rates_len = 0; | 114 | bss->supp_rates_len = 0; |
96 | if (elems->supp_rates) { | 115 | if (elems->supp_rates) { |
97 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | 116 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; |
@@ -111,6 +130,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
111 | } | 130 | } |
112 | 131 | ||
113 | bss->wmm_used = elems->wmm_param || elems->wmm_info; | 132 | bss->wmm_used = elems->wmm_param || elems->wmm_info; |
133 | bss->uapsd_supported = is_uapsd_supported(elems); | ||
114 | 134 | ||
115 | if (!beacon) | 135 | if (!beacon) |
116 | bss->last_probe_resp = jiffies; | 136 | bss->last_probe_resp = jiffies; |
@@ -147,7 +167,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
147 | presp = ieee80211_is_probe_resp(fc); | 167 | presp = ieee80211_is_probe_resp(fc); |
148 | if (presp) { | 168 | if (presp) { |
149 | /* ignore ProbeResp to foreign address */ | 169 | /* ignore ProbeResp to foreign address */ |
150 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | 170 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) |
151 | return RX_DROP_MONITOR; | 171 | return RX_DROP_MONITOR; |
152 | 172 | ||
153 | presp = true; | 173 | presp = true; |
@@ -220,82 +240,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
220 | return true; | 240 | return true; |
221 | } | 241 | } |
222 | 242 | ||
223 | /* | ||
224 | * inform AP that we will go to sleep so that it will buffer the frames | ||
225 | * while we scan | ||
226 | */ | ||
227 | static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata) | ||
228 | { | ||
229 | struct ieee80211_local *local = sdata->local; | ||
230 | |||
231 | local->scan_ps_enabled = false; | ||
232 | |||
233 | /* FIXME: what to do when local->pspolling is true? */ | ||
234 | |||
235 | del_timer_sync(&local->dynamic_ps_timer); | ||
236 | cancel_work_sync(&local->dynamic_ps_enable_work); | ||
237 | |||
238 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
239 | local->scan_ps_enabled = true; | ||
240 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
241 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
242 | } | ||
243 | |||
244 | if (!(local->scan_ps_enabled) || | ||
245 | !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) | ||
246 | /* | ||
247 | * If power save was enabled, no need to send a nullfunc | ||
248 | * frame because AP knows that we are sleeping. But if the | ||
249 | * hardware is creating the nullfunc frame for power save | ||
250 | * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not | ||
251 | * enabled) and power save was enabled, the firmware just | ||
252 | * sent a null frame with power save disabled. So we need | ||
253 | * to send a new nullfunc frame to inform the AP that we | ||
254 | * are again sleeping. | ||
255 | */ | ||
256 | ieee80211_send_nullfunc(local, sdata, 1); | ||
257 | } | ||
258 | |||
259 | /* inform AP that we are awake again, unless power save is enabled */ | ||
260 | static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) | ||
261 | { | ||
262 | struct ieee80211_local *local = sdata->local; | ||
263 | |||
264 | if (!local->ps_sdata) | ||
265 | ieee80211_send_nullfunc(local, sdata, 0); | ||
266 | else if (local->scan_ps_enabled) { | ||
267 | /* | ||
268 | * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware | ||
269 | * will send a nullfunc frame with the powersave bit set | ||
270 | * even though the AP already knows that we are sleeping. | ||
271 | * This could be avoided by sending a null frame with power | ||
272 | * save bit disabled before enabling the power save, but | ||
273 | * this doesn't gain anything. | ||
274 | * | ||
275 | * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need | ||
276 | * to send a nullfunc frame because AP already knows that | ||
277 | * we are sleeping, let's just enable power save mode in | ||
278 | * hardware. | ||
279 | */ | ||
280 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
281 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
282 | } else if (local->hw.conf.dynamic_ps_timeout > 0) { | ||
283 | /* | ||
284 | * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer | ||
285 | * had been running before leaving the operating channel, | ||
286 | * restart the timer now and send a nullfunc frame to inform | ||
287 | * the AP that we are awake. | ||
288 | */ | ||
289 | ieee80211_send_nullfunc(local, sdata, 0); | ||
290 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
291 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 243 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
296 | { | 244 | { |
297 | struct ieee80211_local *local = hw_to_local(hw); | 245 | struct ieee80211_local *local = hw_to_local(hw); |
298 | struct ieee80211_sub_if_data *sdata; | ||
299 | bool was_hw_scan; | 246 | bool was_hw_scan; |
300 | 247 | ||
301 | mutex_lock(&local->scan_mtx); | 248 | mutex_lock(&local->scan_mtx); |
@@ -344,41 +291,19 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
344 | 291 | ||
345 | drv_sw_scan_complete(local); | 292 | drv_sw_scan_complete(local); |
346 | 293 | ||
347 | mutex_lock(&local->iflist_mtx); | 294 | ieee80211_offchannel_return(local, true); |
348 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
349 | if (!netif_running(sdata->dev)) | ||
350 | continue; | ||
351 | |||
352 | /* Tell AP we're back */ | ||
353 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
354 | if (sdata->u.mgd.associated) { | ||
355 | ieee80211_scan_ps_disable(sdata); | ||
356 | netif_tx_wake_all_queues(sdata->dev); | ||
357 | } | ||
358 | } else | ||
359 | netif_tx_wake_all_queues(sdata->dev); | ||
360 | |||
361 | /* re-enable beaconing */ | ||
362 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
363 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
364 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
365 | ieee80211_bss_info_change_notify( | ||
366 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
367 | } | ||
368 | mutex_unlock(&local->iflist_mtx); | ||
369 | 295 | ||
370 | done: | 296 | done: |
371 | ieee80211_recalc_idle(local); | 297 | ieee80211_recalc_idle(local); |
372 | ieee80211_mlme_notify_scan_completed(local); | 298 | ieee80211_mlme_notify_scan_completed(local); |
373 | ieee80211_ibss_notify_scan_completed(local); | 299 | ieee80211_ibss_notify_scan_completed(local); |
374 | ieee80211_mesh_notify_scan_completed(local); | 300 | ieee80211_mesh_notify_scan_completed(local); |
301 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
375 | } | 302 | } |
376 | EXPORT_SYMBOL(ieee80211_scan_completed); | 303 | EXPORT_SYMBOL(ieee80211_scan_completed); |
377 | 304 | ||
378 | static int ieee80211_start_sw_scan(struct ieee80211_local *local) | 305 | static int ieee80211_start_sw_scan(struct ieee80211_local *local) |
379 | { | 306 | { |
380 | struct ieee80211_sub_if_data *sdata; | ||
381 | |||
382 | /* | 307 | /* |
383 | * Hardware/driver doesn't support hw_scan, so use software | 308 | * Hardware/driver doesn't support hw_scan, so use software |
384 | * scanning instead. First send a nullfunc frame with power save | 309 | * scanning instead. First send a nullfunc frame with power save |
@@ -394,33 +319,15 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
394 | */ | 319 | */ |
395 | drv_sw_scan_start(local); | 320 | drv_sw_scan_start(local); |
396 | 321 | ||
397 | mutex_lock(&local->iflist_mtx); | 322 | ieee80211_offchannel_stop_beaconing(local); |
398 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
399 | if (!netif_running(sdata->dev)) | ||
400 | continue; | ||
401 | |||
402 | /* disable beaconing */ | ||
403 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
404 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
405 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
406 | ieee80211_bss_info_change_notify( | ||
407 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
408 | |||
409 | /* | ||
410 | * only handle non-STA interfaces here, STA interfaces | ||
411 | * are handled in the scan state machine | ||
412 | */ | ||
413 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
414 | netif_tx_stop_all_queues(sdata->dev); | ||
415 | } | ||
416 | mutex_unlock(&local->iflist_mtx); | ||
417 | 323 | ||
418 | local->next_scan_state = SCAN_DECISION; | 324 | local->next_scan_state = SCAN_DECISION; |
419 | local->scan_channel_idx = 0; | 325 | local->scan_channel_idx = 0; |
420 | 326 | ||
327 | drv_flush(local, false); | ||
328 | |||
421 | ieee80211_configure_filter(local); | 329 | ieee80211_configure_filter(local); |
422 | 330 | ||
423 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | ||
424 | ieee80211_queue_delayed_work(&local->hw, | 331 | ieee80211_queue_delayed_work(&local->hw, |
425 | &local->scan_work, | 332 | &local->scan_work, |
426 | IEEE80211_CHANNEL_TIME); | 333 | IEEE80211_CHANNEL_TIME); |
@@ -433,12 +340,18 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
433 | struct cfg80211_scan_request *req) | 340 | struct cfg80211_scan_request *req) |
434 | { | 341 | { |
435 | struct ieee80211_local *local = sdata->local; | 342 | struct ieee80211_local *local = sdata->local; |
436 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
437 | int rc; | 343 | int rc; |
438 | 344 | ||
439 | if (local->scan_req) | 345 | if (local->scan_req) |
440 | return -EBUSY; | 346 | return -EBUSY; |
441 | 347 | ||
348 | if (!list_empty(&local->work_list)) { | ||
349 | /* wait for the work to finish/time out */ | ||
350 | local->scan_req = req; | ||
351 | local->scan_sdata = sdata; | ||
352 | return 0; | ||
353 | } | ||
354 | |||
442 | if (local->ops->hw_scan) { | 355 | if (local->ops->hw_scan) { |
443 | u8 *ies; | 356 | u8 *ies; |
444 | 357 | ||
@@ -458,32 +371,33 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
458 | local->hw_scan_req->ie = ies; | 371 | local->hw_scan_req->ie = ies; |
459 | 372 | ||
460 | local->hw_scan_band = 0; | 373 | local->hw_scan_band = 0; |
374 | |||
375 | /* | ||
376 | * After allocating local->hw_scan_req, we must | ||
377 | * go through until ieee80211_prep_hw_scan(), so | ||
378 | * anything that might be changed here and leave | ||
379 | * this function early must not go after this | ||
380 | * allocation. | ||
381 | */ | ||
461 | } | 382 | } |
462 | 383 | ||
463 | local->scan_req = req; | 384 | local->scan_req = req; |
464 | local->scan_sdata = sdata; | 385 | local->scan_sdata = sdata; |
465 | 386 | ||
466 | if (req != local->int_scan_req && | ||
467 | sdata->vif.type == NL80211_IFTYPE_STATION && | ||
468 | !list_empty(&ifmgd->work_list)) { | ||
469 | /* actually wait for the work it's doing to finish/time out */ | ||
470 | set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | if (local->ops->hw_scan) | 387 | if (local->ops->hw_scan) |
475 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 388 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
476 | else | 389 | else |
477 | __set_bit(SCAN_SW_SCANNING, &local->scanning); | 390 | __set_bit(SCAN_SW_SCANNING, &local->scanning); |
391 | |||
478 | /* | 392 | /* |
479 | * Kicking off the scan need not be protected, | 393 | * Kicking off the scan need not be protected, |
480 | * only the scan variable stuff, since now | 394 | * only the scan variable stuff, since now |
481 | * local->scan_req is assigned and other callers | 395 | * local->scan_req is assigned and other callers |
482 | * will abort their scan attempts. | 396 | * will abort their scan attempts. |
483 | * | 397 | * |
484 | * This avoids getting a scan_mtx -> iflist_mtx | 398 | * This avoids too many locking dependencies |
485 | * dependency, so that the scan completed calls | 399 | * so that the scan completed calls have more |
486 | * have more locking freedom. | 400 | * locking freedom. |
487 | */ | 401 | */ |
488 | 402 | ||
489 | ieee80211_recalc_idle(local); | 403 | ieee80211_recalc_idle(local); |
@@ -526,7 +440,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
526 | /* check if at least one STA interface is associated */ | 440 | /* check if at least one STA interface is associated */ |
527 | mutex_lock(&local->iflist_mtx); | 441 | mutex_lock(&local->iflist_mtx); |
528 | list_for_each_entry(sdata, &local->interfaces, list) { | 442 | list_for_each_entry(sdata, &local->interfaces, list) { |
529 | if (!netif_running(sdata->dev)) | 443 | if (!ieee80211_sdata_running(sdata)) |
530 | continue; | 444 | continue; |
531 | 445 | ||
532 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 446 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
@@ -564,56 +478,35 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
564 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | 478 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, |
565 | unsigned long *next_delay) | 479 | unsigned long *next_delay) |
566 | { | 480 | { |
567 | struct ieee80211_sub_if_data *sdata; | 481 | ieee80211_offchannel_stop_station(local); |
482 | |||
483 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
568 | 484 | ||
569 | /* | 485 | /* |
570 | * notify the AP about us leaving the channel and stop all STA interfaces | 486 | * What if the nullfunc frames didn't arrive? |
571 | */ | 487 | */ |
572 | mutex_lock(&local->iflist_mtx); | 488 | drv_flush(local, false); |
573 | list_for_each_entry(sdata, &local->interfaces, list) { | 489 | if (local->ops->flush) |
574 | if (!netif_running(sdata->dev)) | 490 | *next_delay = 0; |
575 | continue; | 491 | else |
576 | 492 | *next_delay = HZ / 10; | |
577 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
578 | netif_tx_stop_all_queues(sdata->dev); | ||
579 | if (sdata->u.mgd.associated) | ||
580 | ieee80211_scan_ps_enable(sdata); | ||
581 | } | ||
582 | } | ||
583 | mutex_unlock(&local->iflist_mtx); | ||
584 | |||
585 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
586 | 493 | ||
587 | /* advance to the next channel to be scanned */ | 494 | /* advance to the next channel to be scanned */ |
588 | *next_delay = HZ / 10; | ||
589 | local->next_scan_state = SCAN_SET_CHANNEL; | 495 | local->next_scan_state = SCAN_SET_CHANNEL; |
590 | } | 496 | } |
591 | 497 | ||
592 | static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, | 498 | static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, |
593 | unsigned long *next_delay) | 499 | unsigned long *next_delay) |
594 | { | 500 | { |
595 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
596 | |||
597 | /* switch back to the operating channel */ | 501 | /* switch back to the operating channel */ |
598 | local->scan_channel = NULL; | 502 | local->scan_channel = NULL; |
599 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 503 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
600 | 504 | ||
601 | /* | 505 | /* |
602 | * notify the AP about us being back and restart all STA interfaces | 506 | * Only re-enable station mode interface now; beaconing will be |
507 | * re-enabled once the full scan has been completed. | ||
603 | */ | 508 | */ |
604 | mutex_lock(&local->iflist_mtx); | 509 | ieee80211_offchannel_return(local, false); |
605 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
606 | if (!netif_running(sdata->dev)) | ||
607 | continue; | ||
608 | |||
609 | /* Tell AP we're back */ | ||
610 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
611 | if (sdata->u.mgd.associated) | ||
612 | ieee80211_scan_ps_disable(sdata); | ||
613 | netif_tx_wake_all_queues(sdata->dev); | ||
614 | } | ||
615 | } | ||
616 | mutex_unlock(&local->iflist_mtx); | ||
617 | 510 | ||
618 | __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); | 511 | __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); |
619 | 512 | ||
@@ -727,7 +620,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
727 | /* | 620 | /* |
728 | * Avoid re-scheduling when the sdata is going away. | 621 | * Avoid re-scheduling when the sdata is going away. |
729 | */ | 622 | */ |
730 | if (!netif_running(sdata->dev)) { | 623 | if (!ieee80211_sdata_running(sdata)) { |
731 | ieee80211_scan_completed(&local->hw, true); | 624 | ieee80211_scan_completed(&local->hw, true); |
732 | return; | 625 | return; |
733 | } | 626 | } |
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index aa743a895cf9..7733f66ee2c4 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -35,7 +35,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da | |||
35 | 35 | ||
36 | if (!skb) { | 36 | if (!skb) { |
37 | printk(KERN_ERR "%s: failed to allocate buffer for " | 37 | printk(KERN_ERR "%s: failed to allocate buffer for " |
38 | "measurement report frame\n", sdata->dev->name); | 38 | "measurement report frame\n", sdata->name); |
39 | return; | 39 | return; |
40 | } | 40 | } |
41 | 41 | ||
@@ -43,7 +43,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da | |||
43 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); | 43 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); |
44 | memset(msr_report, 0, 24); | 44 | memset(msr_report, 0, 24); |
45 | memcpy(msr_report->da, da, ETH_ALEN); | 45 | memcpy(msr_report->da, da, ETH_ALEN); |
46 | memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); | 46 | memcpy(msr_report->sa, sdata->vif.addr, ETH_ALEN); |
47 | memcpy(msr_report->bssid, bssid, ETH_ALEN); | 47 | memcpy(msr_report->bssid, bssid, ETH_ALEN); |
48 | msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 48 | msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
49 | IEEE80211_STYPE_ACTION); | 49 | IEEE80211_STYPE_ACTION); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 71f370dd24bc..211c475f73c6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -32,49 +32,33 @@ | |||
32 | * for faster lookup and a list for iteration. They are managed using | 32 | * for faster lookup and a list for iteration. They are managed using |
33 | * RCU, i.e. access to the list and hash table is protected by RCU. | 33 | * RCU, i.e. access to the list and hash table is protected by RCU. |
34 | * | 34 | * |
35 | * Upon allocating a STA info structure with sta_info_alloc(), the caller owns | 35 | * Upon allocating a STA info structure with sta_info_alloc(), the caller |
36 | * that structure. It must then either destroy it using sta_info_destroy() | 36 | * owns that structure. It must then insert it into the hash table using |
37 | * (which is pretty useless) or insert it into the hash table using | 37 | * either sta_info_insert() or sta_info_insert_rcu(); only in the latter |
38 | * sta_info_insert() which demotes the reference from ownership to a regular | 38 | * case (which acquires an rcu read section but must not be called from |
39 | * RCU-protected reference; if the function is called without protection by an | 39 | * within one) will the pointer still be valid after the call. Note that |
40 | * RCU critical section the reference is instantly invalidated. Note that the | 40 | * the caller may not do much with the STA info before inserting it, in |
41 | * caller may not do much with the STA info before inserting it, in particular, | 41 | * particular, it may not start any mesh peer link management or add |
42 | * it may not start any mesh peer link management or add encryption keys. | 42 | * encryption keys. |
43 | * | 43 | * |
44 | * When the insertion fails (sta_info_insert()) returns non-zero), the | 44 | * When the insertion fails (sta_info_insert()) returns non-zero), the |
45 | * structure will have been freed by sta_info_insert()! | 45 | * structure will have been freed by sta_info_insert()! |
46 | * | 46 | * |
47 | * sta entries are added by mac80211 when you establish a link with a | 47 | * Station entries are added by mac80211 when you establish a link with a |
48 | * peer. This means different things for the different type of interfaces | 48 | * peer. This means different things for the different type of interfaces |
49 | * we support. For a regular station this mean we add the AP sta when we | 49 | * we support. For a regular station this mean we add the AP sta when we |
50 | * receive an assocation response from the AP. For IBSS this occurs when | 50 | * receive an assocation response from the AP. For IBSS this occurs when |
51 | * we receive a probe response or a beacon from target IBSS network. For | 51 | * get to know about a peer on the same IBSS. For WDS we add the sta for |
52 | * WDS we add the sta for the peer imediately upon device open. When using | 52 | * the peer imediately upon device open. When using AP mode we add stations |
53 | * AP mode we add stations for each respective station upon request from | 53 | * for each respective station upon request from userspace through nl80211. |
54 | * userspace through nl80211. | ||
55 | * | 54 | * |
56 | * Because there are debugfs entries for each station, and adding those | 55 | * In order to remove a STA info structure, various sta_info_destroy_*() |
57 | * must be able to sleep, it is also possible to "pin" a station entry, | 56 | * calls are available. |
58 | * that means it can be removed from the hash table but not be freed. | ||
59 | * See the comment in __sta_info_unlink() for more information, this is | ||
60 | * an internal capability only. | ||
61 | * | 57 | * |
62 | * In order to remove a STA info structure, the caller needs to first | 58 | * There is no concept of ownership on a STA entry, each structure is |
63 | * unlink it (sta_info_unlink()) from the list and hash tables and | 59 | * owned by the global hash table/list until it is removed. All users of |
64 | * then destroy it; sta_info_destroy() will wait for an RCU grace period | 60 | * the structure need to be RCU protected so that the structure won't be |
65 | * to elapse before actually freeing it. Due to the pinning and the | 61 | * freed before they are done using it. |
66 | * possibility of multiple callers trying to remove the same STA info at | ||
67 | * the same time, sta_info_unlink() can clear the STA info pointer it is | ||
68 | * passed to indicate that the STA info is owned by somebody else now. | ||
69 | * | ||
70 | * If sta_info_unlink() did not clear the pointer then the caller owns | ||
71 | * the STA info structure now and is responsible of destroying it with | ||
72 | * a call to sta_info_destroy(). | ||
73 | * | ||
74 | * In all other cases, there is no concept of ownership on a STA entry, | ||
75 | * each structure is owned by the global hash table/list until it is | ||
76 | * removed. All users of the structure need to be RCU protected so that | ||
77 | * the structure won't be freed before they are done using it. | ||
78 | */ | 62 | */ |
79 | 63 | ||
80 | /* Caller must hold local->sta_lock */ | 64 | /* Caller must hold local->sta_lock */ |
@@ -103,13 +87,37 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
103 | } | 87 | } |
104 | 88 | ||
105 | /* protected by RCU */ | 89 | /* protected by RCU */ |
106 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) | 90 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
91 | const u8 *addr) | ||
107 | { | 92 | { |
93 | struct ieee80211_local *local = sdata->local; | ||
108 | struct sta_info *sta; | 94 | struct sta_info *sta; |
109 | 95 | ||
110 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 96 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); |
111 | while (sta) { | 97 | while (sta) { |
112 | if (memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 98 | if (sta->sdata == sdata && |
99 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
100 | break; | ||
101 | sta = rcu_dereference(sta->hnext); | ||
102 | } | ||
103 | return sta; | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * Get sta info either from the specified interface | ||
108 | * or from one of its vlans | ||
109 | */ | ||
110 | struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | ||
111 | const u8 *addr) | ||
112 | { | ||
113 | struct ieee80211_local *local = sdata->local; | ||
114 | struct sta_info *sta; | ||
115 | |||
116 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | ||
117 | while (sta) { | ||
118 | if ((sta->sdata == sdata || | ||
119 | sta->sdata->bss == sdata->bss) && | ||
120 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
113 | break; | 121 | break; |
114 | sta = rcu_dereference(sta->hnext); | 122 | sta = rcu_dereference(sta->hnext); |
115 | } | 123 | } |
@@ -161,101 +169,6 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
161 | kfree(sta); | 169 | kfree(sta); |
162 | } | 170 | } |
163 | 171 | ||
164 | void sta_info_destroy(struct sta_info *sta) | ||
165 | { | ||
166 | struct ieee80211_local *local; | ||
167 | struct sk_buff *skb; | ||
168 | int i; | ||
169 | |||
170 | might_sleep(); | ||
171 | |||
172 | if (!sta) | ||
173 | return; | ||
174 | |||
175 | local = sta->local; | ||
176 | |||
177 | cancel_work_sync(&sta->drv_unblock_wk); | ||
178 | |||
179 | rate_control_remove_sta_debugfs(sta); | ||
180 | ieee80211_sta_debugfs_remove(sta); | ||
181 | |||
182 | #ifdef CONFIG_MAC80211_MESH | ||
183 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
184 | mesh_plink_deactivate(sta); | ||
185 | #endif | ||
186 | |||
187 | /* | ||
188 | * We have only unlinked the key, and actually destroying it | ||
189 | * may mean it is removed from hardware which requires that | ||
190 | * the key->sta pointer is still valid, so flush the key todo | ||
191 | * list here. | ||
192 | * | ||
193 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
194 | * nothing can reference this sta struct any more. | ||
195 | */ | ||
196 | ieee80211_key_todo(); | ||
197 | |||
198 | #ifdef CONFIG_MAC80211_MESH | ||
199 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
200 | del_timer_sync(&sta->plink_timer); | ||
201 | #endif | ||
202 | |||
203 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
204 | local->total_ps_buffered--; | ||
205 | dev_kfree_skb_any(skb); | ||
206 | } | ||
207 | |||
208 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | ||
209 | dev_kfree_skb_any(skb); | ||
210 | |||
211 | for (i = 0; i < STA_TID_NUM; i++) { | ||
212 | struct tid_ampdu_rx *tid_rx; | ||
213 | struct tid_ampdu_tx *tid_tx; | ||
214 | |||
215 | spin_lock_bh(&sta->lock); | ||
216 | tid_rx = sta->ampdu_mlme.tid_rx[i]; | ||
217 | /* Make sure timer won't free the tid_rx struct, see below */ | ||
218 | if (tid_rx) | ||
219 | tid_rx->shutdown = true; | ||
220 | |||
221 | spin_unlock_bh(&sta->lock); | ||
222 | |||
223 | /* | ||
224 | * Outside spinlock - shutdown is true now so that the timer | ||
225 | * won't free tid_rx, we have to do that now. Can't let the | ||
226 | * timer do it because we have to sync the timer outside the | ||
227 | * lock that it takes itself. | ||
228 | */ | ||
229 | if (tid_rx) { | ||
230 | del_timer_sync(&tid_rx->session_timer); | ||
231 | kfree(tid_rx); | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * No need to do such complications for TX agg sessions, the | ||
236 | * path leading to freeing the tid_tx struct goes via a call | ||
237 | * from the driver, and thus needs to look up the sta struct | ||
238 | * again, which cannot be found when we get here. Hence, we | ||
239 | * just need to delete the timer and free the aggregation | ||
240 | * info; we won't be telling the peer about it then but that | ||
241 | * doesn't matter if we're not talking to it again anyway. | ||
242 | */ | ||
243 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
244 | if (tid_tx) { | ||
245 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
246 | /* | ||
247 | * STA removed while aggregation session being | ||
248 | * started? Bit odd, but purge frames anyway. | ||
249 | */ | ||
250 | skb_queue_purge(&tid_tx->pending); | ||
251 | kfree(tid_tx); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | __sta_info_free(local, sta); | ||
256 | } | ||
257 | |||
258 | |||
259 | /* Caller must hold local->sta_lock */ | 172 | /* Caller must hold local->sta_lock */ |
260 | static void sta_info_hash_add(struct ieee80211_local *local, | 173 | static void sta_info_hash_add(struct ieee80211_local *local, |
261 | struct sta_info *sta) | 174 | struct sta_info *sta) |
@@ -352,7 +265,93 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
352 | return sta; | 265 | return sta; |
353 | } | 266 | } |
354 | 267 | ||
355 | int sta_info_insert(struct sta_info *sta) | 268 | static int sta_info_finish_insert(struct sta_info *sta, bool async) |
269 | { | ||
270 | struct ieee80211_local *local = sta->local; | ||
271 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
272 | struct station_info sinfo; | ||
273 | unsigned long flags; | ||
274 | int err = 0; | ||
275 | |||
276 | WARN_ON(!mutex_is_locked(&local->sta_mtx)); | ||
277 | |||
278 | /* notify driver */ | ||
279 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
280 | sdata = container_of(sdata->bss, | ||
281 | struct ieee80211_sub_if_data, | ||
282 | u.ap); | ||
283 | err = drv_sta_add(local, sdata, &sta->sta); | ||
284 | if (err) { | ||
285 | if (!async) | ||
286 | return err; | ||
287 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" | ||
288 | " - keeping it anyway.\n", | ||
289 | sdata->name, sta->sta.addr, err); | ||
290 | } else { | ||
291 | sta->uploaded = true; | ||
292 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
293 | if (async) | ||
294 | printk(KERN_DEBUG "%s: Finished adding IBSS STA %pM\n", | ||
295 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
296 | #endif | ||
297 | } | ||
298 | |||
299 | sdata = sta->sdata; | ||
300 | |||
301 | if (!async) { | ||
302 | local->num_sta++; | ||
303 | local->sta_generation++; | ||
304 | smp_mb(); | ||
305 | |||
306 | /* make the station visible */ | ||
307 | spin_lock_irqsave(&local->sta_lock, flags); | ||
308 | sta_info_hash_add(local, sta); | ||
309 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
310 | } | ||
311 | |||
312 | list_add(&sta->list, &local->sta_list); | ||
313 | |||
314 | ieee80211_sta_debugfs_add(sta); | ||
315 | rate_control_add_sta_debugfs(sta); | ||
316 | |||
317 | sinfo.filled = 0; | ||
318 | sinfo.generation = local->sta_generation; | ||
319 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
320 | |||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static void sta_info_finish_pending(struct ieee80211_local *local) | ||
326 | { | ||
327 | struct sta_info *sta; | ||
328 | unsigned long flags; | ||
329 | |||
330 | spin_lock_irqsave(&local->sta_lock, flags); | ||
331 | while (!list_empty(&local->sta_pending_list)) { | ||
332 | sta = list_first_entry(&local->sta_pending_list, | ||
333 | struct sta_info, list); | ||
334 | list_del(&sta->list); | ||
335 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
336 | |||
337 | sta_info_finish_insert(sta, true); | ||
338 | |||
339 | spin_lock_irqsave(&local->sta_lock, flags); | ||
340 | } | ||
341 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
342 | } | ||
343 | |||
344 | static void sta_info_finish_work(struct work_struct *work) | ||
345 | { | ||
346 | struct ieee80211_local *local = | ||
347 | container_of(work, struct ieee80211_local, sta_finish_work); | ||
348 | |||
349 | mutex_lock(&local->sta_mtx); | ||
350 | sta_info_finish_pending(local); | ||
351 | mutex_unlock(&local->sta_mtx); | ||
352 | } | ||
353 | |||
354 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | ||
356 | { | 355 | { |
357 | struct ieee80211_local *local = sta->local; | 356 | struct ieee80211_local *local = sta->local; |
358 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 357 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -364,38 +363,89 @@ int sta_info_insert(struct sta_info *sta) | |||
364 | * something inserts a STA (on one CPU) without holding the RTNL | 363 | * something inserts a STA (on one CPU) without holding the RTNL |
365 | * and another CPU turns off the net device. | 364 | * and another CPU turns off the net device. |
366 | */ | 365 | */ |
367 | if (unlikely(!netif_running(sdata->dev))) { | 366 | if (unlikely(!ieee80211_sdata_running(sdata))) { |
368 | err = -ENETDOWN; | 367 | err = -ENETDOWN; |
368 | rcu_read_lock(); | ||
369 | goto out_free; | 369 | goto out_free; |
370 | } | 370 | } |
371 | 371 | ||
372 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 || | 372 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || |
373 | is_multicast_ether_addr(sta->sta.addr))) { | 373 | is_multicast_ether_addr(sta->sta.addr))) { |
374 | err = -EINVAL; | 374 | err = -EINVAL; |
375 | rcu_read_lock(); | ||
375 | goto out_free; | 376 | goto out_free; |
376 | } | 377 | } |
377 | 378 | ||
379 | /* | ||
380 | * In ad-hoc mode, we sometimes need to insert stations | ||
381 | * from tasklet context from the RX path. To avoid races, | ||
382 | * always do so in that case -- see the comment below. | ||
383 | */ | ||
384 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
385 | spin_lock_irqsave(&local->sta_lock, flags); | ||
386 | /* check if STA exists already */ | ||
387 | if (sta_info_get_bss(sdata, sta->sta.addr)) { | ||
388 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
389 | rcu_read_lock(); | ||
390 | err = -EEXIST; | ||
391 | goto out_free; | ||
392 | } | ||
393 | |||
394 | local->num_sta++; | ||
395 | local->sta_generation++; | ||
396 | smp_mb(); | ||
397 | sta_info_hash_add(local, sta); | ||
398 | |||
399 | list_add_tail(&sta->list, &local->sta_pending_list); | ||
400 | |||
401 | rcu_read_lock(); | ||
402 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
403 | |||
404 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
405 | printk(KERN_DEBUG "%s: Added IBSS STA %pM\n", | ||
406 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
407 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
408 | |||
409 | ieee80211_queue_work(&local->hw, &local->sta_finish_work); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * On first glance, this will look racy, because the code | ||
416 | * below this point, which inserts a station with sleeping, | ||
417 | * unlocks the sta_lock between checking existence in the | ||
418 | * hash table and inserting into it. | ||
419 | * | ||
420 | * However, it is not racy against itself because it keeps | ||
421 | * the mutex locked. It still seems to race against the | ||
422 | * above code that atomically inserts the station... That, | ||
423 | * however, is not true because the above code can only | ||
424 | * be invoked for IBSS interfaces, and the below code will | ||
425 | * not be -- and the two do not race against each other as | ||
426 | * the hash table also keys off the interface. | ||
427 | */ | ||
428 | |||
429 | might_sleep(); | ||
430 | |||
431 | mutex_lock(&local->sta_mtx); | ||
432 | |||
378 | spin_lock_irqsave(&local->sta_lock, flags); | 433 | spin_lock_irqsave(&local->sta_lock, flags); |
379 | /* check if STA exists already */ | 434 | /* check if STA exists already */ |
380 | if (sta_info_get(local, sta->sta.addr)) { | 435 | if (sta_info_get_bss(sdata, sta->sta.addr)) { |
381 | spin_unlock_irqrestore(&local->sta_lock, flags); | 436 | spin_unlock_irqrestore(&local->sta_lock, flags); |
437 | rcu_read_lock(); | ||
382 | err = -EEXIST; | 438 | err = -EEXIST; |
383 | goto out_free; | 439 | goto out_free; |
384 | } | 440 | } |
385 | list_add(&sta->list, &local->sta_list); | ||
386 | local->sta_generation++; | ||
387 | local->num_sta++; | ||
388 | sta_info_hash_add(local, sta); | ||
389 | 441 | ||
390 | /* notify driver */ | 442 | spin_unlock_irqrestore(&local->sta_lock, flags); |
391 | if (local->ops->sta_notify) { | ||
392 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
393 | sdata = container_of(sdata->bss, | ||
394 | struct ieee80211_sub_if_data, | ||
395 | u.ap); | ||
396 | 443 | ||
397 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); | 444 | err = sta_info_finish_insert(sta, false); |
398 | sdata = sta->sdata; | 445 | if (err) { |
446 | mutex_unlock(&local->sta_mtx); | ||
447 | rcu_read_lock(); | ||
448 | goto out_free; | ||
399 | } | 449 | } |
400 | 450 | ||
401 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 451 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -403,18 +453,9 @@ int sta_info_insert(struct sta_info *sta) | |||
403 | wiphy_name(local->hw.wiphy), sta->sta.addr); | 453 | wiphy_name(local->hw.wiphy), sta->sta.addr); |
404 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 454 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
405 | 455 | ||
406 | spin_unlock_irqrestore(&local->sta_lock, flags); | 456 | /* move reference to rcu-protected */ |
407 | 457 | rcu_read_lock(); | |
408 | #ifdef CONFIG_MAC80211_DEBUGFS | 458 | mutex_unlock(&local->sta_mtx); |
409 | /* | ||
410 | * Debugfs entry adding might sleep, so schedule process | ||
411 | * context task for adding entry for STAs that do not yet | ||
412 | * have one. | ||
413 | * NOTE: due to auto-freeing semantics this may only be done | ||
414 | * if the insertion is successful! | ||
415 | */ | ||
416 | schedule_work(&local->sta_debugfs_add); | ||
417 | #endif | ||
418 | 459 | ||
419 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 460 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
420 | mesh_accept_plinks_update(sdata); | 461 | mesh_accept_plinks_update(sdata); |
@@ -426,6 +467,15 @@ int sta_info_insert(struct sta_info *sta) | |||
426 | return err; | 467 | return err; |
427 | } | 468 | } |
428 | 469 | ||
470 | int sta_info_insert(struct sta_info *sta) | ||
471 | { | ||
472 | int err = sta_info_insert_rcu(sta); | ||
473 | |||
474 | rcu_read_unlock(); | ||
475 | |||
476 | return err; | ||
477 | } | ||
478 | |||
429 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) | 479 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) |
430 | { | 480 | { |
431 | /* | 481 | /* |
@@ -494,108 +544,6 @@ void sta_info_clear_tim_bit(struct sta_info *sta) | |||
494 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 544 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
495 | } | 545 | } |
496 | 546 | ||
497 | static void __sta_info_unlink(struct sta_info **sta) | ||
498 | { | ||
499 | struct ieee80211_local *local = (*sta)->local; | ||
500 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; | ||
501 | /* | ||
502 | * pull caller's reference if we're already gone. | ||
503 | */ | ||
504 | if (sta_info_hash_del(local, *sta)) { | ||
505 | *sta = NULL; | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | if ((*sta)->key) { | ||
510 | ieee80211_key_free((*sta)->key); | ||
511 | WARN_ON((*sta)->key); | ||
512 | } | ||
513 | |||
514 | list_del(&(*sta)->list); | ||
515 | (*sta)->dead = true; | ||
516 | |||
517 | if (test_and_clear_sta_flags(*sta, | ||
518 | WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { | ||
519 | BUG_ON(!sdata->bss); | ||
520 | |||
521 | atomic_dec(&sdata->bss->num_sta_ps); | ||
522 | __sta_info_clear_tim_bit(sdata->bss, *sta); | ||
523 | } | ||
524 | |||
525 | local->num_sta--; | ||
526 | local->sta_generation++; | ||
527 | |||
528 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
529 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | ||
530 | |||
531 | if (local->ops->sta_notify) { | ||
532 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
533 | sdata = container_of(sdata->bss, | ||
534 | struct ieee80211_sub_if_data, | ||
535 | u.ap); | ||
536 | |||
537 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, | ||
538 | &(*sta)->sta); | ||
539 | sdata = (*sta)->sdata; | ||
540 | } | ||
541 | |||
542 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
543 | mesh_accept_plinks_update(sdata); | ||
544 | #ifdef CONFIG_MAC80211_MESH | ||
545 | del_timer(&(*sta)->plink_timer); | ||
546 | #endif | ||
547 | } | ||
548 | |||
549 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
550 | printk(KERN_DEBUG "%s: Removed STA %pM\n", | ||
551 | wiphy_name(local->hw.wiphy), (*sta)->sta.addr); | ||
552 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
553 | |||
554 | /* | ||
555 | * Finally, pull caller's reference if the STA is pinned by the | ||
556 | * task that is adding the debugfs entries. In that case, we | ||
557 | * leave the STA "to be freed". | ||
558 | * | ||
559 | * The rules are not trivial, but not too complex either: | ||
560 | * (1) pin_status is only modified under the sta_lock | ||
561 | * (2) STAs may only be pinned under the RTNL so that | ||
562 | * sta_info_flush() is guaranteed to actually destroy | ||
563 | * all STAs that are active for a given interface, this | ||
564 | * is required for correctness because otherwise we | ||
565 | * could notify a driver that an interface is going | ||
566 | * away and only after that (!) notify it about a STA | ||
567 | * on that interface going away. | ||
568 | * (3) sta_info_debugfs_add_work() will set the status | ||
569 | * to PINNED when it found an item that needs a new | ||
570 | * debugfs directory created. In that case, that item | ||
571 | * must not be freed although all *RCU* users are done | ||
572 | * with it. Hence, we tell the caller of _unlink() | ||
573 | * that the item is already gone (as can happen when | ||
574 | * two tasks try to unlink/destroy at the same time) | ||
575 | * (4) We set the pin_status to DESTROY here when we | ||
576 | * find such an item. | ||
577 | * (5) sta_info_debugfs_add_work() will reset the pin_status | ||
578 | * from PINNED to NORMAL when it is done with the item, | ||
579 | * but will check for DESTROY before resetting it in | ||
580 | * which case it will free the item. | ||
581 | */ | ||
582 | if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) { | ||
583 | (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY; | ||
584 | *sta = NULL; | ||
585 | return; | ||
586 | } | ||
587 | } | ||
588 | |||
589 | void sta_info_unlink(struct sta_info **sta) | ||
590 | { | ||
591 | struct ieee80211_local *local = (*sta)->local; | ||
592 | unsigned long flags; | ||
593 | |||
594 | spin_lock_irqsave(&local->sta_lock, flags); | ||
595 | __sta_info_unlink(sta); | ||
596 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
597 | } | ||
598 | |||
599 | static int sta_info_buffer_expired(struct sta_info *sta, | 547 | static int sta_info_buffer_expired(struct sta_info *sta, |
600 | struct sk_buff *skb) | 548 | struct sk_buff *skb) |
601 | { | 549 | { |
@@ -652,109 +600,209 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
652 | } | 600 | } |
653 | } | 601 | } |
654 | 602 | ||
655 | 603 | static int __must_check __sta_info_destroy(struct sta_info *sta) | |
656 | static void sta_info_cleanup(unsigned long data) | ||
657 | { | 604 | { |
658 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 605 | struct ieee80211_local *local; |
659 | struct sta_info *sta; | 606 | struct ieee80211_sub_if_data *sdata; |
607 | struct sk_buff *skb; | ||
608 | unsigned long flags; | ||
609 | int ret, i; | ||
660 | 610 | ||
661 | rcu_read_lock(); | 611 | might_sleep(); |
662 | list_for_each_entry_rcu(sta, &local->sta_list, list) | ||
663 | sta_info_cleanup_expire_buffered(local, sta); | ||
664 | rcu_read_unlock(); | ||
665 | 612 | ||
666 | if (local->quiescing) | 613 | if (!sta) |
667 | return; | 614 | return -ENOENT; |
668 | 615 | ||
669 | local->sta_cleanup.expires = | 616 | local = sta->local; |
670 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 617 | sdata = sta->sdata; |
671 | add_timer(&local->sta_cleanup); | ||
672 | } | ||
673 | 618 | ||
674 | #ifdef CONFIG_MAC80211_DEBUGFS | 619 | spin_lock_irqsave(&local->sta_lock, flags); |
675 | /* | 620 | ret = sta_info_hash_del(local, sta); |
676 | * See comment in __sta_info_unlink, | 621 | /* this might still be the pending list ... which is fine */ |
677 | * caller must hold local->sta_lock. | 622 | if (!ret) |
678 | */ | 623 | list_del(&sta->list); |
679 | static void __sta_info_pin(struct sta_info *sta) | 624 | spin_unlock_irqrestore(&local->sta_lock, flags); |
680 | { | 625 | if (ret) |
681 | WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL); | 626 | return ret; |
682 | sta->pin_status = STA_INFO_PIN_STAT_PINNED; | 627 | |
628 | if (sta->key) { | ||
629 | ieee80211_key_free(sta->key); | ||
630 | /* | ||
631 | * We have only unlinked the key, and actually destroying it | ||
632 | * may mean it is removed from hardware which requires that | ||
633 | * the key->sta pointer is still valid, so flush the key todo | ||
634 | * list here. | ||
635 | * | ||
636 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
637 | * nothing can reference this sta struct any more. | ||
638 | */ | ||
639 | ieee80211_key_todo(); | ||
640 | |||
641 | WARN_ON(sta->key); | ||
642 | } | ||
643 | |||
644 | sta->dead = true; | ||
645 | |||
646 | if (test_and_clear_sta_flags(sta, | ||
647 | WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { | ||
648 | BUG_ON(!sdata->bss); | ||
649 | |||
650 | atomic_dec(&sdata->bss->num_sta_ps); | ||
651 | __sta_info_clear_tim_bit(sdata->bss, sta); | ||
652 | } | ||
653 | |||
654 | local->num_sta--; | ||
655 | local->sta_generation++; | ||
656 | |||
657 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
658 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | ||
659 | |||
660 | if (sta->uploaded) { | ||
661 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
662 | sdata = container_of(sdata->bss, | ||
663 | struct ieee80211_sub_if_data, | ||
664 | u.ap); | ||
665 | drv_sta_remove(local, sdata, &sta->sta); | ||
666 | sdata = sta->sdata; | ||
667 | } | ||
668 | |||
669 | #ifdef CONFIG_MAC80211_MESH | ||
670 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
671 | mesh_accept_plinks_update(sdata); | ||
672 | del_timer(&sta->plink_timer); | ||
673 | } | ||
674 | #endif | ||
675 | |||
676 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
677 | printk(KERN_DEBUG "%s: Removed STA %pM\n", | ||
678 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
679 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
680 | cancel_work_sync(&sta->drv_unblock_wk); | ||
681 | |||
682 | rate_control_remove_sta_debugfs(sta); | ||
683 | ieee80211_sta_debugfs_remove(sta); | ||
684 | |||
685 | #ifdef CONFIG_MAC80211_MESH | ||
686 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { | ||
687 | mesh_plink_deactivate(sta); | ||
688 | del_timer_sync(&sta->plink_timer); | ||
689 | } | ||
690 | #endif | ||
691 | |||
692 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
693 | local->total_ps_buffered--; | ||
694 | dev_kfree_skb_any(skb); | ||
695 | } | ||
696 | |||
697 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | ||
698 | dev_kfree_skb_any(skb); | ||
699 | |||
700 | for (i = 0; i < STA_TID_NUM; i++) { | ||
701 | struct tid_ampdu_rx *tid_rx; | ||
702 | struct tid_ampdu_tx *tid_tx; | ||
703 | |||
704 | spin_lock_bh(&sta->lock); | ||
705 | tid_rx = sta->ampdu_mlme.tid_rx[i]; | ||
706 | /* Make sure timer won't free the tid_rx struct, see below */ | ||
707 | if (tid_rx) | ||
708 | tid_rx->shutdown = true; | ||
709 | |||
710 | spin_unlock_bh(&sta->lock); | ||
711 | |||
712 | /* | ||
713 | * Outside spinlock - shutdown is true now so that the timer | ||
714 | * won't free tid_rx, we have to do that now. Can't let the | ||
715 | * timer do it because we have to sync the timer outside the | ||
716 | * lock that it takes itself. | ||
717 | */ | ||
718 | if (tid_rx) { | ||
719 | del_timer_sync(&tid_rx->session_timer); | ||
720 | kfree(tid_rx); | ||
721 | } | ||
722 | |||
723 | /* | ||
724 | * No need to do such complications for TX agg sessions, the | ||
725 | * path leading to freeing the tid_tx struct goes via a call | ||
726 | * from the driver, and thus needs to look up the sta struct | ||
727 | * again, which cannot be found when we get here. Hence, we | ||
728 | * just need to delete the timer and free the aggregation | ||
729 | * info; we won't be telling the peer about it then but that | ||
730 | * doesn't matter if we're not talking to it again anyway. | ||
731 | */ | ||
732 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
733 | if (tid_tx) { | ||
734 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
735 | /* | ||
736 | * STA removed while aggregation session being | ||
737 | * started? Bit odd, but purge frames anyway. | ||
738 | */ | ||
739 | skb_queue_purge(&tid_tx->pending); | ||
740 | kfree(tid_tx); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | __sta_info_free(local, sta); | ||
745 | |||
746 | return 0; | ||
683 | } | 747 | } |
684 | 748 | ||
685 | /* | 749 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) |
686 | * See comment in __sta_info_unlink, returns sta if it | ||
687 | * needs to be destroyed. | ||
688 | */ | ||
689 | static struct sta_info *__sta_info_unpin(struct sta_info *sta) | ||
690 | { | 750 | { |
691 | struct sta_info *ret = NULL; | 751 | struct sta_info *sta; |
692 | unsigned long flags; | 752 | int ret; |
693 | 753 | ||
694 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 754 | mutex_lock(&sdata->local->sta_mtx); |
695 | WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY && | 755 | sta = sta_info_get(sdata, addr); |
696 | sta->pin_status != STA_INFO_PIN_STAT_PINNED); | 756 | ret = __sta_info_destroy(sta); |
697 | if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY) | 757 | mutex_unlock(&sdata->local->sta_mtx); |
698 | ret = sta; | ||
699 | sta->pin_status = STA_INFO_PIN_STAT_NORMAL; | ||
700 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | ||
701 | 758 | ||
702 | return ret; | 759 | return ret; |
703 | } | 760 | } |
704 | 761 | ||
705 | static void sta_info_debugfs_add_work(struct work_struct *work) | 762 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, |
763 | const u8 *addr) | ||
706 | { | 764 | { |
707 | struct ieee80211_local *local = | 765 | struct sta_info *sta; |
708 | container_of(work, struct ieee80211_local, sta_debugfs_add); | 766 | int ret; |
709 | struct sta_info *sta, *tmp; | ||
710 | unsigned long flags; | ||
711 | 767 | ||
712 | /* We need to keep the RTNL across the whole pinned status. */ | 768 | mutex_lock(&sdata->local->sta_mtx); |
713 | rtnl_lock(); | 769 | sta = sta_info_get_bss(sdata, addr); |
714 | while (1) { | 770 | ret = __sta_info_destroy(sta); |
715 | sta = NULL; | 771 | mutex_unlock(&sdata->local->sta_mtx); |
716 | 772 | ||
717 | spin_lock_irqsave(&local->sta_lock, flags); | 773 | return ret; |
718 | list_for_each_entry(tmp, &local->sta_list, list) { | 774 | } |
719 | /* | ||
720 | * debugfs.add_has_run will be set by | ||
721 | * ieee80211_sta_debugfs_add regardless | ||
722 | * of what else it does. | ||
723 | */ | ||
724 | if (!tmp->debugfs.add_has_run) { | ||
725 | sta = tmp; | ||
726 | __sta_info_pin(sta); | ||
727 | break; | ||
728 | } | ||
729 | } | ||
730 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
731 | 775 | ||
732 | if (!sta) | 776 | static void sta_info_cleanup(unsigned long data) |
733 | break; | 777 | { |
778 | struct ieee80211_local *local = (struct ieee80211_local *) data; | ||
779 | struct sta_info *sta; | ||
734 | 780 | ||
735 | ieee80211_sta_debugfs_add(sta); | 781 | rcu_read_lock(); |
736 | rate_control_add_sta_debugfs(sta); | 782 | list_for_each_entry_rcu(sta, &local->sta_list, list) |
783 | sta_info_cleanup_expire_buffered(local, sta); | ||
784 | rcu_read_unlock(); | ||
737 | 785 | ||
738 | sta = __sta_info_unpin(sta); | 786 | if (local->quiescing) |
739 | sta_info_destroy(sta); | 787 | return; |
740 | } | 788 | |
741 | rtnl_unlock(); | 789 | local->sta_cleanup.expires = |
790 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | ||
791 | add_timer(&local->sta_cleanup); | ||
742 | } | 792 | } |
743 | #endif | ||
744 | 793 | ||
745 | void sta_info_init(struct ieee80211_local *local) | 794 | void sta_info_init(struct ieee80211_local *local) |
746 | { | 795 | { |
747 | spin_lock_init(&local->sta_lock); | 796 | spin_lock_init(&local->sta_lock); |
797 | mutex_init(&local->sta_mtx); | ||
748 | INIT_LIST_HEAD(&local->sta_list); | 798 | INIT_LIST_HEAD(&local->sta_list); |
799 | INIT_LIST_HEAD(&local->sta_pending_list); | ||
800 | INIT_WORK(&local->sta_finish_work, sta_info_finish_work); | ||
749 | 801 | ||
750 | setup_timer(&local->sta_cleanup, sta_info_cleanup, | 802 | setup_timer(&local->sta_cleanup, sta_info_cleanup, |
751 | (unsigned long)local); | 803 | (unsigned long)local); |
752 | local->sta_cleanup.expires = | 804 | local->sta_cleanup.expires = |
753 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 805 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
754 | |||
755 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
756 | INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work); | ||
757 | #endif | ||
758 | } | 806 | } |
759 | 807 | ||
760 | int sta_info_start(struct ieee80211_local *local) | 808 | int sta_info_start(struct ieee80211_local *local) |
@@ -766,16 +814,6 @@ int sta_info_start(struct ieee80211_local *local) | |||
766 | void sta_info_stop(struct ieee80211_local *local) | 814 | void sta_info_stop(struct ieee80211_local *local) |
767 | { | 815 | { |
768 | del_timer(&local->sta_cleanup); | 816 | del_timer(&local->sta_cleanup); |
769 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
770 | /* | ||
771 | * Make sure the debugfs adding work isn't pending after this | ||
772 | * because we're about to be destroyed. It doesn't matter | ||
773 | * whether it ran or not since we're going to flush all STAs | ||
774 | * anyway. | ||
775 | */ | ||
776 | cancel_work_sync(&local->sta_debugfs_add); | ||
777 | #endif | ||
778 | |||
779 | sta_info_flush(local, NULL); | 817 | sta_info_flush(local, NULL); |
780 | } | 818 | } |
781 | 819 | ||
@@ -791,26 +829,19 @@ int sta_info_flush(struct ieee80211_local *local, | |||
791 | struct ieee80211_sub_if_data *sdata) | 829 | struct ieee80211_sub_if_data *sdata) |
792 | { | 830 | { |
793 | struct sta_info *sta, *tmp; | 831 | struct sta_info *sta, *tmp; |
794 | LIST_HEAD(tmp_list); | ||
795 | int ret = 0; | 832 | int ret = 0; |
796 | unsigned long flags; | ||
797 | 833 | ||
798 | might_sleep(); | 834 | might_sleep(); |
799 | 835 | ||
800 | spin_lock_irqsave(&local->sta_lock, flags); | 836 | mutex_lock(&local->sta_mtx); |
837 | |||
838 | sta_info_finish_pending(local); | ||
839 | |||
801 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | 840 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
802 | if (!sdata || sdata == sta->sdata) { | 841 | if (!sdata || sdata == sta->sdata) |
803 | __sta_info_unlink(&sta); | 842 | WARN_ON(__sta_info_destroy(sta)); |
804 | if (sta) { | ||
805 | list_add_tail(&sta->list, &tmp_list); | ||
806 | ret++; | ||
807 | } | ||
808 | } | ||
809 | } | 843 | } |
810 | spin_unlock_irqrestore(&local->sta_lock, flags); | 844 | mutex_unlock(&local->sta_mtx); |
811 | |||
812 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
813 | sta_info_destroy(sta); | ||
814 | 845 | ||
815 | return ret; | 846 | return ret; |
816 | } | 847 | } |
@@ -820,34 +851,28 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
820 | { | 851 | { |
821 | struct ieee80211_local *local = sdata->local; | 852 | struct ieee80211_local *local = sdata->local; |
822 | struct sta_info *sta, *tmp; | 853 | struct sta_info *sta, *tmp; |
823 | LIST_HEAD(tmp_list); | ||
824 | unsigned long flags; | ||
825 | 854 | ||
826 | spin_lock_irqsave(&local->sta_lock, flags); | 855 | mutex_lock(&local->sta_mtx); |
827 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | 856 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) |
828 | if (time_after(jiffies, sta->last_rx + exp_time)) { | 857 | if (time_after(jiffies, sta->last_rx + exp_time)) { |
829 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 858 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
830 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", | 859 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", |
831 | sdata->dev->name, sta->sta.addr); | 860 | sdata->name, sta->sta.addr); |
832 | #endif | 861 | #endif |
833 | __sta_info_unlink(&sta); | 862 | WARN_ON(__sta_info_destroy(sta)); |
834 | if (sta) | ||
835 | list_add(&sta->list, &tmp_list); | ||
836 | } | 863 | } |
837 | spin_unlock_irqrestore(&local->sta_lock, flags); | 864 | mutex_unlock(&local->sta_mtx); |
838 | |||
839 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
840 | sta_info_destroy(sta); | ||
841 | } | 865 | } |
842 | 866 | ||
843 | struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, | 867 | struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, |
844 | const u8 *addr) | 868 | const u8 *addr) |
845 | { | 869 | { |
846 | struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); | 870 | struct sta_info *sta, *nxt; |
847 | 871 | ||
848 | if (!sta) | 872 | /* Just return a random station ... first in list ... */ |
849 | return NULL; | 873 | for_each_sta_info(hw_to_local(hw), addr, sta, nxt) |
850 | return &sta->sta; | 874 | return &sta->sta; |
875 | return NULL; | ||
851 | } | 876 | } |
852 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); | 877 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); |
853 | 878 | ||
@@ -872,7 +897,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
872 | struct ieee80211_local *local = sdata->local; | 897 | struct ieee80211_local *local = sdata->local; |
873 | int sent, buffered; | 898 | int sent, buffered; |
874 | 899 | ||
875 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); | 900 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); |
876 | 901 | ||
877 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 902 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
878 | sta_info_clear_tim_bit(sta); | 903 | sta_info_clear_tim_bit(sta); |
@@ -885,7 +910,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
885 | 910 | ||
886 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 911 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
887 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " | 912 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " |
888 | "since STA not sleeping anymore\n", sdata->dev->name, | 913 | "since STA not sleeping anymore\n", sdata->name, |
889 | sta->sta.addr, sta->sta.aid, sent - buffered, buffered); | 914 | sta->sta.addr, sta->sta.aid, sent - buffered, buffered); |
890 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 915 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
891 | } | 916 | } |
@@ -944,7 +969,7 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
944 | */ | 969 | */ |
945 | printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " | 970 | printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " |
946 | "though there are no buffered frames for it\n", | 971 | "though there are no buffered frames for it\n", |
947 | sdata->dev->name, sta->sta.addr); | 972 | sdata->name, sta->sta.addr); |
948 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 973 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
949 | } | 974 | } |
950 | } | 975 | } |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b4810f6aa94f..822d84522937 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -42,6 +42,9 @@ | |||
42 | * be in the queues | 42 | * be in the queues |
43 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping | 43 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping |
44 | * station in power-save mode, reply when the driver unblocks. | 44 | * station in power-save mode, reply when the driver unblocks. |
45 | * @WLAN_STA_DISASSOC: Disassociation in progress. | ||
46 | * This is used to reject TX BA session requests when disassociation | ||
47 | * is in progress. | ||
45 | */ | 48 | */ |
46 | enum ieee80211_sta_info_flags { | 49 | enum ieee80211_sta_info_flags { |
47 | WLAN_STA_AUTH = 1<<0, | 50 | WLAN_STA_AUTH = 1<<0, |
@@ -57,6 +60,7 @@ enum ieee80211_sta_info_flags { | |||
57 | WLAN_STA_SUSPEND = 1<<11, | 60 | WLAN_STA_SUSPEND = 1<<11, |
58 | WLAN_STA_PS_DRIVER = 1<<12, | 61 | WLAN_STA_PS_DRIVER = 1<<12, |
59 | WLAN_STA_PSPOLL = 1<<13, | 62 | WLAN_STA_PSPOLL = 1<<13, |
63 | WLAN_STA_DISASSOC = 1<<14, | ||
60 | }; | 64 | }; |
61 | 65 | ||
62 | #define STA_TID_NUM 16 | 66 | #define STA_TID_NUM 16 |
@@ -162,11 +166,6 @@ struct sta_ampdu_mlme { | |||
162 | }; | 166 | }; |
163 | 167 | ||
164 | 168 | ||
165 | /* see __sta_info_unlink */ | ||
166 | #define STA_INFO_PIN_STAT_NORMAL 0 | ||
167 | #define STA_INFO_PIN_STAT_PINNED 1 | ||
168 | #define STA_INFO_PIN_STAT_DESTROY 2 | ||
169 | |||
170 | /** | 169 | /** |
171 | * struct sta_info - STA information | 170 | * struct sta_info - STA information |
172 | * | 171 | * |
@@ -187,7 +186,6 @@ struct sta_ampdu_mlme { | |||
187 | * @flaglock: spinlock for flags accesses | 186 | * @flaglock: spinlock for flags accesses |
188 | * @drv_unblock_wk: used for driver PS unblocking | 187 | * @drv_unblock_wk: used for driver PS unblocking |
189 | * @listen_interval: listen interval of this station, when we're acting as AP | 188 | * @listen_interval: listen interval of this station, when we're acting as AP |
190 | * @pin_status: used internally for pinning a STA struct into memory | ||
191 | * @flags: STA flags, see &enum ieee80211_sta_info_flags | 189 | * @flags: STA flags, see &enum ieee80211_sta_info_flags |
192 | * @ps_tx_buf: buffer of frames to transmit to this station | 190 | * @ps_tx_buf: buffer of frames to transmit to this station |
193 | * when it leaves power saving state | 191 | * when it leaves power saving state |
@@ -226,6 +224,7 @@ struct sta_ampdu_mlme { | |||
226 | * @debugfs: debug filesystem info | 224 | * @debugfs: debug filesystem info |
227 | * @sta: station information we share with the driver | 225 | * @sta: station information we share with the driver |
228 | * @dead: set to true when sta is unlinked | 226 | * @dead: set to true when sta is unlinked |
227 | * @uploaded: set to true when sta is uploaded to the driver | ||
229 | */ | 228 | */ |
230 | struct sta_info { | 229 | struct sta_info { |
231 | /* General information, mostly static */ | 230 | /* General information, mostly static */ |
@@ -245,11 +244,7 @@ struct sta_info { | |||
245 | 244 | ||
246 | bool dead; | 245 | bool dead; |
247 | 246 | ||
248 | /* | 247 | bool uploaded; |
249 | * for use by the internal lifetime management, | ||
250 | * see __sta_info_unlink | ||
251 | */ | ||
252 | u8 pin_status; | ||
253 | 248 | ||
254 | /* | 249 | /* |
255 | * frequently updated, locked with own spinlock (flaglock), | 250 | * frequently updated, locked with own spinlock (flaglock), |
@@ -403,9 +398,37 @@ static inline u32 get_sta_flags(struct sta_info *sta) | |||
403 | #define STA_INFO_CLEANUP_INTERVAL (10 * HZ) | 398 | #define STA_INFO_CLEANUP_INTERVAL (10 * HZ) |
404 | 399 | ||
405 | /* | 400 | /* |
406 | * Get a STA info, must have be under RCU read lock. | 401 | * Get a STA info, must be under RCU read lock. |
407 | */ | 402 | */ |
408 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); | 403 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
404 | const u8 *addr); | ||
405 | |||
406 | struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | ||
407 | const u8 *addr); | ||
408 | |||
409 | static inline | ||
410 | void for_each_sta_info_type_check(struct ieee80211_local *local, | ||
411 | const u8 *addr, | ||
412 | struct sta_info *sta, | ||
413 | struct sta_info *nxt) | ||
414 | { | ||
415 | } | ||
416 | |||
417 | #define for_each_sta_info(local, _addr, sta, nxt) \ | ||
418 | for ( /* initialise loop */ \ | ||
419 | sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ | ||
420 | nxt = sta ? rcu_dereference(sta->hnext) : NULL; \ | ||
421 | /* typecheck */ \ | ||
422 | for_each_sta_info_type_check(local, (_addr), sta, nxt), \ | ||
423 | /* continue condition */ \ | ||
424 | sta; \ | ||
425 | /* advance loop */ \ | ||
426 | sta = nxt, \ | ||
427 | nxt = sta ? rcu_dereference(sta->hnext) : NULL \ | ||
428 | ) \ | ||
429 | /* compare address and run code only if it matches */ \ | ||
430 | if (memcmp(sta->sta.addr, (_addr), ETH_ALEN) == 0) | ||
431 | |||
409 | /* | 432 | /* |
410 | * Get STA info by index, BROKEN! | 433 | * Get STA info by index, BROKEN! |
411 | */ | 434 | */ |
@@ -421,18 +444,19 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
421 | * Insert STA info into hash table/list, returns zero or a | 444 | * Insert STA info into hash table/list, returns zero or a |
422 | * -EEXIST if (if the same MAC address is already present). | 445 | * -EEXIST if (if the same MAC address is already present). |
423 | * | 446 | * |
424 | * Calling this without RCU protection makes the caller | 447 | * Calling the non-rcu version makes the caller relinquish, |
425 | * relinquish its reference to @sta. | 448 | * the _rcu version calls read_lock_rcu() and must be called |
449 | * without it held. | ||
426 | */ | 450 | */ |
427 | int sta_info_insert(struct sta_info *sta); | 451 | int sta_info_insert(struct sta_info *sta); |
428 | /* | 452 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
429 | * Unlink a STA info from the hash table/list. | 453 | int sta_info_insert_atomic(struct sta_info *sta); |
430 | * This can NULL the STA pointer if somebody else | 454 | |
431 | * has already unlinked it. | 455 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |
432 | */ | 456 | const u8 *addr); |
433 | void sta_info_unlink(struct sta_info **sta); | 457 | int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, |
458 | const u8 *addr); | ||
434 | 459 | ||
435 | void sta_info_destroy(struct sta_info *sta); | ||
436 | void sta_info_set_tim_bit(struct sta_info *sta); | 460 | void sta_info_set_tim_bit(struct sta_info *sta); |
437 | void sta_info_clear_tim_bit(struct sta_info *sta); | 461 | void sta_info_clear_tim_bit(struct sta_info *sta); |
438 | 462 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index d78f36c64c7b..56d5b9a6ec5b 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -45,29 +45,19 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
45 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 45 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * XXX: This is temporary! | 48 | * This skb 'survived' a round-trip through the driver, and |
49 | * | 49 | * hopefully the driver didn't mangle it too badly. However, |
50 | * The problem here is that when we get here, the driver will | 50 | * we can definitely not rely on the the control information |
51 | * quite likely have pretty much overwritten info->control by | 51 | * being correct. Clear it so we don't get junk there, and |
52 | * using info->driver_data or info->rate_driver_data. Thus, | 52 | * indicate that it needs new processing, but must not be |
53 | * when passing out the frame to the driver again, we would be | 53 | * modified/encrypted again. |
54 | * passing completely bogus data since the driver would then | ||
55 | * expect a properly filled info->control. In mac80211 itself | ||
56 | * the same problem occurs, since we need info->control.vif | ||
57 | * internally. | ||
58 | * | ||
59 | * To fix this, we should send the frame through TX processing | ||
60 | * again. However, it's not that simple, since the frame will | ||
61 | * have been software-encrypted (if applicable) already, and | ||
62 | * encrypting it again doesn't do much good. So to properly do | ||
63 | * that, we not only have to skip the actual 'raw' encryption | ||
64 | * (key selection etc. still has to be done!) but also the | ||
65 | * sequence number assignment since that impacts the crypto | ||
66 | * encapsulation, of course. | ||
67 | * | ||
68 | * Hence, for now, fix the bug by just dropping the frame. | ||
69 | */ | 54 | */ |
70 | goto drop; | 55 | memset(&info->control, 0, sizeof(info->control)); |
56 | |||
57 | info->control.jiffies = jiffies; | ||
58 | info->control.vif = &sta->sdata->vif; | ||
59 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | | ||
60 | IEEE80211_TX_INTFL_RETRANSMISSION; | ||
71 | 61 | ||
72 | sta->tx_filtered_count++; | 62 | sta->tx_filtered_count++; |
73 | 63 | ||
@@ -122,7 +112,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
122 | return; | 112 | return; |
123 | } | 113 | } |
124 | 114 | ||
125 | drop: | ||
126 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 115 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
127 | if (net_ratelimit()) | 116 | if (net_ratelimit()) |
128 | printk(KERN_DEBUG "%s: dropped TX filtered frame, " | 117 | printk(KERN_DEBUG "%s: dropped TX filtered frame, " |
@@ -134,6 +123,40 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
134 | dev_kfree_skb(skb); | 123 | dev_kfree_skb(skb); |
135 | } | 124 | } |
136 | 125 | ||
126 | static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | ||
127 | { | ||
128 | struct ieee80211_mgmt *mgmt = (void *) skb->data; | ||
129 | struct ieee80211_local *local = sta->local; | ||
130 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
131 | |||
132 | if (ieee80211_is_action(mgmt->frame_control) && | ||
133 | sdata->vif.type == NL80211_IFTYPE_STATION && | ||
134 | mgmt->u.action.category == WLAN_CATEGORY_HT && | ||
135 | mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) { | ||
136 | /* | ||
137 | * This update looks racy, but isn't -- if we come | ||
138 | * here we've definitely got a station that we're | ||
139 | * talking to, and on a managed interface that can | ||
140 | * only be the AP. And the only other place updating | ||
141 | * this variable is before we're associated. | ||
142 | */ | ||
143 | switch (mgmt->u.action.u.ht_smps.smps_control) { | ||
144 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: | ||
145 | sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC; | ||
146 | break; | ||
147 | case WLAN_HT_SMPS_CONTROL_STATIC: | ||
148 | sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC; | ||
149 | break; | ||
150 | case WLAN_HT_SMPS_CONTROL_DISABLED: | ||
151 | default: /* shouldn't happen since we don't send that */ | ||
152 | sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF; | ||
153 | break; | ||
154 | } | ||
155 | |||
156 | ieee80211_queue_work(&local->hw, &local->recalc_smps); | ||
157 | } | ||
158 | } | ||
159 | |||
137 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | 160 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) |
138 | { | 161 | { |
139 | struct sk_buff *skb2; | 162 | struct sk_buff *skb2; |
@@ -146,7 +169,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
146 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 169 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
147 | struct ieee80211_sub_if_data *sdata; | 170 | struct ieee80211_sub_if_data *sdata; |
148 | struct net_device *prev_dev = NULL; | 171 | struct net_device *prev_dev = NULL; |
149 | struct sta_info *sta; | 172 | struct sta_info *sta, *tmp; |
150 | int retry_count = -1, i; | 173 | int retry_count = -1, i; |
151 | bool injected; | 174 | bool injected; |
152 | 175 | ||
@@ -165,10 +188,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
165 | rcu_read_lock(); | 188 | rcu_read_lock(); |
166 | 189 | ||
167 | sband = local->hw.wiphy->bands[info->band]; | 190 | sband = local->hw.wiphy->bands[info->band]; |
191 | fc = hdr->frame_control; | ||
168 | 192 | ||
169 | sta = sta_info_get(local, hdr->addr1); | 193 | for_each_sta_info(local, hdr->addr1, sta, tmp) { |
194 | /* skip wrong virtual interface */ | ||
195 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | ||
196 | continue; | ||
170 | 197 | ||
171 | if (sta) { | ||
172 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | 198 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && |
173 | test_sta_flags(sta, WLAN_STA_PS_STA)) { | 199 | test_sta_flags(sta, WLAN_STA_PS_STA)) { |
174 | /* | 200 | /* |
@@ -180,8 +206,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
180 | return; | 206 | return; |
181 | } | 207 | } |
182 | 208 | ||
183 | fc = hdr->frame_control; | ||
184 | |||
185 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | 209 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && |
186 | (ieee80211_is_data_qos(fc))) { | 210 | (ieee80211_is_data_qos(fc))) { |
187 | u16 tid, ssn; | 211 | u16 tid, ssn; |
@@ -208,6 +232,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
208 | rate_control_tx_status(local, sband, sta, skb); | 232 | rate_control_tx_status(local, sband, sta, skb); |
209 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | 233 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) |
210 | ieee80211s_update_metric(local, sta, skb); | 234 | ieee80211s_update_metric(local, sta, skb); |
235 | |||
236 | if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
237 | (info->flags & IEEE80211_TX_STAT_ACK)) | ||
238 | ieee80211_frame_acked(sta, skb); | ||
211 | } | 239 | } |
212 | 240 | ||
213 | rcu_read_unlock(); | 241 | rcu_read_unlock(); |
@@ -246,6 +274,25 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
246 | local->dot11FailedCount++; | 274 | local->dot11FailedCount++; |
247 | } | 275 | } |
248 | 276 | ||
277 | if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) && | ||
278 | (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && | ||
279 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
280 | local->ps_sdata && !(local->scanning)) { | ||
281 | if (info->flags & IEEE80211_TX_STAT_ACK) { | ||
282 | local->ps_sdata->u.mgd.flags |= | ||
283 | IEEE80211_STA_NULLFUNC_ACKED; | ||
284 | ieee80211_queue_work(&local->hw, | ||
285 | &local->dynamic_ps_enable_work); | ||
286 | } else | ||
287 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
288 | msecs_to_jiffies(10)); | ||
289 | } | ||
290 | |||
291 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) | ||
292 | cfg80211_action_tx_status( | ||
293 | skb->dev, (unsigned long) skb, skb->data, skb->len, | ||
294 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); | ||
295 | |||
249 | /* this was a transmitted frame, but now we want to reuse it */ | 296 | /* this was a transmitted frame, but now we want to reuse it */ |
250 | skb_orphan(skb); | 297 | skb_orphan(skb); |
251 | 298 | ||
@@ -311,7 +358,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
311 | rcu_read_lock(); | 358 | rcu_read_lock(); |
312 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 359 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
313 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { | 360 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { |
314 | if (!netif_running(sdata->dev)) | 361 | if (!ieee80211_sdata_running(sdata)) |
315 | continue; | 362 | continue; |
316 | 363 | ||
317 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && | 364 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 4921d724b6c7..7ef491e9d66d 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -100,7 +100,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx, | |||
100 | p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j)); | 100 | p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j)); |
101 | p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; | 101 | p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; |
102 | } | 102 | } |
103 | ctx->initialized = 1; | 103 | ctx->state = TKIP_STATE_PHASE1_DONE; |
104 | } | 104 | } |
105 | 105 | ||
106 | static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, | 106 | static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, |
@@ -183,7 +183,7 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
183 | /* Update the p1k only when the iv16 in the packet wraps around, this | 183 | /* Update the p1k only when the iv16 in the packet wraps around, this |
184 | * might occur after the wrap around of iv16 in the key in case of | 184 | * might occur after the wrap around of iv16 in the key in case of |
185 | * fragmented packets. */ | 185 | * fragmented packets. */ |
186 | if (iv16 == 0 || !ctx->initialized) | 186 | if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) |
187 | tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32); | 187 | tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32); |
188 | 188 | ||
189 | if (type == IEEE80211_TKIP_P1_KEY) { | 189 | if (type == IEEE80211_TKIP_P1_KEY) { |
@@ -195,11 +195,13 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
195 | } | 195 | } |
196 | EXPORT_SYMBOL(ieee80211_get_tkip_key); | 196 | EXPORT_SYMBOL(ieee80211_get_tkip_key); |
197 | 197 | ||
198 | /* Encrypt packet payload with TKIP using @key. @pos is a pointer to the | 198 | /* |
199 | * Encrypt packet payload with TKIP using @key. @pos is a pointer to the | ||
199 | * beginning of the buffer containing payload. This payload must include | 200 | * beginning of the buffer containing payload. This payload must include |
200 | * headroom of eight octets for IV and Ext. IV and taildroom of four octets | 201 | * the IV/Ext.IV and space for (taildroom) four octets for ICV. |
201 | * for ICV. @payload_len is the length of payload (_not_ including extra | 202 | * @payload_len is the length of payload (_not_ including IV/ICV length). |
202 | * headroom and tailroom). @ta is the transmitter addresses. */ | 203 | * @ta is the transmitter addresses. |
204 | */ | ||
203 | void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | 205 | void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, |
204 | struct ieee80211_key *key, | 206 | struct ieee80211_key *key, |
205 | u8 *pos, size_t payload_len, u8 *ta) | 207 | u8 *pos, size_t payload_len, u8 *ta) |
@@ -209,12 +211,11 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | |||
209 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; | 211 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
210 | 212 | ||
211 | /* Calculate per-packet key */ | 213 | /* Calculate per-packet key */ |
212 | if (ctx->iv16 == 0 || !ctx->initialized) | 214 | if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) |
213 | tkip_mixing_phase1(tk, ctx, ta, ctx->iv32); | 215 | tkip_mixing_phase1(tk, ctx, ta, ctx->iv32); |
214 | 216 | ||
215 | tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); | 217 | tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); |
216 | 218 | ||
217 | pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); | ||
218 | ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); | 219 | ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); |
219 | } | 220 | } |
220 | 221 | ||
@@ -259,7 +260,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
259 | if ((keyid >> 6) != key->conf.keyidx) | 260 | if ((keyid >> 6) != key->conf.keyidx) |
260 | return TKIP_DECRYPT_INVALID_KEYIDX; | 261 | return TKIP_DECRYPT_INVALID_KEYIDX; |
261 | 262 | ||
262 | if (key->u.tkip.rx[queue].initialized && | 263 | if (key->u.tkip.rx[queue].state != TKIP_STATE_NOT_INIT && |
263 | (iv32 < key->u.tkip.rx[queue].iv32 || | 264 | (iv32 < key->u.tkip.rx[queue].iv32 || |
264 | (iv32 == key->u.tkip.rx[queue].iv32 && | 265 | (iv32 == key->u.tkip.rx[queue].iv32 && |
265 | iv16 <= key->u.tkip.rx[queue].iv16))) { | 266 | iv16 <= key->u.tkip.rx[queue].iv16))) { |
@@ -275,11 +276,11 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
275 | 276 | ||
276 | if (only_iv) { | 277 | if (only_iv) { |
277 | res = TKIP_DECRYPT_OK; | 278 | res = TKIP_DECRYPT_OK; |
278 | key->u.tkip.rx[queue].initialized = 1; | 279 | key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; |
279 | goto done; | 280 | goto done; |
280 | } | 281 | } |
281 | 282 | ||
282 | if (!key->u.tkip.rx[queue].initialized || | 283 | if (key->u.tkip.rx[queue].state == TKIP_STATE_NOT_INIT || |
283 | key->u.tkip.rx[queue].iv32 != iv32) { | 284 | key->u.tkip.rx[queue].iv32 != iv32) { |
284 | /* IV16 wrapped around - perform TKIP phase 1 */ | 285 | /* IV16 wrapped around - perform TKIP phase 1 */ |
285 | tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); | 286 | tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); |
@@ -299,18 +300,18 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
299 | printk("\n"); | 300 | printk("\n"); |
300 | } | 301 | } |
301 | #endif | 302 | #endif |
302 | if (key->local->ops->update_tkip_key && | 303 | } |
303 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 304 | if (key->local->ops->update_tkip_key && |
304 | static const u8 bcast[ETH_ALEN] = | 305 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && |
305 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 306 | key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) { |
306 | const u8 *sta_addr = key->sta->sta.addr; | 307 | struct ieee80211_sub_if_data *sdata = key->sdata; |
307 | 308 | ||
308 | if (is_multicast_ether_addr(ra)) | 309 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
309 | sta_addr = bcast; | 310 | sdata = container_of(key->sdata->bss, |
310 | 311 | struct ieee80211_sub_if_data, u.ap); | |
311 | drv_update_tkip_key(key->local, &key->conf, sta_addr, | 312 | drv_update_tkip_key(key->local, sdata, &key->conf, key->sta, |
312 | iv32, key->u.tkip.rx[queue].p1k); | 313 | iv32, key->u.tkip.rx[queue].p1k); |
313 | } | 314 | key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; |
314 | } | 315 | } |
315 | 316 | ||
316 | tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); | 317 | tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ac210b586702..cbe53ed4fb0b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -180,6 +180,71 @@ static int inline is_ieee80211_device(struct ieee80211_local *local, | |||
180 | } | 180 | } |
181 | 181 | ||
182 | /* tx handlers */ | 182 | /* tx handlers */ |
183 | static ieee80211_tx_result debug_noinline | ||
184 | ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) | ||
185 | { | ||
186 | struct ieee80211_local *local = tx->local; | ||
187 | struct ieee80211_if_managed *ifmgd; | ||
188 | |||
189 | /* driver doesn't support power save */ | ||
190 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) | ||
191 | return TX_CONTINUE; | ||
192 | |||
193 | /* hardware does dynamic power save */ | ||
194 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | ||
195 | return TX_CONTINUE; | ||
196 | |||
197 | /* dynamic power save disabled */ | ||
198 | if (local->hw.conf.dynamic_ps_timeout <= 0) | ||
199 | return TX_CONTINUE; | ||
200 | |||
201 | /* we are scanning, don't enable power save */ | ||
202 | if (local->scanning) | ||
203 | return TX_CONTINUE; | ||
204 | |||
205 | if (!local->ps_sdata) | ||
206 | return TX_CONTINUE; | ||
207 | |||
208 | /* No point if we're going to suspend */ | ||
209 | if (local->quiescing) | ||
210 | return TX_CONTINUE; | ||
211 | |||
212 | /* dynamic ps is supported only in managed mode */ | ||
213 | if (tx->sdata->vif.type != NL80211_IFTYPE_STATION) | ||
214 | return TX_CONTINUE; | ||
215 | |||
216 | ifmgd = &tx->sdata->u.mgd; | ||
217 | |||
218 | /* | ||
219 | * Don't wakeup from power save if u-apsd is enabled, voip ac has | ||
220 | * u-apsd enabled and the frame is in voip class. This effectively | ||
221 | * means that even if all access categories have u-apsd enabled, in | ||
222 | * practise u-apsd is only used with the voip ac. This is a | ||
223 | * workaround for the case when received voip class packets do not | ||
224 | * have correct qos tag for some reason, due the network or the | ||
225 | * peer application. | ||
226 | * | ||
227 | * Note: local->uapsd_queues access is racy here. If the value is | ||
228 | * changed via debugfs, user needs to reassociate manually to have | ||
229 | * everything in sync. | ||
230 | */ | ||
231 | if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) | ||
232 | && (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) | ||
233 | && skb_get_queue_mapping(tx->skb) == 0) | ||
234 | return TX_CONTINUE; | ||
235 | |||
236 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
237 | ieee80211_stop_queues_by_reason(&local->hw, | ||
238 | IEEE80211_QUEUE_STOP_REASON_PS); | ||
239 | ieee80211_queue_work(&local->hw, | ||
240 | &local->dynamic_ps_disable_work); | ||
241 | } | ||
242 | |||
243 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
244 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | ||
245 | |||
246 | return TX_CONTINUE; | ||
247 | } | ||
183 | 248 | ||
184 | static ieee80211_tx_result debug_noinline | 249 | static ieee80211_tx_result debug_noinline |
185 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | 250 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) |
@@ -223,7 +288,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
223 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 288 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
224 | printk(KERN_DEBUG "%s: dropped data frame to not " | 289 | printk(KERN_DEBUG "%s: dropped data frame to not " |
225 | "associated station %pM\n", | 290 | "associated station %pM\n", |
226 | tx->dev->name, hdr->addr1); | 291 | tx->sdata->name, hdr->addr1); |
227 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 292 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
228 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); | 293 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); |
229 | return TX_DROP; | 294 | return TX_DROP; |
@@ -331,7 +396,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
331 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 396 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
332 | if (net_ratelimit()) | 397 | if (net_ratelimit()) |
333 | printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n", | 398 | printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n", |
334 | tx->dev->name); | 399 | tx->sdata->name); |
335 | #endif | 400 | #endif |
336 | dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); | 401 | dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); |
337 | } else | 402 | } else |
@@ -391,7 +456,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
391 | if (net_ratelimit()) { | 456 | if (net_ratelimit()) { |
392 | printk(KERN_DEBUG "%s: STA %pM TX " | 457 | printk(KERN_DEBUG "%s: STA %pM TX " |
393 | "buffer full - dropping oldest frame\n", | 458 | "buffer full - dropping oldest frame\n", |
394 | tx->dev->name, sta->sta.addr); | 459 | tx->sdata->name, sta->sta.addr); |
395 | } | 460 | } |
396 | #endif | 461 | #endif |
397 | dev_kfree_skb(old); | 462 | dev_kfree_skb(old); |
@@ -416,7 +481,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
416 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 481 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
417 | else if (unlikely(staflags & WLAN_STA_PS_STA)) { | 482 | else if (unlikely(staflags & WLAN_STA_PS_STA)) { |
418 | printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " | 483 | printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " |
419 | "set -> send frame\n", tx->dev->name, | 484 | "set -> send frame\n", tx->sdata->name, |
420 | sta->sta.addr); | 485 | sta->sta.addr); |
421 | } | 486 | } |
422 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 487 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
@@ -464,6 +529,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
464 | tx->key = NULL; | 529 | tx->key = NULL; |
465 | 530 | ||
466 | if (tx->key) { | 531 | if (tx->key) { |
532 | bool skip_hw = false; | ||
533 | |||
467 | tx->key->tx_rx_count++; | 534 | tx->key->tx_rx_count++; |
468 | /* TODO: add threshold stuff again */ | 535 | /* TODO: add threshold stuff again */ |
469 | 536 | ||
@@ -480,16 +547,32 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
480 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, | 547 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, |
481 | tx->skb)) | 548 | tx->skb)) |
482 | tx->key = NULL; | 549 | tx->key = NULL; |
550 | else | ||
551 | skip_hw = (tx->key->conf.flags & | ||
552 | IEEE80211_KEY_FLAG_SW_MGMT) && | ||
553 | ieee80211_is_mgmt(hdr->frame_control); | ||
483 | break; | 554 | break; |
484 | case ALG_AES_CMAC: | 555 | case ALG_AES_CMAC: |
485 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 556 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
486 | tx->key = NULL; | 557 | tx->key = NULL; |
487 | break; | 558 | break; |
488 | } | 559 | } |
560 | |||
561 | if (!skip_hw && tx->key && | ||
562 | tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | ||
563 | info->control.hw_key = &tx->key->conf; | ||
489 | } | 564 | } |
490 | 565 | ||
491 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 566 | return TX_CONTINUE; |
492 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 567 | } |
568 | |||
569 | static ieee80211_tx_result debug_noinline | ||
570 | ieee80211_tx_h_sta(struct ieee80211_tx_data *tx) | ||
571 | { | ||
572 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
573 | |||
574 | if (tx->sta && tx->sta->uploaded) | ||
575 | info->control.sta = &tx->sta->sta; | ||
493 | 576 | ||
494 | return TX_CONTINUE; | 577 | return TX_CONTINUE; |
495 | } | 578 | } |
@@ -519,7 +602,12 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
519 | txrc.bss_conf = &tx->sdata->vif.bss_conf; | 602 | txrc.bss_conf = &tx->sdata->vif.bss_conf; |
520 | txrc.skb = tx->skb; | 603 | txrc.skb = tx->skb; |
521 | txrc.reported_rate.idx = -1; | 604 | txrc.reported_rate.idx = -1; |
522 | txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; | 605 | txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[tx->channel->band]; |
606 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) | ||
607 | txrc.max_rate_idx = -1; | ||
608 | else | ||
609 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | ||
610 | txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP; | ||
523 | 611 | ||
524 | /* set up RTS protection if desired */ | 612 | /* set up RTS protection if desired */ |
525 | if (len > tx->local->hw.wiphy->rts_threshold) { | 613 | if (len > tx->local->hw.wiphy->rts_threshold) { |
@@ -549,7 +637,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
549 | "%s: Dropped data frame as no usable bitrate found while " | 637 | "%s: Dropped data frame as no usable bitrate found while " |
550 | "scanning and associated. Target station: " | 638 | "scanning and associated. Target station: " |
551 | "%pM on %d GHz band\n", | 639 | "%pM on %d GHz band\n", |
552 | tx->dev->name, hdr->addr1, | 640 | tx->sdata->name, hdr->addr1, |
553 | tx->channel->band ? 5 : 2)) | 641 | tx->channel->band ? 5 : 2)) |
554 | return TX_DROP; | 642 | return TX_DROP; |
555 | 643 | ||
@@ -664,17 +752,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
664 | } | 752 | } |
665 | 753 | ||
666 | static ieee80211_tx_result debug_noinline | 754 | static ieee80211_tx_result debug_noinline |
667 | ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | ||
668 | { | ||
669 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
670 | |||
671 | if (tx->sta) | ||
672 | info->control.sta = &tx->sta->sta; | ||
673 | |||
674 | return TX_CONTINUE; | ||
675 | } | ||
676 | |||
677 | static ieee80211_tx_result debug_noinline | ||
678 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | 755 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) |
679 | { | 756 | { |
680 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 757 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
@@ -933,7 +1010,8 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
933 | (struct ieee80211_radiotap_header *) skb->data; | 1010 | (struct ieee80211_radiotap_header *) skb->data; |
934 | struct ieee80211_supported_band *sband; | 1011 | struct ieee80211_supported_band *sband; |
935 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1012 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
936 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); | 1013 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, |
1014 | NULL); | ||
937 | 1015 | ||
938 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 1016 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
939 | 1017 | ||
@@ -969,7 +1047,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
969 | * because it will be recomputed and added | 1047 | * because it will be recomputed and added |
970 | * on transmission | 1048 | * on transmission |
971 | */ | 1049 | */ |
972 | if (skb->len < (iterator.max_length + FCS_LEN)) | 1050 | if (skb->len < (iterator._max_length + FCS_LEN)) |
973 | return false; | 1051 | return false; |
974 | 1052 | ||
975 | skb_trim(skb, skb->len - FCS_LEN); | 1053 | skb_trim(skb, skb->len - FCS_LEN); |
@@ -996,10 +1074,10 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
996 | 1074 | ||
997 | /* | 1075 | /* |
998 | * remove the radiotap header | 1076 | * remove the radiotap header |
999 | * iterator->max_length was sanity-checked against | 1077 | * iterator->_max_length was sanity-checked against |
1000 | * skb->len by iterator init | 1078 | * skb->len by iterator init |
1001 | */ | 1079 | */ |
1002 | skb_pull(skb, iterator.max_length); | 1080 | skb_pull(skb, iterator._max_length); |
1003 | 1081 | ||
1004 | return true; | 1082 | return true; |
1005 | } | 1083 | } |
@@ -1021,7 +1099,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1021 | 1099 | ||
1022 | memset(tx, 0, sizeof(*tx)); | 1100 | memset(tx, 0, sizeof(*tx)); |
1023 | tx->skb = skb; | 1101 | tx->skb = skb; |
1024 | tx->dev = sdata->dev; /* use original interface */ | ||
1025 | tx->local = local; | 1102 | tx->local = local; |
1026 | tx->sdata = sdata; | 1103 | tx->sdata = sdata; |
1027 | tx->channel = local->hw.conf.channel; | 1104 | tx->channel = local->hw.conf.channel; |
@@ -1032,7 +1109,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1032 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 1109 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
1033 | 1110 | ||
1034 | /* process and remove the injection radiotap header */ | 1111 | /* process and remove the injection radiotap header */ |
1035 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { | 1112 | if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) { |
1036 | if (!__ieee80211_parse_tx_radiotap(tx, skb)) | 1113 | if (!__ieee80211_parse_tx_radiotap(tx, skb)) |
1037 | return TX_DROP; | 1114 | return TX_DROP; |
1038 | 1115 | ||
@@ -1041,6 +1118,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1041 | * the radiotap header that was present and pre-filled | 1118 | * the radiotap header that was present and pre-filled |
1042 | * 'tx' with tx control information. | 1119 | * 'tx' with tx control information. |
1043 | */ | 1120 | */ |
1121 | info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP; | ||
1044 | } | 1122 | } |
1045 | 1123 | ||
1046 | /* | 1124 | /* |
@@ -1052,10 +1130,15 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1052 | 1130 | ||
1053 | hdr = (struct ieee80211_hdr *) skb->data; | 1131 | hdr = (struct ieee80211_hdr *) skb->data; |
1054 | 1132 | ||
1055 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1133 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { |
1056 | tx->sta = rcu_dereference(sdata->u.vlan.sta); | 1134 | tx->sta = rcu_dereference(sdata->u.vlan.sta); |
1135 | if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) | ||
1136 | return TX_DROP; | ||
1137 | } else if (info->flags & IEEE80211_TX_CTL_INJECTED) { | ||
1138 | tx->sta = sta_info_get_bss(sdata, hdr->addr1); | ||
1139 | } | ||
1057 | if (!tx->sta) | 1140 | if (!tx->sta) |
1058 | tx->sta = sta_info_get(local, hdr->addr1); | 1141 | tx->sta = sta_info_get(sdata, hdr->addr1); |
1059 | 1142 | ||
1060 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && | 1143 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && |
1061 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { | 1144 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { |
@@ -1207,6 +1290,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1207 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | 1290 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) |
1208 | { | 1291 | { |
1209 | struct sk_buff *skb = tx->skb; | 1292 | struct sk_buff *skb = tx->skb; |
1293 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1210 | ieee80211_tx_result res = TX_DROP; | 1294 | ieee80211_tx_result res = TX_DROP; |
1211 | 1295 | ||
1212 | #define CALL_TXH(txh) \ | 1296 | #define CALL_TXH(txh) \ |
@@ -1216,13 +1300,18 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1216 | goto txh_done; \ | 1300 | goto txh_done; \ |
1217 | } while (0) | 1301 | } while (0) |
1218 | 1302 | ||
1303 | CALL_TXH(ieee80211_tx_h_dynamic_ps); | ||
1219 | CALL_TXH(ieee80211_tx_h_check_assoc); | 1304 | CALL_TXH(ieee80211_tx_h_check_assoc); |
1220 | CALL_TXH(ieee80211_tx_h_ps_buf); | 1305 | CALL_TXH(ieee80211_tx_h_ps_buf); |
1221 | CALL_TXH(ieee80211_tx_h_select_key); | 1306 | CALL_TXH(ieee80211_tx_h_select_key); |
1222 | CALL_TXH(ieee80211_tx_h_michael_mic_add); | 1307 | CALL_TXH(ieee80211_tx_h_sta); |
1223 | if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) | 1308 | if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) |
1224 | CALL_TXH(ieee80211_tx_h_rate_ctrl); | 1309 | CALL_TXH(ieee80211_tx_h_rate_ctrl); |
1225 | CALL_TXH(ieee80211_tx_h_misc); | 1310 | |
1311 | if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) | ||
1312 | goto txh_done; | ||
1313 | |||
1314 | CALL_TXH(ieee80211_tx_h_michael_mic_add); | ||
1226 | CALL_TXH(ieee80211_tx_h_sequence); | 1315 | CALL_TXH(ieee80211_tx_h_sequence); |
1227 | CALL_TXH(ieee80211_tx_h_fragment); | 1316 | CALL_TXH(ieee80211_tx_h_fragment); |
1228 | /* handlers after fragment must be aware of tx info fragmentation! */ | 1317 | /* handlers after fragment must be aware of tx info fragmentation! */ |
@@ -1398,34 +1487,6 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1398 | return 0; | 1487 | return 0; |
1399 | } | 1488 | } |
1400 | 1489 | ||
1401 | static bool need_dynamic_ps(struct ieee80211_local *local) | ||
1402 | { | ||
1403 | /* driver doesn't support power save */ | ||
1404 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) | ||
1405 | return false; | ||
1406 | |||
1407 | /* hardware does dynamic power save */ | ||
1408 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | ||
1409 | return false; | ||
1410 | |||
1411 | /* dynamic power save disabled */ | ||
1412 | if (local->hw.conf.dynamic_ps_timeout <= 0) | ||
1413 | return false; | ||
1414 | |||
1415 | /* we are scanning, don't enable power save */ | ||
1416 | if (local->scanning) | ||
1417 | return false; | ||
1418 | |||
1419 | if (!local->ps_sdata) | ||
1420 | return false; | ||
1421 | |||
1422 | /* No point if we're going to suspend */ | ||
1423 | if (local->quiescing) | ||
1424 | return false; | ||
1425 | |||
1426 | return true; | ||
1427 | } | ||
1428 | |||
1429 | static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | 1490 | static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, |
1430 | struct sk_buff *skb) | 1491 | struct sk_buff *skb) |
1431 | { | 1492 | { |
@@ -1436,25 +1497,14 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1436 | int headroom; | 1497 | int headroom; |
1437 | bool may_encrypt; | 1498 | bool may_encrypt; |
1438 | 1499 | ||
1439 | if (need_dynamic_ps(local)) { | ||
1440 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
1441 | ieee80211_stop_queues_by_reason(&local->hw, | ||
1442 | IEEE80211_QUEUE_STOP_REASON_PS); | ||
1443 | ieee80211_queue_work(&local->hw, | ||
1444 | &local->dynamic_ps_disable_work); | ||
1445 | } | ||
1446 | |||
1447 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
1448 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | ||
1449 | } | ||
1450 | |||
1451 | rcu_read_lock(); | 1500 | rcu_read_lock(); |
1452 | 1501 | ||
1453 | if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { | 1502 | if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { |
1454 | int hdrlen; | 1503 | int hdrlen; |
1455 | u16 len_rthdr; | 1504 | u16 len_rthdr; |
1456 | 1505 | ||
1457 | info->flags |= IEEE80211_TX_CTL_INJECTED; | 1506 | info->flags |= IEEE80211_TX_CTL_INJECTED | |
1507 | IEEE80211_TX_INTFL_HAS_RADIOTAP; | ||
1458 | 1508 | ||
1459 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | 1509 | len_rthdr = ieee80211_get_radiotap_len(skb->data); |
1460 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); | 1510 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); |
@@ -1474,11 +1524,11 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1474 | 1524 | ||
1475 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, | 1525 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, |
1476 | list) { | 1526 | list) { |
1477 | if (!netif_running(tmp_sdata->dev)) | 1527 | if (!ieee80211_sdata_running(tmp_sdata)) |
1478 | continue; | 1528 | continue; |
1479 | if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) | 1529 | if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) |
1480 | continue; | 1530 | continue; |
1481 | if (compare_ether_addr(tmp_sdata->dev->dev_addr, | 1531 | if (compare_ether_addr(tmp_sdata->vif.addr, |
1482 | hdr->addr2) == 0) { | 1532 | hdr->addr2) == 0) { |
1483 | sdata = tmp_sdata; | 1533 | sdata = tmp_sdata; |
1484 | break; | 1534 | break; |
@@ -1642,7 +1692,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1642 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1692 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1643 | /* RA TA DA SA */ | 1693 | /* RA TA DA SA */ |
1644 | memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN); | 1694 | memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN); |
1645 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1695 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1646 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1696 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1647 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1697 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1648 | hdrlen = 30; | 1698 | hdrlen = 30; |
@@ -1656,7 +1706,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1656 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 1706 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
1657 | /* DA BSSID SA */ | 1707 | /* DA BSSID SA */ |
1658 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1708 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1659 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1709 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1660 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); | 1710 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); |
1661 | hdrlen = 24; | 1711 | hdrlen = 24; |
1662 | break; | 1712 | break; |
@@ -1664,7 +1714,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1664 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1714 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1665 | /* RA TA DA SA */ | 1715 | /* RA TA DA SA */ |
1666 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); | 1716 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); |
1667 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1717 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1668 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1718 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1669 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1719 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1670 | hdrlen = 30; | 1720 | hdrlen = 30; |
@@ -1678,8 +1728,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1678 | goto fail; | 1728 | goto fail; |
1679 | } | 1729 | } |
1680 | 1730 | ||
1681 | if (compare_ether_addr(dev->dev_addr, | 1731 | if (compare_ether_addr(sdata->vif.addr, |
1682 | skb->data + ETH_ALEN) == 0) { | 1732 | skb->data + ETH_ALEN) == 0) { |
1683 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1733 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1684 | skb->data, skb->data + ETH_ALEN); | 1734 | skb->data, skb->data + ETH_ALEN); |
1685 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1735 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
@@ -1709,7 +1759,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1709 | } | 1759 | } |
1710 | } | 1760 | } |
1711 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1761 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1712 | mesh_da, dev->dev_addr); | 1762 | mesh_da, sdata->vif.addr); |
1713 | rcu_read_unlock(); | 1763 | rcu_read_unlock(); |
1714 | if (is_mesh_mcast) | 1764 | if (is_mesh_mcast) |
1715 | meshhdrlen = | 1765 | meshhdrlen = |
@@ -1734,7 +1784,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1734 | if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) { | 1784 | if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) { |
1735 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1785 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1736 | /* RA TA DA SA */ | 1786 | /* RA TA DA SA */ |
1737 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1787 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1738 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1788 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1739 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1789 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1740 | hdrlen = 30; | 1790 | hdrlen = 30; |
@@ -1765,9 +1815,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1765 | */ | 1815 | */ |
1766 | if (!is_multicast_ether_addr(hdr.addr1)) { | 1816 | if (!is_multicast_ether_addr(hdr.addr1)) { |
1767 | rcu_read_lock(); | 1817 | rcu_read_lock(); |
1768 | sta = sta_info_get(local, hdr.addr1); | 1818 | sta = sta_info_get(sdata, hdr.addr1); |
1769 | /* XXX: in the future, use sdata to look up the sta */ | 1819 | if (sta) |
1770 | if (sta && sta->sdata == sdata) | ||
1771 | sta_flags = get_sta_flags(sta); | 1820 | sta_flags = get_sta_flags(sta); |
1772 | rcu_read_unlock(); | 1821 | rcu_read_unlock(); |
1773 | } | 1822 | } |
@@ -1786,7 +1835,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1786 | unlikely(!is_multicast_ether_addr(hdr.addr1) && | 1835 | unlikely(!is_multicast_ether_addr(hdr.addr1) && |
1787 | !(sta_flags & WLAN_STA_AUTHORIZED) && | 1836 | !(sta_flags & WLAN_STA_AUTHORIZED) && |
1788 | !(ethertype == ETH_P_PAE && | 1837 | !(ethertype == ETH_P_PAE && |
1789 | compare_ether_addr(dev->dev_addr, | 1838 | compare_ether_addr(sdata->vif.addr, |
1790 | skb->data + ETH_ALEN) == 0))) { | 1839 | skb->data + ETH_ALEN) == 0))) { |
1791 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1840 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1792 | if (net_ratelimit()) | 1841 | if (net_ratelimit()) |
@@ -1926,7 +1975,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1926 | ieee80211_tx(sdata, skb, true); | 1975 | ieee80211_tx(sdata, skb, true); |
1927 | } else { | 1976 | } else { |
1928 | hdr = (struct ieee80211_hdr *)skb->data; | 1977 | hdr = (struct ieee80211_hdr *)skb->data; |
1929 | sta = sta_info_get(local, hdr->addr1); | 1978 | sta = sta_info_get(sdata, hdr->addr1); |
1930 | 1979 | ||
1931 | ret = __ieee80211_tx(local, &skb, sta, true); | 1980 | ret = __ieee80211_tx(local, &skb, sta, true); |
1932 | if (ret != IEEE80211_TX_OK) | 1981 | if (ret != IEEE80211_TX_OK) |
@@ -2062,6 +2111,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2062 | struct beacon_data *beacon; | 2111 | struct beacon_data *beacon; |
2063 | struct ieee80211_supported_band *sband; | 2112 | struct ieee80211_supported_band *sband; |
2064 | enum ieee80211_band band = local->hw.conf.channel->band; | 2113 | enum ieee80211_band band = local->hw.conf.channel->band; |
2114 | struct ieee80211_tx_rate_control txrc; | ||
2065 | 2115 | ||
2066 | sband = local->hw.wiphy->bands[band]; | 2116 | sband = local->hw.wiphy->bands[band]; |
2067 | 2117 | ||
@@ -2150,8 +2200,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2150 | mgmt->frame_control = | 2200 | mgmt->frame_control = |
2151 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); | 2201 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
2152 | memset(mgmt->da, 0xff, ETH_ALEN); | 2202 | memset(mgmt->da, 0xff, ETH_ALEN); |
2153 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 2203 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
2154 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 2204 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
2155 | mgmt->u.beacon.beacon_int = | 2205 | mgmt->u.beacon.beacon_int = |
2156 | cpu_to_le16(sdata->vif.bss_conf.beacon_int); | 2206 | cpu_to_le16(sdata->vif.bss_conf.beacon_int); |
2157 | mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ | 2207 | mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ |
@@ -2169,21 +2219,25 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2169 | info = IEEE80211_SKB_CB(skb); | 2219 | info = IEEE80211_SKB_CB(skb); |
2170 | 2220 | ||
2171 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 2221 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
2222 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
2172 | info->band = band; | 2223 | info->band = band; |
2173 | /* | 2224 | |
2174 | * XXX: For now, always use the lowest rate | 2225 | memset(&txrc, 0, sizeof(txrc)); |
2175 | */ | 2226 | txrc.hw = hw; |
2176 | info->control.rates[0].idx = 0; | 2227 | txrc.sband = sband; |
2177 | info->control.rates[0].count = 1; | 2228 | txrc.bss_conf = &sdata->vif.bss_conf; |
2178 | info->control.rates[1].idx = -1; | 2229 | txrc.skb = skb; |
2179 | info->control.rates[2].idx = -1; | 2230 | txrc.reported_rate.idx = -1; |
2180 | info->control.rates[3].idx = -1; | 2231 | txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; |
2181 | info->control.rates[4].idx = -1; | 2232 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) |
2182 | BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); | 2233 | txrc.max_rate_idx = -1; |
2234 | else | ||
2235 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | ||
2236 | txrc.ap = true; | ||
2237 | rate_control_get_rate(sdata, NULL, &txrc); | ||
2183 | 2238 | ||
2184 | info->control.vif = vif; | 2239 | info->control.vif = vif; |
2185 | 2240 | ||
2186 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
2187 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 2241 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
2188 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | 2242 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; |
2189 | out: | 2243 | out: |
@@ -2192,6 +2246,134 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2192 | } | 2246 | } |
2193 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); | 2247 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); |
2194 | 2248 | ||
2249 | struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, | ||
2250 | struct ieee80211_vif *vif) | ||
2251 | { | ||
2252 | struct ieee80211_sub_if_data *sdata; | ||
2253 | struct ieee80211_if_managed *ifmgd; | ||
2254 | struct ieee80211_pspoll *pspoll; | ||
2255 | struct ieee80211_local *local; | ||
2256 | struct sk_buff *skb; | ||
2257 | |||
2258 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | ||
2259 | return NULL; | ||
2260 | |||
2261 | sdata = vif_to_sdata(vif); | ||
2262 | ifmgd = &sdata->u.mgd; | ||
2263 | local = sdata->local; | ||
2264 | |||
2265 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); | ||
2266 | if (!skb) { | ||
2267 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | ||
2268 | "pspoll template\n", sdata->name); | ||
2269 | return NULL; | ||
2270 | } | ||
2271 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
2272 | |||
2273 | pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll)); | ||
2274 | memset(pspoll, 0, sizeof(*pspoll)); | ||
2275 | pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | | ||
2276 | IEEE80211_STYPE_PSPOLL); | ||
2277 | pspoll->aid = cpu_to_le16(ifmgd->aid); | ||
2278 | |||
2279 | /* aid in PS-Poll has its two MSBs each set to 1 */ | ||
2280 | pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); | ||
2281 | |||
2282 | memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); | ||
2283 | memcpy(pspoll->ta, vif->addr, ETH_ALEN); | ||
2284 | |||
2285 | return skb; | ||
2286 | } | ||
2287 | EXPORT_SYMBOL(ieee80211_pspoll_get); | ||
2288 | |||
2289 | struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | ||
2290 | struct ieee80211_vif *vif) | ||
2291 | { | ||
2292 | struct ieee80211_hdr_3addr *nullfunc; | ||
2293 | struct ieee80211_sub_if_data *sdata; | ||
2294 | struct ieee80211_if_managed *ifmgd; | ||
2295 | struct ieee80211_local *local; | ||
2296 | struct sk_buff *skb; | ||
2297 | |||
2298 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | ||
2299 | return NULL; | ||
2300 | |||
2301 | sdata = vif_to_sdata(vif); | ||
2302 | ifmgd = &sdata->u.mgd; | ||
2303 | local = sdata->local; | ||
2304 | |||
2305 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc)); | ||
2306 | if (!skb) { | ||
2307 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " | ||
2308 | "template\n", sdata->name); | ||
2309 | return NULL; | ||
2310 | } | ||
2311 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
2312 | |||
2313 | nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb, | ||
2314 | sizeof(*nullfunc)); | ||
2315 | memset(nullfunc, 0, sizeof(*nullfunc)); | ||
2316 | nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
2317 | IEEE80211_STYPE_NULLFUNC | | ||
2318 | IEEE80211_FCTL_TODS); | ||
2319 | memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN); | ||
2320 | memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); | ||
2321 | memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN); | ||
2322 | |||
2323 | return skb; | ||
2324 | } | ||
2325 | EXPORT_SYMBOL(ieee80211_nullfunc_get); | ||
2326 | |||
2327 | struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | ||
2328 | struct ieee80211_vif *vif, | ||
2329 | const u8 *ssid, size_t ssid_len, | ||
2330 | const u8 *ie, size_t ie_len) | ||
2331 | { | ||
2332 | struct ieee80211_sub_if_data *sdata; | ||
2333 | struct ieee80211_local *local; | ||
2334 | struct ieee80211_hdr_3addr *hdr; | ||
2335 | struct sk_buff *skb; | ||
2336 | size_t ie_ssid_len; | ||
2337 | u8 *pos; | ||
2338 | |||
2339 | sdata = vif_to_sdata(vif); | ||
2340 | local = sdata->local; | ||
2341 | ie_ssid_len = 2 + ssid_len; | ||
2342 | |||
2343 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + | ||
2344 | ie_ssid_len + ie_len); | ||
2345 | if (!skb) { | ||
2346 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | ||
2347 | "request template\n", sdata->name); | ||
2348 | return NULL; | ||
2349 | } | ||
2350 | |||
2351 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
2352 | |||
2353 | hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr)); | ||
2354 | memset(hdr, 0, sizeof(*hdr)); | ||
2355 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
2356 | IEEE80211_STYPE_PROBE_REQ); | ||
2357 | memset(hdr->addr1, 0xff, ETH_ALEN); | ||
2358 | memcpy(hdr->addr2, vif->addr, ETH_ALEN); | ||
2359 | memset(hdr->addr3, 0xff, ETH_ALEN); | ||
2360 | |||
2361 | pos = skb_put(skb, ie_ssid_len); | ||
2362 | *pos++ = WLAN_EID_SSID; | ||
2363 | *pos++ = ssid_len; | ||
2364 | if (ssid) | ||
2365 | memcpy(pos, ssid, ssid_len); | ||
2366 | pos += ssid_len; | ||
2367 | |||
2368 | if (ie) { | ||
2369 | pos = skb_put(skb, ie_len); | ||
2370 | memcpy(pos, ie, ie_len); | ||
2371 | } | ||
2372 | |||
2373 | return skb; | ||
2374 | } | ||
2375 | EXPORT_SYMBOL(ieee80211_probereq_get); | ||
2376 | |||
2195 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2377 | void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2196 | const void *frame, size_t frame_len, | 2378 | const void *frame, size_t frame_len, |
2197 | const struct ieee80211_tx_info *frame_txctl, | 2379 | const struct ieee80211_tx_info *frame_txctl, |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3848140313f5..c453226f06b2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
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/wireless.h> | ||
22 | #include <linux/bitmap.h> | 21 | #include <linux/bitmap.h> |
23 | #include <linux/crc32.h> | 22 | #include <linux/crc32.h> |
24 | #include <net/net_namespace.h> | 23 | #include <net/net_namespace.h> |
@@ -480,8 +479,8 @@ void ieee80211_iterate_active_interfaces( | |||
480 | case NL80211_IFTYPE_MESH_POINT: | 479 | case NL80211_IFTYPE_MESH_POINT: |
481 | break; | 480 | break; |
482 | } | 481 | } |
483 | if (netif_running(sdata->dev)) | 482 | if (ieee80211_sdata_running(sdata)) |
484 | iterator(data, sdata->dev->dev_addr, | 483 | iterator(data, sdata->vif.addr, |
485 | &sdata->vif); | 484 | &sdata->vif); |
486 | } | 485 | } |
487 | 486 | ||
@@ -514,8 +513,8 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
514 | case NL80211_IFTYPE_MESH_POINT: | 513 | case NL80211_IFTYPE_MESH_POINT: |
515 | break; | 514 | break; |
516 | } | 515 | } |
517 | if (netif_running(sdata->dev)) | 516 | if (ieee80211_sdata_running(sdata)) |
518 | iterator(data, sdata->dev->dev_addr, | 517 | iterator(data, sdata->vif.addr, |
519 | &sdata->vif); | 518 | &sdata->vif); |
520 | } | 519 | } |
521 | 520 | ||
@@ -793,6 +792,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
793 | break; | 792 | break; |
794 | } | 793 | } |
795 | 794 | ||
795 | qparam.uapsd = false; | ||
796 | |||
796 | drv_conf_tx(local, queue, &qparam); | 797 | drv_conf_tx(local, queue, &qparam); |
797 | } | 798 | } |
798 | } | 799 | } |
@@ -860,7 +861,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
860 | sizeof(*mgmt) + 6 + extra_len); | 861 | sizeof(*mgmt) + 6 + extra_len); |
861 | if (!skb) { | 862 | if (!skb) { |
862 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " | 863 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " |
863 | "frame\n", sdata->dev->name); | 864 | "frame\n", sdata->name); |
864 | return; | 865 | return; |
865 | } | 866 | } |
866 | skb_reserve(skb, local->hw.extra_tx_headroom); | 867 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -870,7 +871,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
870 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 871 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
871 | IEEE80211_STYPE_AUTH); | 872 | IEEE80211_STYPE_AUTH); |
872 | memcpy(mgmt->da, bssid, ETH_ALEN); | 873 | memcpy(mgmt->da, bssid, ETH_ALEN); |
873 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 874 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
874 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | 875 | memcpy(mgmt->bssid, bssid, ETH_ALEN); |
875 | mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); | 876 | mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); |
876 | mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); | 877 | mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); |
@@ -893,43 +894,87 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
893 | enum ieee80211_band band) | 894 | enum ieee80211_band band) |
894 | { | 895 | { |
895 | struct ieee80211_supported_band *sband; | 896 | struct ieee80211_supported_band *sband; |
896 | u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; | 897 | u8 *pos; |
897 | int i; | 898 | size_t offset = 0, noffset; |
899 | int supp_rates_len, i; | ||
898 | 900 | ||
899 | sband = local->hw.wiphy->bands[band]; | 901 | sband = local->hw.wiphy->bands[band]; |
900 | 902 | ||
901 | pos = buffer; | 903 | pos = buffer; |
902 | 904 | ||
905 | supp_rates_len = min_t(int, sband->n_bitrates, 8); | ||
906 | |||
903 | *pos++ = WLAN_EID_SUPP_RATES; | 907 | *pos++ = WLAN_EID_SUPP_RATES; |
904 | supp_rates_len = pos; | 908 | *pos++ = supp_rates_len; |
905 | *pos++ = 0; | 909 | |
906 | 910 | for (i = 0; i < supp_rates_len; i++) { | |
907 | for (i = 0; i < sband->n_bitrates; i++) { | 911 | int rate = sband->bitrates[i].bitrate; |
908 | struct ieee80211_rate *rate = &sband->bitrates[i]; | 912 | *pos++ = (u8) (rate / 5); |
909 | 913 | } | |
910 | if (esupp_rates_len) { | 914 | |
911 | *esupp_rates_len += 1; | 915 | /* insert "request information" if in custom IEs */ |
912 | } else if (*supp_rates_len == 8) { | 916 | if (ie && ie_len) { |
913 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 917 | static const u8 before_extrates[] = { |
914 | esupp_rates_len = pos; | 918 | WLAN_EID_SSID, |
915 | *pos++ = 1; | 919 | WLAN_EID_SUPP_RATES, |
916 | } else | 920 | WLAN_EID_REQUEST, |
917 | *supp_rates_len += 1; | 921 | }; |
922 | noffset = ieee80211_ie_split(ie, ie_len, | ||
923 | before_extrates, | ||
924 | ARRAY_SIZE(before_extrates), | ||
925 | offset); | ||
926 | memcpy(pos, ie + offset, noffset - offset); | ||
927 | pos += noffset - offset; | ||
928 | offset = noffset; | ||
929 | } | ||
930 | |||
931 | if (sband->n_bitrates > i) { | ||
932 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
933 | *pos++ = sband->n_bitrates - i; | ||
934 | |||
935 | for (; i < sband->n_bitrates; i++) { | ||
936 | int rate = sband->bitrates[i].bitrate; | ||
937 | *pos++ = (u8) (rate / 5); | ||
938 | } | ||
939 | } | ||
918 | 940 | ||
919 | *pos++ = rate->bitrate / 5; | 941 | /* insert custom IEs that go before HT */ |
942 | if (ie && ie_len) { | ||
943 | static const u8 before_ht[] = { | ||
944 | WLAN_EID_SSID, | ||
945 | WLAN_EID_SUPP_RATES, | ||
946 | WLAN_EID_REQUEST, | ||
947 | WLAN_EID_EXT_SUPP_RATES, | ||
948 | WLAN_EID_DS_PARAMS, | ||
949 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
950 | }; | ||
951 | noffset = ieee80211_ie_split(ie, ie_len, | ||
952 | before_ht, ARRAY_SIZE(before_ht), | ||
953 | offset); | ||
954 | memcpy(pos, ie + offset, noffset - offset); | ||
955 | pos += noffset - offset; | ||
956 | offset = noffset; | ||
920 | } | 957 | } |
921 | 958 | ||
922 | if (sband->ht_cap.ht_supported) { | 959 | if (sband->ht_cap.ht_supported) { |
923 | __le16 tmp = cpu_to_le16(sband->ht_cap.cap); | 960 | u16 cap = sband->ht_cap.cap; |
961 | __le16 tmp; | ||
962 | |||
963 | if (ieee80211_disable_40mhz_24ghz && | ||
964 | sband->band == IEEE80211_BAND_2GHZ) { | ||
965 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
966 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
967 | } | ||
924 | 968 | ||
925 | *pos++ = WLAN_EID_HT_CAPABILITY; | 969 | *pos++ = WLAN_EID_HT_CAPABILITY; |
926 | *pos++ = sizeof(struct ieee80211_ht_cap); | 970 | *pos++ = sizeof(struct ieee80211_ht_cap); |
927 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | 971 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); |
972 | tmp = cpu_to_le16(cap); | ||
928 | memcpy(pos, &tmp, sizeof(u16)); | 973 | memcpy(pos, &tmp, sizeof(u16)); |
929 | pos += sizeof(u16); | 974 | pos += sizeof(u16); |
930 | /* TODO: needs a define here for << 2 */ | ||
931 | *pos++ = sband->ht_cap.ampdu_factor | | 975 | *pos++ = sband->ht_cap.ampdu_factor | |
932 | (sband->ht_cap.ampdu_density << 2); | 976 | (sband->ht_cap.ampdu_density << |
977 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
933 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | 978 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); |
934 | pos += sizeof(sband->ht_cap.mcs); | 979 | pos += sizeof(sband->ht_cap.mcs); |
935 | pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ | 980 | pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ |
@@ -940,9 +985,11 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
940 | * that calculates local->scan_ies_len. | 985 | * that calculates local->scan_ies_len. |
941 | */ | 986 | */ |
942 | 987 | ||
943 | if (ie) { | 988 | /* add any remaining custom IEs */ |
944 | memcpy(pos, ie, ie_len); | 989 | if (ie && ie_len) { |
945 | pos += ie_len; | 990 | noffset = ie_len; |
991 | memcpy(pos, ie + offset, noffset - offset); | ||
992 | pos += noffset - offset; | ||
946 | } | 993 | } |
947 | 994 | ||
948 | return pos - buffer; | 995 | return pos - buffer; |
@@ -955,40 +1002,33 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
955 | struct ieee80211_local *local = sdata->local; | 1002 | struct ieee80211_local *local = sdata->local; |
956 | struct sk_buff *skb; | 1003 | struct sk_buff *skb; |
957 | struct ieee80211_mgmt *mgmt; | 1004 | struct ieee80211_mgmt *mgmt; |
958 | u8 *pos; | 1005 | size_t buf_len; |
959 | 1006 | u8 *buf; | |
960 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + | 1007 | |
961 | ie_len); | 1008 | /* FIXME: come up with a proper value */ |
962 | if (!skb) { | 1009 | buf = kmalloc(200 + ie_len, GFP_KERNEL); |
963 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | 1010 | if (!buf) { |
964 | "request\n", sdata->dev->name); | 1011 | printk(KERN_DEBUG "%s: failed to allocate temporary IE " |
1012 | "buffer\n", sdata->name); | ||
965 | return; | 1013 | return; |
966 | } | 1014 | } |
967 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
968 | 1015 | ||
969 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 1016 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, |
970 | memset(mgmt, 0, 24); | 1017 | local->hw.conf.channel->band); |
971 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 1018 | |
972 | IEEE80211_STYPE_PROBE_REQ); | 1019 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
973 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 1020 | ssid, ssid_len, |
1021 | buf, buf_len); | ||
1022 | |||
974 | if (dst) { | 1023 | if (dst) { |
1024 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
975 | memcpy(mgmt->da, dst, ETH_ALEN); | 1025 | memcpy(mgmt->da, dst, ETH_ALEN); |
976 | memcpy(mgmt->bssid, dst, ETH_ALEN); | 1026 | memcpy(mgmt->bssid, dst, ETH_ALEN); |
977 | } else { | ||
978 | memset(mgmt->da, 0xff, ETH_ALEN); | ||
979 | memset(mgmt->bssid, 0xff, ETH_ALEN); | ||
980 | } | 1027 | } |
981 | pos = skb_put(skb, 2 + ssid_len); | ||
982 | *pos++ = WLAN_EID_SSID; | ||
983 | *pos++ = ssid_len; | ||
984 | memcpy(pos, ssid, ssid_len); | ||
985 | pos += ssid_len; | ||
986 | |||
987 | skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len, | ||
988 | local->hw.conf.channel->band)); | ||
989 | 1028 | ||
990 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1029 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
991 | ieee80211_tx_skb(sdata, skb); | 1030 | ieee80211_tx_skb(sdata, skb); |
1031 | kfree(buf); | ||
992 | } | 1032 | } |
993 | 1033 | ||
994 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1034 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
@@ -1032,18 +1072,16 @@ void ieee80211_stop_device(struct ieee80211_local *local) | |||
1032 | ieee80211_led_radio(local, false); | 1072 | ieee80211_led_radio(local, false); |
1033 | 1073 | ||
1034 | cancel_work_sync(&local->reconfig_filter); | 1074 | cancel_work_sync(&local->reconfig_filter); |
1035 | drv_stop(local); | ||
1036 | 1075 | ||
1037 | flush_workqueue(local->workqueue); | 1076 | flush_workqueue(local->workqueue); |
1077 | drv_stop(local); | ||
1038 | } | 1078 | } |
1039 | 1079 | ||
1040 | int ieee80211_reconfig(struct ieee80211_local *local) | 1080 | int ieee80211_reconfig(struct ieee80211_local *local) |
1041 | { | 1081 | { |
1042 | struct ieee80211_hw *hw = &local->hw; | 1082 | struct ieee80211_hw *hw = &local->hw; |
1043 | struct ieee80211_sub_if_data *sdata; | 1083 | struct ieee80211_sub_if_data *sdata; |
1044 | struct ieee80211_if_init_conf conf; | ||
1045 | struct sta_info *sta; | 1084 | struct sta_info *sta; |
1046 | unsigned long flags; | ||
1047 | int res; | 1085 | int res; |
1048 | 1086 | ||
1049 | if (local->suspended) | 1087 | if (local->suspended) |
@@ -1061,7 +1099,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1061 | if (res) { | 1099 | if (res) { |
1062 | WARN(local->suspended, "Harware became unavailable " | 1100 | WARN(local->suspended, "Harware became unavailable " |
1063 | "upon resume. This is could be a software issue" | 1101 | "upon resume. This is could be a software issue" |
1064 | "prior to suspend or a harware issue\n"); | 1102 | "prior to suspend or a hardware issue\n"); |
1065 | return res; | 1103 | return res; |
1066 | } | 1104 | } |
1067 | 1105 | ||
@@ -1072,29 +1110,24 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1072 | list_for_each_entry(sdata, &local->interfaces, list) { | 1110 | list_for_each_entry(sdata, &local->interfaces, list) { |
1073 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1111 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
1074 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | 1112 | sdata->vif.type != NL80211_IFTYPE_MONITOR && |
1075 | netif_running(sdata->dev)) { | 1113 | ieee80211_sdata_running(sdata)) |
1076 | conf.vif = &sdata->vif; | 1114 | res = drv_add_interface(local, &sdata->vif); |
1077 | conf.type = sdata->vif.type; | ||
1078 | conf.mac_addr = sdata->dev->dev_addr; | ||
1079 | res = drv_add_interface(local, &conf); | ||
1080 | } | ||
1081 | } | 1115 | } |
1082 | 1116 | ||
1083 | /* add STAs back */ | 1117 | /* add STAs back */ |
1084 | if (local->ops->sta_notify) { | 1118 | mutex_lock(&local->sta_mtx); |
1085 | spin_lock_irqsave(&local->sta_lock, flags); | 1119 | list_for_each_entry(sta, &local->sta_list, list) { |
1086 | list_for_each_entry(sta, &local->sta_list, list) { | 1120 | if (sta->uploaded) { |
1087 | sdata = sta->sdata; | 1121 | sdata = sta->sdata; |
1088 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1122 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1089 | sdata = container_of(sdata->bss, | 1123 | sdata = container_of(sdata->bss, |
1090 | struct ieee80211_sub_if_data, | 1124 | struct ieee80211_sub_if_data, |
1091 | u.ap); | 1125 | u.ap); |
1092 | 1126 | ||
1093 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, | 1127 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); |
1094 | &sta->sta); | ||
1095 | } | 1128 | } |
1096 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
1097 | } | 1129 | } |
1130 | mutex_unlock(&local->sta_mtx); | ||
1098 | 1131 | ||
1099 | /* Clear Suspend state so that ADDBA requests can be processed */ | 1132 | /* Clear Suspend state so that ADDBA requests can be processed */ |
1100 | 1133 | ||
@@ -1119,7 +1152,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1119 | /* Finally also reconfigure all the BSS information */ | 1152 | /* Finally also reconfigure all the BSS information */ |
1120 | list_for_each_entry(sdata, &local->interfaces, list) { | 1153 | list_for_each_entry(sdata, &local->interfaces, list) { |
1121 | u32 changed = ~0; | 1154 | u32 changed = ~0; |
1122 | if (!netif_running(sdata->dev)) | 1155 | if (!ieee80211_sdata_running(sdata)) |
1123 | continue; | 1156 | continue; |
1124 | switch (sdata->vif.type) { | 1157 | switch (sdata->vif.type) { |
1125 | case NL80211_IFTYPE_STATION: | 1158 | case NL80211_IFTYPE_STATION: |
@@ -1145,9 +1178,17 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1145 | } | 1178 | } |
1146 | } | 1179 | } |
1147 | 1180 | ||
1181 | rcu_read_lock(); | ||
1182 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | ||
1183 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
1184 | ieee80211_sta_tear_down_BA_sessions(sta); | ||
1185 | } | ||
1186 | } | ||
1187 | rcu_read_unlock(); | ||
1188 | |||
1148 | /* add back keys */ | 1189 | /* add back keys */ |
1149 | list_for_each_entry(sdata, &local->interfaces, list) | 1190 | list_for_each_entry(sdata, &local->interfaces, list) |
1150 | if (netif_running(sdata->dev)) | 1191 | if (ieee80211_sdata_running(sdata)) |
1151 | ieee80211_enable_keys(sdata); | 1192 | ieee80211_enable_keys(sdata); |
1152 | 1193 | ||
1153 | ieee80211_wake_queues_by_reason(hw, | 1194 | ieee80211_wake_queues_by_reason(hw, |
@@ -1184,13 +1225,143 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1184 | 1225 | ||
1185 | add_timer(&local->sta_cleanup); | 1226 | add_timer(&local->sta_cleanup); |
1186 | 1227 | ||
1187 | spin_lock_irqsave(&local->sta_lock, flags); | 1228 | mutex_lock(&local->sta_mtx); |
1188 | list_for_each_entry(sta, &local->sta_list, list) | 1229 | list_for_each_entry(sta, &local->sta_list, list) |
1189 | mesh_plink_restart(sta); | 1230 | mesh_plink_restart(sta); |
1190 | spin_unlock_irqrestore(&local->sta_lock, flags); | 1231 | mutex_unlock(&local->sta_mtx); |
1191 | #else | 1232 | #else |
1192 | WARN_ON(1); | 1233 | WARN_ON(1); |
1193 | #endif | 1234 | #endif |
1194 | return 0; | 1235 | return 0; |
1195 | } | 1236 | } |
1196 | 1237 | ||
1238 | static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, | ||
1239 | enum ieee80211_smps_mode *smps_mode) | ||
1240 | { | ||
1241 | if (ifmgd->associated) { | ||
1242 | *smps_mode = ifmgd->ap_smps; | ||
1243 | |||
1244 | if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) { | ||
1245 | if (ifmgd->powersave) | ||
1246 | *smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
1247 | else | ||
1248 | *smps_mode = IEEE80211_SMPS_OFF; | ||
1249 | } | ||
1250 | |||
1251 | return 1; | ||
1252 | } | ||
1253 | |||
1254 | return 0; | ||
1255 | } | ||
1256 | |||
1257 | /* must hold iflist_mtx */ | ||
1258 | void ieee80211_recalc_smps(struct ieee80211_local *local, | ||
1259 | struct ieee80211_sub_if_data *forsdata) | ||
1260 | { | ||
1261 | struct ieee80211_sub_if_data *sdata; | ||
1262 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; | ||
1263 | int count = 0; | ||
1264 | |||
1265 | if (forsdata) | ||
1266 | WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx)); | ||
1267 | |||
1268 | WARN_ON(!mutex_is_locked(&local->iflist_mtx)); | ||
1269 | |||
1270 | /* | ||
1271 | * This function could be improved to handle multiple | ||
1272 | * interfaces better, but right now it makes any | ||
1273 | * non-station interfaces force SM PS to be turned | ||
1274 | * off. If there are multiple station interfaces it | ||
1275 | * could also use the best possible mode, e.g. if | ||
1276 | * one is in static and the other in dynamic then | ||
1277 | * dynamic is ok. | ||
1278 | */ | ||
1279 | |||
1280 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1281 | if (!netif_running(sdata->dev)) | ||
1282 | continue; | ||
1283 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1284 | goto set; | ||
1285 | if (sdata != forsdata) { | ||
1286 | /* | ||
1287 | * This nested is ok -- we are holding the iflist_mtx | ||
1288 | * so can't get here twice or so. But it's required | ||
1289 | * since normally we acquire it first and then the | ||
1290 | * iflist_mtx. | ||
1291 | */ | ||
1292 | mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING); | ||
1293 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); | ||
1294 | mutex_unlock(&sdata->u.mgd.mtx); | ||
1295 | } else | ||
1296 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); | ||
1297 | |||
1298 | if (count > 1) { | ||
1299 | smps_mode = IEEE80211_SMPS_OFF; | ||
1300 | break; | ||
1301 | } | ||
1302 | } | ||
1303 | |||
1304 | if (smps_mode == local->smps_mode) | ||
1305 | return; | ||
1306 | |||
1307 | set: | ||
1308 | local->smps_mode = smps_mode; | ||
1309 | /* changed flag is auto-detected for this */ | ||
1310 | ieee80211_hw_config(local, 0); | ||
1311 | } | ||
1312 | |||
1313 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) | ||
1314 | { | ||
1315 | int i; | ||
1316 | |||
1317 | for (i = 0; i < n_ids; i++) | ||
1318 | if (ids[i] == id) | ||
1319 | return true; | ||
1320 | return false; | ||
1321 | } | ||
1322 | |||
1323 | /** | ||
1324 | * ieee80211_ie_split - split an IE buffer according to ordering | ||
1325 | * | ||
1326 | * @ies: the IE buffer | ||
1327 | * @ielen: the length of the IE buffer | ||
1328 | * @ids: an array with element IDs that are allowed before | ||
1329 | * the split | ||
1330 | * @n_ids: the size of the element ID array | ||
1331 | * @offset: offset where to start splitting in the buffer | ||
1332 | * | ||
1333 | * This function splits an IE buffer by updating the @offset | ||
1334 | * variable to point to the location where the buffer should be | ||
1335 | * split. | ||
1336 | * | ||
1337 | * It assumes that the given IE buffer is well-formed, this | ||
1338 | * has to be guaranteed by the caller! | ||
1339 | * | ||
1340 | * It also assumes that the IEs in the buffer are ordered | ||
1341 | * correctly, if not the result of using this function will not | ||
1342 | * be ordered correctly either, i.e. it does no reordering. | ||
1343 | * | ||
1344 | * The function returns the offset where the next part of the | ||
1345 | * buffer starts, which may be @ielen if the entire (remainder) | ||
1346 | * of the buffer should be used. | ||
1347 | */ | ||
1348 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | ||
1349 | const u8 *ids, int n_ids, size_t offset) | ||
1350 | { | ||
1351 | size_t pos = offset; | ||
1352 | |||
1353 | while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) | ||
1354 | pos += 2 + ies[pos + 1]; | ||
1355 | |||
1356 | return pos; | ||
1357 | } | ||
1358 | |||
1359 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) | ||
1360 | { | ||
1361 | size_t pos = offset; | ||
1362 | |||
1363 | while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC) | ||
1364 | pos += 2 + ies[pos + 1]; | ||
1365 | |||
1366 | return pos; | ||
1367 | } | ||
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 247123fe1a7a..5d745f2d7236 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -305,20 +305,19 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
305 | { | 305 | { |
306 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 306 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
307 | 307 | ||
308 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { | 308 | if (!info->control.hw_key) { |
309 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key, | 309 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key, |
310 | tx->key->conf.keylen, | 310 | tx->key->conf.keylen, |
311 | tx->key->conf.keyidx)) | 311 | tx->key->conf.keyidx)) |
312 | return -1; | 312 | return -1; |
313 | } else { | 313 | } else if (info->control.hw_key->flags & |
314 | info->control.hw_key = &tx->key->conf; | 314 | IEEE80211_KEY_FLAG_GENERATE_IV) { |
315 | if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) { | 315 | if (!ieee80211_wep_add_iv(tx->local, skb, |
316 | if (!ieee80211_wep_add_iv(tx->local, skb, | 316 | tx->key->conf.keylen, |
317 | tx->key->conf.keylen, | 317 | tx->key->conf.keyidx)) |
318 | tx->key->conf.keyidx)) | 318 | return -1; |
319 | return -1; | ||
320 | } | ||
321 | } | 319 | } |
320 | |||
322 | return 0; | 321 | return 0; |
323 | } | 322 | } |
324 | 323 | ||
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 79d887dae738..34e6d02da779 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -96,7 +96,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
96 | } | 96 | } |
97 | 97 | ||
98 | if (!sta && ra && !is_multicast_ether_addr(ra)) { | 98 | if (!sta && ra && !is_multicast_ether_addr(ra)) { |
99 | sta = sta_info_get(local, ra); | 99 | sta = sta_info_get(sdata, ra); |
100 | if (sta) | 100 | if (sta) |
101 | sta_flags = get_sta_flags(sta); | 101 | sta_flags = get_sta_flags(sta); |
102 | } | 102 | } |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c new file mode 100644 index 000000000000..1e1ea3007b06 --- /dev/null +++ b/net/mac80211/work.c | |||
@@ -0,0 +1,1100 @@ | |||
1 | /* | ||
2 | * mac80211 work implementation | ||
3 | * | ||
4 | * Copyright 2003-2008, Jouni Malinen <j@w1.fi> | ||
5 | * Copyright 2004, Instant802 Networks, Inc. | ||
6 | * Copyright 2005, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2009, Johannes Berg <johannes@sipsolutions.net> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/delay.h> | ||
17 | #include <linux/if_ether.h> | ||
18 | #include <linux/skbuff.h> | ||
19 | #include <linux/if_arp.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/crc32.h> | ||
22 | #include <net/mac80211.h> | ||
23 | #include <asm/unaligned.h> | ||
24 | |||
25 | #include "ieee80211_i.h" | ||
26 | #include "rate.h" | ||
27 | |||
28 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | ||
29 | #define IEEE80211_AUTH_MAX_TRIES 3 | ||
30 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | ||
31 | #define IEEE80211_ASSOC_MAX_TRIES 3 | ||
32 | #define IEEE80211_MAX_PROBE_TRIES 5 | ||
33 | |||
34 | enum work_action { | ||
35 | WORK_ACT_NONE, | ||
36 | WORK_ACT_TIMEOUT, | ||
37 | WORK_ACT_DONE, | ||
38 | }; | ||
39 | |||
40 | |||
41 | /* utils */ | ||
42 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) | ||
43 | { | ||
44 | WARN_ON(!mutex_is_locked(&local->work_mtx)); | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * We can have multiple work items (and connection probing) | ||
49 | * scheduling this timer, but we need to take care to only | ||
50 | * reschedule it when it should fire _earlier_ than it was | ||
51 | * asked for before, or if it's not pending right now. This | ||
52 | * function ensures that. Note that it then is required to | ||
53 | * run this function for all timeouts after the first one | ||
54 | * has happened -- the work that runs from this timer will | ||
55 | * do that. | ||
56 | */ | ||
57 | static void run_again(struct ieee80211_local *local, | ||
58 | unsigned long timeout) | ||
59 | { | ||
60 | ASSERT_WORK_MTX(local); | ||
61 | |||
62 | if (!timer_pending(&local->work_timer) || | ||
63 | time_before(timeout, local->work_timer.expires)) | ||
64 | mod_timer(&local->work_timer, timeout); | ||
65 | } | ||
66 | |||
67 | static void work_free_rcu(struct rcu_head *head) | ||
68 | { | ||
69 | struct ieee80211_work *wk = | ||
70 | container_of(head, struct ieee80211_work, rcu_head); | ||
71 | |||
72 | kfree(wk); | ||
73 | } | ||
74 | |||
75 | void free_work(struct ieee80211_work *wk) | ||
76 | { | ||
77 | call_rcu(&wk->rcu_head, work_free_rcu); | ||
78 | } | ||
79 | |||
80 | static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | ||
81 | struct ieee80211_supported_band *sband, | ||
82 | u32 *rates) | ||
83 | { | ||
84 | int i, j, count; | ||
85 | *rates = 0; | ||
86 | count = 0; | ||
87 | for (i = 0; i < supp_rates_len; i++) { | ||
88 | int rate = (supp_rates[i] & 0x7F) * 5; | ||
89 | |||
90 | for (j = 0; j < sband->n_bitrates; j++) | ||
91 | if (sband->bitrates[j].bitrate == rate) { | ||
92 | *rates |= BIT(j); | ||
93 | count++; | ||
94 | break; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | return count; | ||
99 | } | ||
100 | |||
101 | /* frame sending functions */ | ||
102 | |||
103 | static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | ||
104 | struct ieee80211_supported_band *sband, | ||
105 | struct ieee80211_channel *channel, | ||
106 | enum ieee80211_smps_mode smps) | ||
107 | { | ||
108 | struct ieee80211_ht_info *ht_info; | ||
109 | u8 *pos; | ||
110 | u32 flags = channel->flags; | ||
111 | u16 cap = sband->ht_cap.cap; | ||
112 | __le16 tmp; | ||
113 | |||
114 | if (!sband->ht_cap.ht_supported) | ||
115 | return; | ||
116 | |||
117 | if (!ht_info_ie) | ||
118 | return; | ||
119 | |||
120 | if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) | ||
121 | return; | ||
122 | |||
123 | ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); | ||
124 | |||
125 | /* determine capability flags */ | ||
126 | |||
127 | if (ieee80211_disable_40mhz_24ghz && | ||
128 | sband->band == IEEE80211_BAND_2GHZ) { | ||
129 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
130 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
131 | } | ||
132 | |||
133 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
134 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
135 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | ||
136 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
137 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
138 | } | ||
139 | break; | ||
140 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
141 | if (flags & IEEE80211_CHAN_NO_HT40MINUS) { | ||
142 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
143 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
144 | } | ||
145 | break; | ||
146 | } | ||
147 | |||
148 | /* set SM PS mode properly */ | ||
149 | cap &= ~IEEE80211_HT_CAP_SM_PS; | ||
150 | switch (smps) { | ||
151 | case IEEE80211_SMPS_AUTOMATIC: | ||
152 | case IEEE80211_SMPS_NUM_MODES: | ||
153 | WARN_ON(1); | ||
154 | case IEEE80211_SMPS_OFF: | ||
155 | cap |= WLAN_HT_CAP_SM_PS_DISABLED << | ||
156 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
157 | break; | ||
158 | case IEEE80211_SMPS_STATIC: | ||
159 | cap |= WLAN_HT_CAP_SM_PS_STATIC << | ||
160 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
161 | break; | ||
162 | case IEEE80211_SMPS_DYNAMIC: | ||
163 | cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
164 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
165 | break; | ||
166 | } | ||
167 | |||
168 | /* reserve and fill IE */ | ||
169 | |||
170 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
171 | *pos++ = WLAN_EID_HT_CAPABILITY; | ||
172 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
173 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | ||
174 | |||
175 | /* capability flags */ | ||
176 | tmp = cpu_to_le16(cap); | ||
177 | memcpy(pos, &tmp, sizeof(u16)); | ||
178 | pos += sizeof(u16); | ||
179 | |||
180 | /* AMPDU parameters */ | ||
181 | *pos++ = sband->ht_cap.ampdu_factor | | ||
182 | (sband->ht_cap.ampdu_density << | ||
183 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
184 | |||
185 | /* MCS set */ | ||
186 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | ||
187 | pos += sizeof(sband->ht_cap.mcs); | ||
188 | |||
189 | /* extended capabilities */ | ||
190 | pos += sizeof(__le16); | ||
191 | |||
192 | /* BF capabilities */ | ||
193 | pos += sizeof(__le32); | ||
194 | |||
195 | /* antenna selection */ | ||
196 | pos += sizeof(u8); | ||
197 | } | ||
198 | |||
199 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | ||
200 | struct ieee80211_work *wk) | ||
201 | { | ||
202 | struct ieee80211_local *local = sdata->local; | ||
203 | struct sk_buff *skb; | ||
204 | struct ieee80211_mgmt *mgmt; | ||
205 | u8 *pos, qos_info; | ||
206 | const u8 *ies; | ||
207 | size_t offset = 0, noffset; | ||
208 | int i, len, count, rates_len, supp_rates_len; | ||
209 | u16 capab; | ||
210 | struct ieee80211_supported_band *sband; | ||
211 | u32 rates = 0; | ||
212 | |||
213 | sband = local->hw.wiphy->bands[wk->chan->band]; | ||
214 | |||
215 | /* | ||
216 | * Get all rates supported by the device and the AP as | ||
217 | * some APs don't like getting a superset of their rates | ||
218 | * in the association request (e.g. D-Link DAP 1353 in | ||
219 | * b-only mode)... | ||
220 | */ | ||
221 | rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, | ||
222 | wk->assoc.supp_rates_len, | ||
223 | sband, &rates); | ||
224 | |||
225 | skb = alloc_skb(local->hw.extra_tx_headroom + | ||
226 | sizeof(*mgmt) + /* bit too much but doesn't matter */ | ||
227 | 2 + wk->assoc.ssid_len + /* SSID */ | ||
228 | 4 + rates_len + /* (extended) rates */ | ||
229 | 4 + /* power capability */ | ||
230 | 2 + 2 * sband->n_channels + /* supported channels */ | ||
231 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ | ||
232 | wk->ie_len + /* extra IEs */ | ||
233 | 9, /* WMM */ | ||
234 | GFP_KERNEL); | ||
235 | if (!skb) { | ||
236 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | ||
237 | "frame\n", sdata->name); | ||
238 | return; | ||
239 | } | ||
240 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
241 | |||
242 | capab = WLAN_CAPABILITY_ESS; | ||
243 | |||
244 | if (sband->band == IEEE80211_BAND_2GHZ) { | ||
245 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | ||
246 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; | ||
247 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) | ||
248 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
249 | } | ||
250 | |||
251 | if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY) | ||
252 | capab |= WLAN_CAPABILITY_PRIVACY; | ||
253 | |||
254 | if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && | ||
255 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) | ||
256 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; | ||
257 | |||
258 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
259 | memset(mgmt, 0, 24); | ||
260 | memcpy(mgmt->da, wk->filter_ta, ETH_ALEN); | ||
261 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
262 | memcpy(mgmt->bssid, wk->filter_ta, ETH_ALEN); | ||
263 | |||
264 | if (!is_zero_ether_addr(wk->assoc.prev_bssid)) { | ||
265 | skb_put(skb, 10); | ||
266 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
267 | IEEE80211_STYPE_REASSOC_REQ); | ||
268 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); | ||
269 | mgmt->u.reassoc_req.listen_interval = | ||
270 | cpu_to_le16(local->hw.conf.listen_interval); | ||
271 | memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid, | ||
272 | ETH_ALEN); | ||
273 | } else { | ||
274 | skb_put(skb, 4); | ||
275 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
276 | IEEE80211_STYPE_ASSOC_REQ); | ||
277 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | ||
278 | mgmt->u.assoc_req.listen_interval = | ||
279 | cpu_to_le16(local->hw.conf.listen_interval); | ||
280 | } | ||
281 | |||
282 | /* SSID */ | ||
283 | ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len); | ||
284 | *pos++ = WLAN_EID_SSID; | ||
285 | *pos++ = wk->assoc.ssid_len; | ||
286 | memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); | ||
287 | |||
288 | /* add all rates which were marked to be used above */ | ||
289 | supp_rates_len = rates_len; | ||
290 | if (supp_rates_len > 8) | ||
291 | supp_rates_len = 8; | ||
292 | |||
293 | len = sband->n_bitrates; | ||
294 | pos = skb_put(skb, supp_rates_len + 2); | ||
295 | *pos++ = WLAN_EID_SUPP_RATES; | ||
296 | *pos++ = supp_rates_len; | ||
297 | |||
298 | count = 0; | ||
299 | for (i = 0; i < sband->n_bitrates; i++) { | ||
300 | if (BIT(i) & rates) { | ||
301 | int rate = sband->bitrates[i].bitrate; | ||
302 | *pos++ = (u8) (rate / 5); | ||
303 | if (++count == 8) | ||
304 | break; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | if (rates_len > count) { | ||
309 | pos = skb_put(skb, rates_len - count + 2); | ||
310 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
311 | *pos++ = rates_len - count; | ||
312 | |||
313 | for (i++; i < sband->n_bitrates; i++) { | ||
314 | if (BIT(i) & rates) { | ||
315 | int rate = sband->bitrates[i].bitrate; | ||
316 | *pos++ = (u8) (rate / 5); | ||
317 | } | ||
318 | } | ||
319 | } | ||
320 | |||
321 | if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { | ||
322 | /* 1. power capabilities */ | ||
323 | pos = skb_put(skb, 4); | ||
324 | *pos++ = WLAN_EID_PWR_CAPABILITY; | ||
325 | *pos++ = 2; | ||
326 | *pos++ = 0; /* min tx power */ | ||
327 | *pos++ = wk->chan->max_power; /* max tx power */ | ||
328 | |||
329 | /* 2. supported channels */ | ||
330 | /* TODO: get this in reg domain format */ | ||
331 | pos = skb_put(skb, 2 * sband->n_channels + 2); | ||
332 | *pos++ = WLAN_EID_SUPPORTED_CHANNELS; | ||
333 | *pos++ = 2 * sband->n_channels; | ||
334 | for (i = 0; i < sband->n_channels; i++) { | ||
335 | *pos++ = ieee80211_frequency_to_channel( | ||
336 | sband->channels[i].center_freq); | ||
337 | *pos++ = 1; /* one channel in the subband*/ | ||
338 | } | ||
339 | } | ||
340 | |||
341 | /* if present, add any custom IEs that go before HT */ | ||
342 | if (wk->ie_len && wk->ie) { | ||
343 | static const u8 before_ht[] = { | ||
344 | WLAN_EID_SSID, | ||
345 | WLAN_EID_SUPP_RATES, | ||
346 | WLAN_EID_EXT_SUPP_RATES, | ||
347 | WLAN_EID_PWR_CAPABILITY, | ||
348 | WLAN_EID_SUPPORTED_CHANNELS, | ||
349 | WLAN_EID_RSN, | ||
350 | WLAN_EID_QOS_CAPA, | ||
351 | WLAN_EID_RRM_ENABLED_CAPABILITIES, | ||
352 | WLAN_EID_MOBILITY_DOMAIN, | ||
353 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
354 | }; | ||
355 | noffset = ieee80211_ie_split(wk->ie, wk->ie_len, | ||
356 | before_ht, ARRAY_SIZE(before_ht), | ||
357 | offset); | ||
358 | pos = skb_put(skb, noffset - offset); | ||
359 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
360 | offset = noffset; | ||
361 | } | ||
362 | |||
363 | if (wk->assoc.use_11n && wk->assoc.wmm_used && | ||
364 | local->hw.queues >= 4) | ||
365 | ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie, | ||
366 | sband, wk->chan, wk->assoc.smps); | ||
367 | |||
368 | /* if present, add any custom non-vendor IEs that go after HT */ | ||
369 | if (wk->ie_len && wk->ie) { | ||
370 | noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len, | ||
371 | offset); | ||
372 | pos = skb_put(skb, noffset - offset); | ||
373 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
374 | offset = noffset; | ||
375 | } | ||
376 | |||
377 | if (wk->assoc.wmm_used && local->hw.queues >= 4) { | ||
378 | if (wk->assoc.uapsd_used) { | ||
379 | qos_info = local->uapsd_queues; | ||
380 | qos_info |= (local->uapsd_max_sp_len << | ||
381 | IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT); | ||
382 | } else { | ||
383 | qos_info = 0; | ||
384 | } | ||
385 | |||
386 | pos = skb_put(skb, 9); | ||
387 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
388 | *pos++ = 7; /* len */ | ||
389 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
390 | *pos++ = 0x50; | ||
391 | *pos++ = 0xf2; | ||
392 | *pos++ = 2; /* WME */ | ||
393 | *pos++ = 0; /* WME info */ | ||
394 | *pos++ = 1; /* WME ver */ | ||
395 | *pos++ = qos_info; | ||
396 | } | ||
397 | |||
398 | /* add any remaining custom (i.e. vendor specific here) IEs */ | ||
399 | if (wk->ie_len && wk->ie) { | ||
400 | noffset = wk->ie_len; | ||
401 | pos = skb_put(skb, noffset - offset); | ||
402 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
403 | } | ||
404 | |||
405 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
406 | ieee80211_tx_skb(sdata, skb); | ||
407 | } | ||
408 | |||
409 | static void ieee80211_remove_auth_bss(struct ieee80211_local *local, | ||
410 | struct ieee80211_work *wk) | ||
411 | { | ||
412 | struct cfg80211_bss *cbss; | ||
413 | u16 capa_val = WLAN_CAPABILITY_ESS; | ||
414 | |||
415 | if (wk->probe_auth.privacy) | ||
416 | capa_val |= WLAN_CAPABILITY_PRIVACY; | ||
417 | |||
418 | cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->filter_ta, | ||
419 | wk->probe_auth.ssid, wk->probe_auth.ssid_len, | ||
420 | WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, | ||
421 | capa_val); | ||
422 | if (!cbss) | ||
423 | return; | ||
424 | |||
425 | cfg80211_unlink_bss(local->hw.wiphy, cbss); | ||
426 | cfg80211_put_bss(cbss); | ||
427 | } | ||
428 | |||
429 | static enum work_action __must_check | ||
430 | ieee80211_direct_probe(struct ieee80211_work *wk) | ||
431 | { | ||
432 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
433 | struct ieee80211_local *local = sdata->local; | ||
434 | |||
435 | wk->probe_auth.tries++; | ||
436 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { | ||
437 | printk(KERN_DEBUG "%s: direct probe to %pM timed out\n", | ||
438 | sdata->name, wk->filter_ta); | ||
439 | |||
440 | /* | ||
441 | * Most likely AP is not in the range so remove the | ||
442 | * bss struct for that AP. | ||
443 | */ | ||
444 | ieee80211_remove_auth_bss(local, wk); | ||
445 | |||
446 | return WORK_ACT_TIMEOUT; | ||
447 | } | ||
448 | |||
449 | printk(KERN_DEBUG "%s: direct probe to %pM (try %d)\n", | ||
450 | sdata->name, wk->filter_ta, wk->probe_auth.tries); | ||
451 | |||
452 | /* | ||
453 | * Direct probe is sent to broadcast address as some APs | ||
454 | * will not answer to direct packet in unassociated state. | ||
455 | */ | ||
456 | ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, | ||
457 | wk->probe_auth.ssid_len, NULL, 0); | ||
458 | |||
459 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
460 | run_again(local, wk->timeout); | ||
461 | |||
462 | return WORK_ACT_NONE; | ||
463 | } | ||
464 | |||
465 | |||
466 | static enum work_action __must_check | ||
467 | ieee80211_authenticate(struct ieee80211_work *wk) | ||
468 | { | ||
469 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
470 | struct ieee80211_local *local = sdata->local; | ||
471 | |||
472 | wk->probe_auth.tries++; | ||
473 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { | ||
474 | printk(KERN_DEBUG "%s: authentication with %pM" | ||
475 | " timed out\n", sdata->name, wk->filter_ta); | ||
476 | |||
477 | /* | ||
478 | * Most likely AP is not in the range so remove the | ||
479 | * bss struct for that AP. | ||
480 | */ | ||
481 | ieee80211_remove_auth_bss(local, wk); | ||
482 | |||
483 | return WORK_ACT_TIMEOUT; | ||
484 | } | ||
485 | |||
486 | printk(KERN_DEBUG "%s: authenticate with %pM (try %d)\n", | ||
487 | sdata->name, wk->filter_ta, wk->probe_auth.tries); | ||
488 | |||
489 | ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie, | ||
490 | wk->ie_len, wk->filter_ta, NULL, 0, 0); | ||
491 | wk->probe_auth.transaction = 2; | ||
492 | |||
493 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
494 | run_again(local, wk->timeout); | ||
495 | |||
496 | return WORK_ACT_NONE; | ||
497 | } | ||
498 | |||
499 | static enum work_action __must_check | ||
500 | ieee80211_associate(struct ieee80211_work *wk) | ||
501 | { | ||
502 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
503 | struct ieee80211_local *local = sdata->local; | ||
504 | |||
505 | wk->assoc.tries++; | ||
506 | if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { | ||
507 | printk(KERN_DEBUG "%s: association with %pM" | ||
508 | " timed out\n", | ||
509 | sdata->name, wk->filter_ta); | ||
510 | |||
511 | /* | ||
512 | * Most likely AP is not in the range so remove the | ||
513 | * bss struct for that AP. | ||
514 | */ | ||
515 | if (wk->assoc.bss) | ||
516 | cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss); | ||
517 | |||
518 | return WORK_ACT_TIMEOUT; | ||
519 | } | ||
520 | |||
521 | printk(KERN_DEBUG "%s: associate with %pM (try %d)\n", | ||
522 | sdata->name, wk->filter_ta, wk->assoc.tries); | ||
523 | ieee80211_send_assoc(sdata, wk); | ||
524 | |||
525 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | ||
526 | run_again(local, wk->timeout); | ||
527 | |||
528 | return WORK_ACT_NONE; | ||
529 | } | ||
530 | |||
531 | static enum work_action __must_check | ||
532 | ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) | ||
533 | { | ||
534 | /* | ||
535 | * First time we run, do nothing -- the generic code will | ||
536 | * have switched to the right channel etc. | ||
537 | */ | ||
538 | if (!wk->started) { | ||
539 | wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration); | ||
540 | |||
541 | cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk, | ||
542 | wk->chan, wk->chan_type, | ||
543 | wk->remain.duration, GFP_KERNEL); | ||
544 | |||
545 | return WORK_ACT_NONE; | ||
546 | } | ||
547 | |||
548 | return WORK_ACT_TIMEOUT; | ||
549 | } | ||
550 | |||
551 | static void ieee80211_auth_challenge(struct ieee80211_work *wk, | ||
552 | struct ieee80211_mgmt *mgmt, | ||
553 | size_t len) | ||
554 | { | ||
555 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
556 | u8 *pos; | ||
557 | struct ieee802_11_elems elems; | ||
558 | |||
559 | pos = mgmt->u.auth.variable; | ||
560 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
561 | if (!elems.challenge) | ||
562 | return; | ||
563 | ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm, | ||
564 | elems.challenge - 2, elems.challenge_len + 2, | ||
565 | wk->filter_ta, wk->probe_auth.key, | ||
566 | wk->probe_auth.key_len, wk->probe_auth.key_idx); | ||
567 | wk->probe_auth.transaction = 4; | ||
568 | } | ||
569 | |||
570 | static enum work_action __must_check | ||
571 | ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, | ||
572 | struct ieee80211_mgmt *mgmt, size_t len) | ||
573 | { | ||
574 | u16 auth_alg, auth_transaction, status_code; | ||
575 | |||
576 | if (wk->type != IEEE80211_WORK_AUTH) | ||
577 | return WORK_ACT_NONE; | ||
578 | |||
579 | if (len < 24 + 6) | ||
580 | return WORK_ACT_NONE; | ||
581 | |||
582 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | ||
583 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | ||
584 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | ||
585 | |||
586 | if (auth_alg != wk->probe_auth.algorithm || | ||
587 | auth_transaction != wk->probe_auth.transaction) | ||
588 | return WORK_ACT_NONE; | ||
589 | |||
590 | if (status_code != WLAN_STATUS_SUCCESS) { | ||
591 | printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", | ||
592 | wk->sdata->name, mgmt->sa, status_code); | ||
593 | return WORK_ACT_DONE; | ||
594 | } | ||
595 | |||
596 | switch (wk->probe_auth.algorithm) { | ||
597 | case WLAN_AUTH_OPEN: | ||
598 | case WLAN_AUTH_LEAP: | ||
599 | case WLAN_AUTH_FT: | ||
600 | break; | ||
601 | case WLAN_AUTH_SHARED_KEY: | ||
602 | if (wk->probe_auth.transaction != 4) { | ||
603 | ieee80211_auth_challenge(wk, mgmt, len); | ||
604 | /* need another frame */ | ||
605 | return WORK_ACT_NONE; | ||
606 | } | ||
607 | break; | ||
608 | default: | ||
609 | WARN_ON(1); | ||
610 | return WORK_ACT_NONE; | ||
611 | } | ||
612 | |||
613 | printk(KERN_DEBUG "%s: authenticated\n", wk->sdata->name); | ||
614 | return WORK_ACT_DONE; | ||
615 | } | ||
616 | |||
617 | static enum work_action __must_check | ||
618 | ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, | ||
619 | struct ieee80211_mgmt *mgmt, size_t len, | ||
620 | bool reassoc) | ||
621 | { | ||
622 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
623 | struct ieee80211_local *local = sdata->local; | ||
624 | u16 capab_info, status_code, aid; | ||
625 | struct ieee802_11_elems elems; | ||
626 | u8 *pos; | ||
627 | |||
628 | /* | ||
629 | * AssocResp and ReassocResp have identical structure, so process both | ||
630 | * of them in this function. | ||
631 | */ | ||
632 | |||
633 | if (len < 24 + 6) | ||
634 | return WORK_ACT_NONE; | ||
635 | |||
636 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | ||
637 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | ||
638 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | ||
639 | |||
640 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | ||
641 | "status=%d aid=%d)\n", | ||
642 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, | ||
643 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | ||
644 | |||
645 | pos = mgmt->u.assoc_resp.variable; | ||
646 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
647 | |||
648 | if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && | ||
649 | elems.timeout_int && elems.timeout_int_len == 5 && | ||
650 | elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { | ||
651 | u32 tu, ms; | ||
652 | tu = get_unaligned_le32(elems.timeout_int + 1); | ||
653 | ms = tu * 1024 / 1000; | ||
654 | printk(KERN_DEBUG "%s: %pM rejected association temporarily; " | ||
655 | "comeback duration %u TU (%u ms)\n", | ||
656 | sdata->name, mgmt->sa, tu, ms); | ||
657 | wk->timeout = jiffies + msecs_to_jiffies(ms); | ||
658 | if (ms > IEEE80211_ASSOC_TIMEOUT) | ||
659 | run_again(local, wk->timeout); | ||
660 | return WORK_ACT_NONE; | ||
661 | } | ||
662 | |||
663 | if (status_code != WLAN_STATUS_SUCCESS) | ||
664 | printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", | ||
665 | sdata->name, mgmt->sa, status_code); | ||
666 | else | ||
667 | printk(KERN_DEBUG "%s: associated\n", sdata->name); | ||
668 | |||
669 | return WORK_ACT_DONE; | ||
670 | } | ||
671 | |||
672 | static enum work_action __must_check | ||
673 | ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, | ||
674 | struct ieee80211_mgmt *mgmt, size_t len, | ||
675 | struct ieee80211_rx_status *rx_status) | ||
676 | { | ||
677 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
678 | struct ieee80211_local *local = sdata->local; | ||
679 | size_t baselen; | ||
680 | |||
681 | ASSERT_WORK_MTX(local); | ||
682 | |||
683 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | ||
684 | if (baselen > len) | ||
685 | return WORK_ACT_NONE; | ||
686 | |||
687 | printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); | ||
688 | return WORK_ACT_DONE; | ||
689 | } | ||
690 | |||
691 | static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | ||
692 | struct sk_buff *skb) | ||
693 | { | ||
694 | struct ieee80211_rx_status *rx_status; | ||
695 | struct ieee80211_mgmt *mgmt; | ||
696 | struct ieee80211_work *wk; | ||
697 | enum work_action rma = WORK_ACT_NONE; | ||
698 | u16 fc; | ||
699 | |||
700 | rx_status = (struct ieee80211_rx_status *) skb->cb; | ||
701 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
702 | fc = le16_to_cpu(mgmt->frame_control); | ||
703 | |||
704 | mutex_lock(&local->work_mtx); | ||
705 | |||
706 | list_for_each_entry(wk, &local->work_list, list) { | ||
707 | const u8 *bssid = NULL; | ||
708 | |||
709 | switch (wk->type) { | ||
710 | case IEEE80211_WORK_DIRECT_PROBE: | ||
711 | case IEEE80211_WORK_AUTH: | ||
712 | case IEEE80211_WORK_ASSOC: | ||
713 | bssid = wk->filter_ta; | ||
714 | break; | ||
715 | default: | ||
716 | continue; | ||
717 | } | ||
718 | |||
719 | /* | ||
720 | * Before queuing, we already verified mgmt->sa, | ||
721 | * so this is needed just for matching. | ||
722 | */ | ||
723 | if (compare_ether_addr(bssid, mgmt->bssid)) | ||
724 | continue; | ||
725 | |||
726 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
727 | case IEEE80211_STYPE_PROBE_RESP: | ||
728 | rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len, | ||
729 | rx_status); | ||
730 | break; | ||
731 | case IEEE80211_STYPE_AUTH: | ||
732 | rma = ieee80211_rx_mgmt_auth(wk, mgmt, skb->len); | ||
733 | break; | ||
734 | case IEEE80211_STYPE_ASSOC_RESP: | ||
735 | rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, | ||
736 | skb->len, false); | ||
737 | break; | ||
738 | case IEEE80211_STYPE_REASSOC_RESP: | ||
739 | rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, | ||
740 | skb->len, true); | ||
741 | break; | ||
742 | default: | ||
743 | WARN_ON(1); | ||
744 | } | ||
745 | /* | ||
746 | * We've processed this frame for that work, so it can't | ||
747 | * belong to another work struct. | ||
748 | * NB: this is also required for correctness for 'rma'! | ||
749 | */ | ||
750 | break; | ||
751 | } | ||
752 | |||
753 | switch (rma) { | ||
754 | case WORK_ACT_NONE: | ||
755 | break; | ||
756 | case WORK_ACT_DONE: | ||
757 | list_del_rcu(&wk->list); | ||
758 | break; | ||
759 | default: | ||
760 | WARN(1, "unexpected: %d", rma); | ||
761 | } | ||
762 | |||
763 | mutex_unlock(&local->work_mtx); | ||
764 | |||
765 | if (rma != WORK_ACT_DONE) | ||
766 | goto out; | ||
767 | |||
768 | switch (wk->done(wk, skb)) { | ||
769 | case WORK_DONE_DESTROY: | ||
770 | free_work(wk); | ||
771 | break; | ||
772 | case WORK_DONE_REQUEUE: | ||
773 | synchronize_rcu(); | ||
774 | wk->started = false; /* restart */ | ||
775 | mutex_lock(&local->work_mtx); | ||
776 | list_add_tail(&wk->list, &local->work_list); | ||
777 | mutex_unlock(&local->work_mtx); | ||
778 | } | ||
779 | |||
780 | out: | ||
781 | kfree_skb(skb); | ||
782 | } | ||
783 | |||
784 | static void ieee80211_work_timer(unsigned long data) | ||
785 | { | ||
786 | struct ieee80211_local *local = (void *) data; | ||
787 | |||
788 | if (local->quiescing) | ||
789 | return; | ||
790 | |||
791 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
792 | } | ||
793 | |||
794 | static void ieee80211_work_work(struct work_struct *work) | ||
795 | { | ||
796 | struct ieee80211_local *local = | ||
797 | container_of(work, struct ieee80211_local, work_work); | ||
798 | struct sk_buff *skb; | ||
799 | struct ieee80211_work *wk, *tmp; | ||
800 | LIST_HEAD(free_work); | ||
801 | enum work_action rma; | ||
802 | bool remain_off_channel = false; | ||
803 | |||
804 | if (local->scanning) | ||
805 | return; | ||
806 | |||
807 | /* | ||
808 | * ieee80211_queue_work() should have picked up most cases, | ||
809 | * here we'll pick the the rest. | ||
810 | */ | ||
811 | if (WARN(local->suspended, "work scheduled while going to suspend\n")) | ||
812 | return; | ||
813 | |||
814 | /* first process frames to avoid timing out while a frame is pending */ | ||
815 | while ((skb = skb_dequeue(&local->work_skb_queue))) | ||
816 | ieee80211_work_rx_queued_mgmt(local, skb); | ||
817 | |||
818 | ieee80211_recalc_idle(local); | ||
819 | |||
820 | mutex_lock(&local->work_mtx); | ||
821 | |||
822 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | ||
823 | bool started = wk->started; | ||
824 | |||
825 | /* mark work as started if it's on the current off-channel */ | ||
826 | if (!started && local->tmp_channel && | ||
827 | wk->chan == local->tmp_channel && | ||
828 | wk->chan_type == local->tmp_channel_type) { | ||
829 | started = true; | ||
830 | wk->timeout = jiffies; | ||
831 | } | ||
832 | |||
833 | if (!started && !local->tmp_channel) { | ||
834 | /* | ||
835 | * TODO: could optimize this by leaving the | ||
836 | * station vifs in awake mode if they | ||
837 | * happen to be on the same channel as | ||
838 | * the requested channel | ||
839 | */ | ||
840 | ieee80211_offchannel_stop_beaconing(local); | ||
841 | ieee80211_offchannel_stop_station(local); | ||
842 | |||
843 | local->tmp_channel = wk->chan; | ||
844 | local->tmp_channel_type = wk->chan_type; | ||
845 | ieee80211_hw_config(local, 0); | ||
846 | started = true; | ||
847 | wk->timeout = jiffies; | ||
848 | } | ||
849 | |||
850 | /* don't try to work with items that aren't started */ | ||
851 | if (!started) | ||
852 | continue; | ||
853 | |||
854 | if (time_is_after_jiffies(wk->timeout)) { | ||
855 | /* | ||
856 | * This work item isn't supposed to be worked on | ||
857 | * right now, but take care to adjust the timer | ||
858 | * properly. | ||
859 | */ | ||
860 | run_again(local, wk->timeout); | ||
861 | continue; | ||
862 | } | ||
863 | |||
864 | switch (wk->type) { | ||
865 | default: | ||
866 | WARN_ON(1); | ||
867 | /* nothing */ | ||
868 | rma = WORK_ACT_NONE; | ||
869 | break; | ||
870 | case IEEE80211_WORK_ABORT: | ||
871 | rma = WORK_ACT_TIMEOUT; | ||
872 | break; | ||
873 | case IEEE80211_WORK_DIRECT_PROBE: | ||
874 | rma = ieee80211_direct_probe(wk); | ||
875 | break; | ||
876 | case IEEE80211_WORK_AUTH: | ||
877 | rma = ieee80211_authenticate(wk); | ||
878 | break; | ||
879 | case IEEE80211_WORK_ASSOC: | ||
880 | rma = ieee80211_associate(wk); | ||
881 | break; | ||
882 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: | ||
883 | rma = ieee80211_remain_on_channel_timeout(wk); | ||
884 | break; | ||
885 | } | ||
886 | |||
887 | wk->started = started; | ||
888 | |||
889 | switch (rma) { | ||
890 | case WORK_ACT_NONE: | ||
891 | /* might have changed the timeout */ | ||
892 | run_again(local, wk->timeout); | ||
893 | break; | ||
894 | case WORK_ACT_TIMEOUT: | ||
895 | list_del_rcu(&wk->list); | ||
896 | synchronize_rcu(); | ||
897 | list_add(&wk->list, &free_work); | ||
898 | break; | ||
899 | default: | ||
900 | WARN(1, "unexpected: %d", rma); | ||
901 | } | ||
902 | } | ||
903 | |||
904 | list_for_each_entry(wk, &local->work_list, list) { | ||
905 | if (!wk->started) | ||
906 | continue; | ||
907 | if (wk->chan != local->tmp_channel) | ||
908 | continue; | ||
909 | if (wk->chan_type != local->tmp_channel_type) | ||
910 | continue; | ||
911 | remain_off_channel = true; | ||
912 | } | ||
913 | |||
914 | if (!remain_off_channel && local->tmp_channel) { | ||
915 | local->tmp_channel = NULL; | ||
916 | ieee80211_hw_config(local, 0); | ||
917 | ieee80211_offchannel_return(local, true); | ||
918 | /* give connection some time to breathe */ | ||
919 | run_again(local, jiffies + HZ/2); | ||
920 | } | ||
921 | |||
922 | if (list_empty(&local->work_list) && local->scan_req) | ||
923 | ieee80211_queue_delayed_work(&local->hw, | ||
924 | &local->scan_work, | ||
925 | round_jiffies_relative(0)); | ||
926 | |||
927 | mutex_unlock(&local->work_mtx); | ||
928 | |||
929 | ieee80211_recalc_idle(local); | ||
930 | |||
931 | list_for_each_entry_safe(wk, tmp, &free_work, list) { | ||
932 | wk->done(wk, NULL); | ||
933 | list_del(&wk->list); | ||
934 | kfree(wk); | ||
935 | } | ||
936 | } | ||
937 | |||
938 | void ieee80211_add_work(struct ieee80211_work *wk) | ||
939 | { | ||
940 | struct ieee80211_local *local; | ||
941 | |||
942 | if (WARN_ON(!wk->chan)) | ||
943 | return; | ||
944 | |||
945 | if (WARN_ON(!wk->sdata)) | ||
946 | return; | ||
947 | |||
948 | if (WARN_ON(!wk->done)) | ||
949 | return; | ||
950 | |||
951 | if (WARN_ON(!ieee80211_sdata_running(wk->sdata))) | ||
952 | return; | ||
953 | |||
954 | wk->started = false; | ||
955 | |||
956 | local = wk->sdata->local; | ||
957 | mutex_lock(&local->work_mtx); | ||
958 | list_add_tail(&wk->list, &local->work_list); | ||
959 | mutex_unlock(&local->work_mtx); | ||
960 | |||
961 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
962 | } | ||
963 | |||
964 | void ieee80211_work_init(struct ieee80211_local *local) | ||
965 | { | ||
966 | mutex_init(&local->work_mtx); | ||
967 | INIT_LIST_HEAD(&local->work_list); | ||
968 | setup_timer(&local->work_timer, ieee80211_work_timer, | ||
969 | (unsigned long)local); | ||
970 | INIT_WORK(&local->work_work, ieee80211_work_work); | ||
971 | skb_queue_head_init(&local->work_skb_queue); | ||
972 | } | ||
973 | |||
974 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | ||
975 | { | ||
976 | struct ieee80211_local *local = sdata->local; | ||
977 | struct ieee80211_work *wk; | ||
978 | |||
979 | mutex_lock(&local->work_mtx); | ||
980 | list_for_each_entry(wk, &local->work_list, list) { | ||
981 | if (wk->sdata != sdata) | ||
982 | continue; | ||
983 | wk->type = IEEE80211_WORK_ABORT; | ||
984 | wk->started = true; | ||
985 | wk->timeout = jiffies; | ||
986 | } | ||
987 | mutex_unlock(&local->work_mtx); | ||
988 | |||
989 | /* run cleanups etc. */ | ||
990 | ieee80211_work_work(&local->work_work); | ||
991 | |||
992 | mutex_lock(&local->work_mtx); | ||
993 | list_for_each_entry(wk, &local->work_list, list) { | ||
994 | if (wk->sdata != sdata) | ||
995 | continue; | ||
996 | WARN_ON(1); | ||
997 | break; | ||
998 | } | ||
999 | mutex_unlock(&local->work_mtx); | ||
1000 | } | ||
1001 | |||
1002 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | ||
1003 | struct sk_buff *skb) | ||
1004 | { | ||
1005 | struct ieee80211_local *local = sdata->local; | ||
1006 | struct ieee80211_mgmt *mgmt; | ||
1007 | struct ieee80211_work *wk; | ||
1008 | u16 fc; | ||
1009 | |||
1010 | if (skb->len < 24) | ||
1011 | return RX_DROP_MONITOR; | ||
1012 | |||
1013 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
1014 | fc = le16_to_cpu(mgmt->frame_control); | ||
1015 | |||
1016 | list_for_each_entry_rcu(wk, &local->work_list, list) { | ||
1017 | if (sdata != wk->sdata) | ||
1018 | continue; | ||
1019 | if (compare_ether_addr(wk->filter_ta, mgmt->sa)) | ||
1020 | continue; | ||
1021 | if (compare_ether_addr(wk->filter_ta, mgmt->bssid)) | ||
1022 | continue; | ||
1023 | |||
1024 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
1025 | case IEEE80211_STYPE_AUTH: | ||
1026 | case IEEE80211_STYPE_PROBE_RESP: | ||
1027 | case IEEE80211_STYPE_ASSOC_RESP: | ||
1028 | case IEEE80211_STYPE_REASSOC_RESP: | ||
1029 | skb_queue_tail(&local->work_skb_queue, skb); | ||
1030 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
1031 | return RX_QUEUED; | ||
1032 | } | ||
1033 | } | ||
1034 | |||
1035 | return RX_CONTINUE; | ||
1036 | } | ||
1037 | |||
1038 | static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, | ||
1039 | struct sk_buff *skb) | ||
1040 | { | ||
1041 | /* | ||
1042 | * We are done serving the remain-on-channel command. | ||
1043 | */ | ||
1044 | cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk, | ||
1045 | wk->chan, wk->chan_type, | ||
1046 | GFP_KERNEL); | ||
1047 | |||
1048 | return WORK_DONE_DESTROY; | ||
1049 | } | ||
1050 | |||
1051 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
1052 | struct ieee80211_channel *chan, | ||
1053 | enum nl80211_channel_type channel_type, | ||
1054 | unsigned int duration, u64 *cookie) | ||
1055 | { | ||
1056 | struct ieee80211_work *wk; | ||
1057 | |||
1058 | wk = kzalloc(sizeof(*wk), GFP_KERNEL); | ||
1059 | if (!wk) | ||
1060 | return -ENOMEM; | ||
1061 | |||
1062 | wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL; | ||
1063 | wk->chan = chan; | ||
1064 | wk->chan_type = channel_type; | ||
1065 | wk->sdata = sdata; | ||
1066 | wk->done = ieee80211_remain_done; | ||
1067 | |||
1068 | wk->remain.duration = duration; | ||
1069 | |||
1070 | *cookie = (unsigned long) wk; | ||
1071 | |||
1072 | ieee80211_add_work(wk); | ||
1073 | |||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
1078 | u64 cookie) | ||
1079 | { | ||
1080 | struct ieee80211_local *local = sdata->local; | ||
1081 | struct ieee80211_work *wk, *tmp; | ||
1082 | bool found = false; | ||
1083 | |||
1084 | mutex_lock(&local->work_mtx); | ||
1085 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | ||
1086 | if ((unsigned long) wk == cookie) { | ||
1087 | wk->timeout = jiffies; | ||
1088 | found = true; | ||
1089 | break; | ||
1090 | } | ||
1091 | } | ||
1092 | mutex_unlock(&local->work_mtx); | ||
1093 | |||
1094 | if (!found) | ||
1095 | return -ENOENT; | ||
1096 | |||
1097 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
1098 | |||
1099 | return 0; | ||
1100 | } | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 5332014cb229..f4971cd45c64 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -31,8 +31,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
31 | unsigned int hdrlen; | 31 | unsigned int hdrlen; |
32 | struct ieee80211_hdr *hdr; | 32 | struct ieee80211_hdr *hdr; |
33 | struct sk_buff *skb = tx->skb; | 33 | struct sk_buff *skb = tx->skb; |
34 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
34 | int authenticator; | 35 | int authenticator; |
35 | int wpa_test = 0; | ||
36 | int tail; | 36 | int tail; |
37 | 37 | ||
38 | hdr = (struct ieee80211_hdr *)skb->data; | 38 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -47,16 +47,15 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
47 | data = skb->data + hdrlen; | 47 | data = skb->data + hdrlen; |
48 | data_len = skb->len - hdrlen; | 48 | data_len = skb->len - hdrlen; |
49 | 49 | ||
50 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 50 | if (info->control.hw_key && |
51 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && | 51 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && |
52 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) && | 52 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
53 | !wpa_test) { | 53 | /* hwaccel - with no need for SW-generated MMIC */ |
54 | /* hwaccel - with no need for preallocated room for MMIC */ | ||
55 | return TX_CONTINUE; | 54 | return TX_CONTINUE; |
56 | } | 55 | } |
57 | 56 | ||
58 | tail = MICHAEL_MIC_LEN; | 57 | tail = MICHAEL_MIC_LEN; |
59 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 58 | if (!info->control.hw_key) |
60 | tail += TKIP_ICV_LEN; | 59 | tail += TKIP_ICV_LEN; |
61 | 60 | ||
62 | if (WARN_ON(skb_tailroom(skb) < tail || | 61 | if (WARN_ON(skb_tailroom(skb) < tail || |
@@ -147,17 +146,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
147 | int len, tail; | 146 | int len, tail; |
148 | u8 *pos; | 147 | u8 *pos; |
149 | 148 | ||
150 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 149 | if (info->control.hw_key && |
151 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 150 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
152 | /* hwaccel - with no need for preallocated room for IV/ICV */ | 151 | /* hwaccel - with no need for software-generated IV */ |
153 | info->control.hw_key = &tx->key->conf; | ||
154 | return 0; | 152 | return 0; |
155 | } | 153 | } |
156 | 154 | ||
157 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 155 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
158 | len = skb->len - hdrlen; | 156 | len = skb->len - hdrlen; |
159 | 157 | ||
160 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 158 | if (info->control.hw_key) |
161 | tail = 0; | 159 | tail = 0; |
162 | else | 160 | else |
163 | tail = TKIP_ICV_LEN; | 161 | tail = TKIP_ICV_LEN; |
@@ -175,13 +173,11 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
175 | if (key->u.tkip.tx.iv16 == 0) | 173 | if (key->u.tkip.tx.iv16 == 0) |
176 | key->u.tkip.tx.iv32++; | 174 | key->u.tkip.tx.iv32++; |
177 | 175 | ||
178 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 176 | pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); |
179 | /* hwaccel - with preallocated room for IV */ | ||
180 | ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); | ||
181 | 177 | ||
182 | info->control.hw_key = &tx->key->conf; | 178 | /* hwaccel - with software IV */ |
179 | if (info->control.hw_key) | ||
183 | return 0; | 180 | return 0; |
184 | } | ||
185 | 181 | ||
186 | /* Add room for ICV */ | 182 | /* Add room for ICV */ |
187 | skb_put(skb, TKIP_ICV_LEN); | 183 | skb_put(skb, TKIP_ICV_LEN); |
@@ -363,24 +359,20 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
363 | int hdrlen, len, tail; | 359 | int hdrlen, len, tail; |
364 | u8 *pos, *pn; | 360 | u8 *pos, *pn; |
365 | int i; | 361 | int i; |
366 | bool skip_hw; | ||
367 | |||
368 | skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) && | ||
369 | ieee80211_is_mgmt(hdr->frame_control); | ||
370 | 362 | ||
371 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 363 | if (info->control.hw_key && |
372 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) && | 364 | !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
373 | !skip_hw) { | 365 | /* |
374 | /* hwaccel - with no need for preallocated room for CCMP | 366 | * hwaccel has no need for preallocated room for CCMP |
375 | * header or MIC fields */ | 367 | * header or MIC fields |
376 | info->control.hw_key = &tx->key->conf; | 368 | */ |
377 | return 0; | 369 | return 0; |
378 | } | 370 | } |
379 | 371 | ||
380 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 372 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
381 | len = skb->len - hdrlen; | 373 | len = skb->len - hdrlen; |
382 | 374 | ||
383 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) | 375 | if (info->control.hw_key) |
384 | tail = 0; | 376 | tail = 0; |
385 | else | 377 | else |
386 | tail = CCMP_MIC_LEN; | 378 | tail = CCMP_MIC_LEN; |
@@ -405,11 +397,9 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
405 | 397 | ||
406 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); | 398 | ccmp_pn2hdr(pos, pn, key->conf.keyidx); |
407 | 399 | ||
408 | if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) { | 400 | /* hwaccel - with software CCMP header */ |
409 | /* hwaccel - with preallocated room for CCMP header */ | 401 | if (info->control.hw_key) |
410 | info->control.hw_key = &tx->key->conf; | ||
411 | return 0; | 402 | return 0; |
412 | } | ||
413 | 403 | ||
414 | pos += CCMP_HDR_LEN; | 404 | pos += CCMP_HDR_LEN; |
415 | ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); | 405 | ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); |
@@ -525,11 +515,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) | |||
525 | u8 *pn, aad[20]; | 515 | u8 *pn, aad[20]; |
526 | int i; | 516 | int i; |
527 | 517 | ||
528 | if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 518 | if (info->control.hw_key) |
529 | /* hwaccel */ | ||
530 | info->control.hw_key = &tx->key->conf; | ||
531 | return 0; | 519 | return 0; |
532 | } | ||
533 | 520 | ||
534 | if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) | 521 | if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) |
535 | return TX_DROP; | 522 | return TX_DROP; |