diff options
Diffstat (limited to 'net/mac80211')
31 files changed, 1340 insertions, 729 deletions
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index a87cb3ba2df6..d2b03e0851ef 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -138,10 +138,8 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) | |||
138 | struct crypto_cipher *tfm; | 138 | struct crypto_cipher *tfm; |
139 | 139 | ||
140 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | 140 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); |
141 | if (IS_ERR(tfm)) | 141 | if (!IS_ERR(tfm)) |
142 | return NULL; | 142 | crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); |
143 | |||
144 | crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); | ||
145 | 143 | ||
146 | return tfm; | 144 | return tfm; |
147 | } | 145 | } |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 3d097b3d7b62..b4d66cca76d6 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -119,10 +119,8 @@ struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]) | |||
119 | struct crypto_cipher *tfm; | 119 | struct crypto_cipher *tfm; |
120 | 120 | ||
121 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | 121 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); |
122 | if (IS_ERR(tfm)) | 122 | if (!IS_ERR(tfm)) |
123 | return NULL; | 123 | crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); |
124 | |||
125 | crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); | ||
126 | 124 | ||
127 | return tfm; | 125 | return tfm; |
128 | } | 126 | } |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 965b272499fd..58eab9e8e4ee 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -86,6 +86,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
86 | tid, 0, reason); | 86 | tid, 0, reason); |
87 | 87 | ||
88 | del_timer_sync(&tid_rx->session_timer); | 88 | del_timer_sync(&tid_rx->session_timer); |
89 | del_timer_sync(&tid_rx->reorder_timer); | ||
89 | 90 | ||
90 | call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); | 91 | call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); |
91 | } | 92 | } |
@@ -120,6 +121,20 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
120 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); | 121 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); |
121 | } | 122 | } |
122 | 123 | ||
124 | static void sta_rx_agg_reorder_timer_expired(unsigned long data) | ||
125 | { | ||
126 | u8 *ptid = (u8 *)data; | ||
127 | u8 *timer_to_id = ptid - *ptid; | ||
128 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
129 | timer_to_tid[0]); | ||
130 | |||
131 | rcu_read_lock(); | ||
132 | spin_lock(&sta->lock); | ||
133 | ieee80211_release_reorder_timeout(sta, *ptid); | ||
134 | spin_unlock(&sta->lock); | ||
135 | rcu_read_unlock(); | ||
136 | } | ||
137 | |||
123 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 138 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, |
124 | u8 dialog_token, u16 status, u16 policy, | 139 | u8 dialog_token, u16 status, u16 policy, |
125 | u16 buf_size, u16 timeout) | 140 | u16 buf_size, u16 timeout) |
@@ -251,11 +266,18 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
251 | goto end; | 266 | goto end; |
252 | } | 267 | } |
253 | 268 | ||
269 | spin_lock_init(&tid_agg_rx->reorder_lock); | ||
270 | |||
254 | /* rx timer */ | 271 | /* rx timer */ |
255 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; | 272 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; |
256 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 273 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
257 | init_timer(&tid_agg_rx->session_timer); | 274 | init_timer(&tid_agg_rx->session_timer); |
258 | 275 | ||
276 | /* rx reorder timer */ | ||
277 | tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; | ||
278 | tid_agg_rx->reorder_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | ||
279 | init_timer(&tid_agg_rx->reorder_timer); | ||
280 | |||
259 | /* prepare reordering buffer */ | 281 | /* prepare reordering buffer */ |
260 | tid_agg_rx->reorder_buf = | 282 | tid_agg_rx->reorder_buf = |
261 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); | 283 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 29ac8e1a509e..c981604b71e6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -19,33 +19,6 @@ | |||
19 | #include "rate.h" | 19 | #include "rate.h" |
20 | #include "mesh.h" | 20 | #include "mesh.h" |
21 | 21 | ||
22 | static bool nl80211_type_check(enum nl80211_iftype type) | ||
23 | { | ||
24 | switch (type) { | ||
25 | case NL80211_IFTYPE_ADHOC: | ||
26 | case NL80211_IFTYPE_STATION: | ||
27 | case NL80211_IFTYPE_MONITOR: | ||
28 | #ifdef CONFIG_MAC80211_MESH | ||
29 | case NL80211_IFTYPE_MESH_POINT: | ||
30 | #endif | ||
31 | case NL80211_IFTYPE_AP: | ||
32 | case NL80211_IFTYPE_AP_VLAN: | ||
33 | case NL80211_IFTYPE_WDS: | ||
34 | return true; | ||
35 | default: | ||
36 | return false; | ||
37 | } | ||
38 | } | ||
39 | |||
40 | static bool nl80211_params_check(enum nl80211_iftype type, | ||
41 | struct vif_params *params) | ||
42 | { | ||
43 | if (!nl80211_type_check(type)) | ||
44 | return false; | ||
45 | |||
46 | return true; | ||
47 | } | ||
48 | |||
49 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | 22 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, |
50 | enum nl80211_iftype type, u32 *flags, | 23 | enum nl80211_iftype type, u32 *flags, |
51 | struct vif_params *params) | 24 | struct vif_params *params) |
@@ -55,9 +28,6 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
55 | struct ieee80211_sub_if_data *sdata; | 28 | struct ieee80211_sub_if_data *sdata; |
56 | int err; | 29 | int err; |
57 | 30 | ||
58 | if (!nl80211_params_check(type, params)) | ||
59 | return -EINVAL; | ||
60 | |||
61 | err = ieee80211_if_add(local, name, &dev, type, params); | 31 | err = ieee80211_if_add(local, name, &dev, type, params); |
62 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) | 32 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) |
63 | return err; | 33 | return err; |
@@ -82,12 +52,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
82 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 52 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
83 | int ret; | 53 | int ret; |
84 | 54 | ||
85 | if (ieee80211_sdata_running(sdata)) | ||
86 | return -EBUSY; | ||
87 | |||
88 | if (!nl80211_params_check(type, params)) | ||
89 | return -EINVAL; | ||
90 | |||
91 | ret = ieee80211_if_change_type(sdata, type); | 55 | ret = ieee80211_if_change_type(sdata, type); |
92 | if (ret) | 56 | if (ret) |
93 | return ret; | 57 | return ret; |
@@ -114,44 +78,30 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
114 | u8 key_idx, const u8 *mac_addr, | 78 | u8 key_idx, const u8 *mac_addr, |
115 | struct key_params *params) | 79 | struct key_params *params) |
116 | { | 80 | { |
117 | struct ieee80211_sub_if_data *sdata; | 81 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
118 | struct sta_info *sta = NULL; | 82 | struct sta_info *sta = NULL; |
119 | enum ieee80211_key_alg alg; | ||
120 | struct ieee80211_key *key; | 83 | struct ieee80211_key *key; |
121 | int err; | 84 | int err; |
122 | 85 | ||
123 | if (!netif_running(dev)) | 86 | if (!ieee80211_sdata_running(sdata)) |
124 | return -ENETDOWN; | 87 | return -ENETDOWN; |
125 | 88 | ||
126 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 89 | /* reject WEP and TKIP keys if WEP failed to initialize */ |
127 | |||
128 | switch (params->cipher) { | 90 | switch (params->cipher) { |
129 | case WLAN_CIPHER_SUITE_WEP40: | 91 | case WLAN_CIPHER_SUITE_WEP40: |
130 | case WLAN_CIPHER_SUITE_WEP104: | ||
131 | alg = ALG_WEP; | ||
132 | break; | ||
133 | case WLAN_CIPHER_SUITE_TKIP: | 92 | case WLAN_CIPHER_SUITE_TKIP: |
134 | alg = ALG_TKIP; | 93 | case WLAN_CIPHER_SUITE_WEP104: |
135 | break; | 94 | if (IS_ERR(sdata->local->wep_tx_tfm)) |
136 | case WLAN_CIPHER_SUITE_CCMP: | 95 | return -EINVAL; |
137 | alg = ALG_CCMP; | ||
138 | break; | ||
139 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
140 | alg = ALG_AES_CMAC; | ||
141 | break; | 96 | break; |
142 | default: | 97 | default: |
143 | return -EINVAL; | 98 | break; |
144 | } | 99 | } |
145 | 100 | ||
146 | /* reject WEP and TKIP keys if WEP failed to initialize */ | 101 | key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, |
147 | if ((alg == ALG_WEP || alg == ALG_TKIP) && | 102 | params->key, params->seq_len, params->seq); |
148 | IS_ERR(sdata->local->wep_tx_tfm)) | 103 | if (IS_ERR(key)) |
149 | return -EINVAL; | 104 | return PTR_ERR(key); |
150 | |||
151 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, | ||
152 | params->seq_len, params->seq); | ||
153 | if (!key) | ||
154 | return -ENOMEM; | ||
155 | 105 | ||
156 | mutex_lock(&sdata->local->sta_mtx); | 106 | mutex_lock(&sdata->local->sta_mtx); |
157 | 107 | ||
@@ -164,9 +114,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
164 | } | 114 | } |
165 | } | 115 | } |
166 | 116 | ||
167 | ieee80211_key_link(key, sdata, sta); | 117 | err = ieee80211_key_link(key, sdata, sta); |
118 | if (err) | ||
119 | ieee80211_key_free(sdata->local, key); | ||
168 | 120 | ||
169 | err = 0; | ||
170 | out_unlock: | 121 | out_unlock: |
171 | mutex_unlock(&sdata->local->sta_mtx); | 122 | mutex_unlock(&sdata->local->sta_mtx); |
172 | 123 | ||
@@ -247,10 +198,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
247 | 198 | ||
248 | memset(¶ms, 0, sizeof(params)); | 199 | memset(¶ms, 0, sizeof(params)); |
249 | 200 | ||
250 | switch (key->conf.alg) { | 201 | params.cipher = key->conf.cipher; |
251 | case ALG_TKIP: | ||
252 | params.cipher = WLAN_CIPHER_SUITE_TKIP; | ||
253 | 202 | ||
203 | switch (key->conf.cipher) { | ||
204 | case WLAN_CIPHER_SUITE_TKIP: | ||
254 | iv32 = key->u.tkip.tx.iv32; | 205 | iv32 = key->u.tkip.tx.iv32; |
255 | iv16 = key->u.tkip.tx.iv16; | 206 | iv16 = key->u.tkip.tx.iv16; |
256 | 207 | ||
@@ -268,8 +219,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
268 | params.seq = seq; | 219 | params.seq = seq; |
269 | params.seq_len = 6; | 220 | params.seq_len = 6; |
270 | break; | 221 | break; |
271 | case ALG_CCMP: | 222 | case WLAN_CIPHER_SUITE_CCMP: |
272 | params.cipher = WLAN_CIPHER_SUITE_CCMP; | ||
273 | seq[0] = key->u.ccmp.tx_pn[5]; | 223 | seq[0] = key->u.ccmp.tx_pn[5]; |
274 | seq[1] = key->u.ccmp.tx_pn[4]; | 224 | seq[1] = key->u.ccmp.tx_pn[4]; |
275 | seq[2] = key->u.ccmp.tx_pn[3]; | 225 | seq[2] = key->u.ccmp.tx_pn[3]; |
@@ -279,14 +229,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
279 | params.seq = seq; | 229 | params.seq = seq; |
280 | params.seq_len = 6; | 230 | params.seq_len = 6; |
281 | break; | 231 | break; |
282 | case ALG_WEP: | 232 | case WLAN_CIPHER_SUITE_AES_CMAC: |
283 | if (key->conf.keylen == 5) | ||
284 | params.cipher = WLAN_CIPHER_SUITE_WEP40; | ||
285 | else | ||
286 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | ||
287 | break; | ||
288 | case ALG_AES_CMAC: | ||
289 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; | ||
290 | seq[0] = key->u.aes_cmac.tx_pn[5]; | 233 | seq[0] = key->u.aes_cmac.tx_pn[5]; |
291 | seq[1] = key->u.aes_cmac.tx_pn[4]; | 234 | seq[1] = key->u.aes_cmac.tx_pn[4]; |
292 | seq[2] = key->u.aes_cmac.tx_pn[3]; | 235 | seq[2] = key->u.aes_cmac.tx_pn[3]; |
@@ -634,6 +577,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
634 | struct sta_info *sta, | 577 | struct sta_info *sta, |
635 | struct station_parameters *params) | 578 | struct station_parameters *params) |
636 | { | 579 | { |
580 | unsigned long flags; | ||
637 | u32 rates; | 581 | u32 rates; |
638 | int i, j; | 582 | int i, j; |
639 | struct ieee80211_supported_band *sband; | 583 | struct ieee80211_supported_band *sband; |
@@ -642,7 +586,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
642 | 586 | ||
643 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 587 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
644 | 588 | ||
645 | spin_lock_bh(&sta->lock); | 589 | spin_lock_irqsave(&sta->flaglock, flags); |
646 | mask = params->sta_flags_mask; | 590 | mask = params->sta_flags_mask; |
647 | set = params->sta_flags_set; | 591 | set = params->sta_flags_set; |
648 | 592 | ||
@@ -669,7 +613,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
669 | if (set & BIT(NL80211_STA_FLAG_MFP)) | 613 | if (set & BIT(NL80211_STA_FLAG_MFP)) |
670 | sta->flags |= WLAN_STA_MFP; | 614 | sta->flags |= WLAN_STA_MFP; |
671 | } | 615 | } |
672 | spin_unlock_bh(&sta->lock); | 616 | spin_unlock_irqrestore(&sta->flaglock, flags); |
673 | 617 | ||
674 | /* | 618 | /* |
675 | * cfg80211 validates this (1-2007) and allows setting the AID | 619 | * cfg80211 validates this (1-2007) and allows setting the AID |
@@ -1143,9 +1087,9 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1143 | p.uapsd = false; | 1087 | p.uapsd = false; |
1144 | 1088 | ||
1145 | if (drv_conf_tx(local, params->queue, &p)) { | 1089 | if (drv_conf_tx(local, params->queue, &p)) { |
1146 | printk(KERN_DEBUG "%s: failed to set TX queue " | 1090 | wiphy_debug(local->hw.wiphy, |
1147 | "parameters for queue %d\n", | 1091 | "failed to set TX queue parameters for queue %d\n", |
1148 | wiphy_name(local->hw.wiphy), params->queue); | 1092 | params->queue); |
1149 | return -EINVAL; | 1093 | return -EINVAL; |
1150 | } | 1094 | } |
1151 | 1095 | ||
@@ -1207,15 +1151,26 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1207 | struct net_device *dev, | 1151 | struct net_device *dev, |
1208 | struct cfg80211_scan_request *req) | 1152 | struct cfg80211_scan_request *req) |
1209 | { | 1153 | { |
1210 | struct ieee80211_sub_if_data *sdata; | 1154 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1211 | |||
1212 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1213 | 1155 | ||
1214 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1156 | switch (ieee80211_vif_type_p2p(&sdata->vif)) { |
1215 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | 1157 | case NL80211_IFTYPE_STATION: |
1216 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | 1158 | case NL80211_IFTYPE_ADHOC: |
1217 | (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon)) | 1159 | case NL80211_IFTYPE_MESH_POINT: |
1160 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1161 | break; | ||
1162 | case NL80211_IFTYPE_P2P_GO: | ||
1163 | if (sdata->local->ops->hw_scan) | ||
1164 | break; | ||
1165 | /* FIXME: implement NoA while scanning in software */ | ||
1166 | return -EOPNOTSUPP; | ||
1167 | case NL80211_IFTYPE_AP: | ||
1168 | if (sdata->u.ap.beacon) | ||
1169 | return -EOPNOTSUPP; | ||
1170 | break; | ||
1171 | default: | ||
1218 | return -EOPNOTSUPP; | 1172 | return -EOPNOTSUPP; |
1173 | } | ||
1219 | 1174 | ||
1220 | return ieee80211_request_scan(sdata, req); | 1175 | return ieee80211_request_scan(sdata, req); |
1221 | } | 1176 | } |
@@ -1541,11 +1496,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
1541 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | 1496 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); |
1542 | } | 1497 | } |
1543 | 1498 | ||
1544 | static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | 1499 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
1545 | struct ieee80211_channel *chan, | 1500 | struct ieee80211_channel *chan, |
1546 | enum nl80211_channel_type channel_type, | 1501 | enum nl80211_channel_type channel_type, |
1547 | bool channel_type_valid, | 1502 | bool channel_type_valid, |
1548 | const u8 *buf, size_t len, u64 *cookie) | 1503 | const u8 *buf, size_t len, u64 *cookie) |
1549 | { | 1504 | { |
1550 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1505 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1551 | struct ieee80211_local *local = sdata->local; | 1506 | struct ieee80211_local *local = sdata->local; |
@@ -1575,8 +1530,6 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | |||
1575 | return -ENOLINK; | 1530 | return -ENOLINK; |
1576 | break; | 1531 | break; |
1577 | case NL80211_IFTYPE_STATION: | 1532 | case NL80211_IFTYPE_STATION: |
1578 | if (!(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) | ||
1579 | flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1580 | break; | 1533 | break; |
1581 | default: | 1534 | default: |
1582 | return -EOPNOTSUPP; | 1535 | return -EOPNOTSUPP; |
@@ -1647,6 +1600,6 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1647 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 1600 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
1648 | .remain_on_channel = ieee80211_remain_on_channel, | 1601 | .remain_on_channel = ieee80211_remain_on_channel, |
1649 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1602 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1650 | .action = ieee80211_action, | 1603 | .mgmt_tx = ieee80211_mgmt_tx, |
1651 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | 1604 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
1652 | }; | 1605 | }; |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 32be11e4c4d9..5b24740fc0b0 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -11,7 +11,7 @@ __ieee80211_get_channel_mode(struct ieee80211_local *local, | |||
11 | { | 11 | { |
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
13 | 13 | ||
14 | WARN_ON(!mutex_is_locked(&local->iflist_mtx)); | 14 | lockdep_assert_held(&local->iflist_mtx); |
15 | 15 | ||
16 | list_for_each_entry(sdata, &local->interfaces, list) { | 16 | list_for_each_entry(sdata, &local->interfaces, list) { |
17 | if (sdata == ignore) | 17 | if (sdata == ignore) |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index a694c593ff6a..e81ef4e8cb32 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -85,13 +85,15 @@ static ssize_t tsf_write(struct file *file, | |||
85 | if (strncmp(buf, "reset", 5) == 0) { | 85 | if (strncmp(buf, "reset", 5) == 0) { |
86 | if (local->ops->reset_tsf) { | 86 | if (local->ops->reset_tsf) { |
87 | drv_reset_tsf(local); | 87 | drv_reset_tsf(local); |
88 | printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy)); | 88 | wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); |
89 | } | 89 | } |
90 | } else { | 90 | } else { |
91 | tsf = simple_strtoul(buf, NULL, 0); | 91 | tsf = simple_strtoul(buf, NULL, 0); |
92 | if (local->ops->set_tsf) { | 92 | if (local->ops->set_tsf) { |
93 | drv_set_tsf(local, tsf); | 93 | drv_set_tsf(local, tsf); |
94 | printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf); | 94 | wiphy_info(local->hw.wiphy, |
95 | "debugfs set TSF to %#018llx\n", tsf); | ||
96 | |||
95 | } | 97 | } |
96 | } | 98 | } |
97 | 99 | ||
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index fa5e76e658ef..1647f8dc5cda 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -64,26 +64,13 @@ static ssize_t key_algorithm_read(struct file *file, | |||
64 | char __user *userbuf, | 64 | char __user *userbuf, |
65 | size_t count, loff_t *ppos) | 65 | size_t count, loff_t *ppos) |
66 | { | 66 | { |
67 | char *alg; | 67 | char buf[15]; |
68 | struct ieee80211_key *key = file->private_data; | 68 | struct ieee80211_key *key = file->private_data; |
69 | u32 c = key->conf.cipher; | ||
69 | 70 | ||
70 | switch (key->conf.alg) { | 71 | sprintf(buf, "%.2x-%.2x-%.2x:%d\n", |
71 | case ALG_WEP: | 72 | c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff); |
72 | alg = "WEP\n"; | 73 | return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); |
73 | break; | ||
74 | case ALG_TKIP: | ||
75 | alg = "TKIP\n"; | ||
76 | break; | ||
77 | case ALG_CCMP: | ||
78 | alg = "CCMP\n"; | ||
79 | break; | ||
80 | case ALG_AES_CMAC: | ||
81 | alg = "AES-128-CMAC\n"; | ||
82 | break; | ||
83 | default: | ||
84 | return 0; | ||
85 | } | ||
86 | return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg)); | ||
87 | } | 74 | } |
88 | KEY_OPS(algorithm); | 75 | KEY_OPS(algorithm); |
89 | 76 | ||
@@ -95,21 +82,22 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | |||
95 | int len; | 82 | int len; |
96 | struct ieee80211_key *key = file->private_data; | 83 | struct ieee80211_key *key = file->private_data; |
97 | 84 | ||
98 | switch (key->conf.alg) { | 85 | switch (key->conf.cipher) { |
99 | case ALG_WEP: | 86 | case WLAN_CIPHER_SUITE_WEP40: |
87 | case WLAN_CIPHER_SUITE_WEP104: | ||
100 | len = scnprintf(buf, sizeof(buf), "\n"); | 88 | len = scnprintf(buf, sizeof(buf), "\n"); |
101 | break; | 89 | break; |
102 | case ALG_TKIP: | 90 | case WLAN_CIPHER_SUITE_TKIP: |
103 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", | 91 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", |
104 | key->u.tkip.tx.iv32, | 92 | key->u.tkip.tx.iv32, |
105 | key->u.tkip.tx.iv16); | 93 | key->u.tkip.tx.iv16); |
106 | break; | 94 | break; |
107 | case ALG_CCMP: | 95 | case WLAN_CIPHER_SUITE_CCMP: |
108 | tpn = key->u.ccmp.tx_pn; | 96 | tpn = key->u.ccmp.tx_pn; |
109 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 97 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
110 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); | 98 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); |
111 | break; | 99 | break; |
112 | case ALG_AES_CMAC: | 100 | case WLAN_CIPHER_SUITE_AES_CMAC: |
113 | tpn = key->u.aes_cmac.tx_pn; | 101 | tpn = key->u.aes_cmac.tx_pn; |
114 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 102 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
115 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], | 103 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], |
@@ -130,11 +118,12 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
130 | int i, len; | 118 | int i, len; |
131 | const u8 *rpn; | 119 | const u8 *rpn; |
132 | 120 | ||
133 | switch (key->conf.alg) { | 121 | switch (key->conf.cipher) { |
134 | case ALG_WEP: | 122 | case WLAN_CIPHER_SUITE_WEP40: |
123 | case WLAN_CIPHER_SUITE_WEP104: | ||
135 | len = scnprintf(buf, sizeof(buf), "\n"); | 124 | len = scnprintf(buf, sizeof(buf), "\n"); |
136 | break; | 125 | break; |
137 | case ALG_TKIP: | 126 | case WLAN_CIPHER_SUITE_TKIP: |
138 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 127 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) |
139 | p += scnprintf(p, sizeof(buf)+buf-p, | 128 | p += scnprintf(p, sizeof(buf)+buf-p, |
140 | "%08x %04x\n", | 129 | "%08x %04x\n", |
@@ -142,7 +131,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
142 | key->u.tkip.rx[i].iv16); | 131 | key->u.tkip.rx[i].iv16); |
143 | len = p - buf; | 132 | len = p - buf; |
144 | break; | 133 | break; |
145 | case ALG_CCMP: | 134 | case WLAN_CIPHER_SUITE_CCMP: |
146 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { | 135 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { |
147 | rpn = key->u.ccmp.rx_pn[i]; | 136 | rpn = key->u.ccmp.rx_pn[i]; |
148 | p += scnprintf(p, sizeof(buf)+buf-p, | 137 | p += scnprintf(p, sizeof(buf)+buf-p, |
@@ -152,7 +141,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
152 | } | 141 | } |
153 | len = p - buf; | 142 | len = p - buf; |
154 | break; | 143 | break; |
155 | case ALG_AES_CMAC: | 144 | case WLAN_CIPHER_SUITE_AES_CMAC: |
156 | rpn = key->u.aes_cmac.rx_pn; | 145 | rpn = key->u.aes_cmac.rx_pn; |
157 | p += scnprintf(p, sizeof(buf)+buf-p, | 146 | p += scnprintf(p, sizeof(buf)+buf-p, |
158 | "%02x%02x%02x%02x%02x%02x\n", | 147 | "%02x%02x%02x%02x%02x%02x\n", |
@@ -174,11 +163,11 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf, | |||
174 | char buf[20]; | 163 | char buf[20]; |
175 | int len; | 164 | int len; |
176 | 165 | ||
177 | switch (key->conf.alg) { | 166 | switch (key->conf.cipher) { |
178 | case ALG_CCMP: | 167 | case WLAN_CIPHER_SUITE_CCMP: |
179 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); | 168 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); |
180 | break; | 169 | break; |
181 | case ALG_AES_CMAC: | 170 | case WLAN_CIPHER_SUITE_AES_CMAC: |
182 | len = scnprintf(buf, sizeof(buf), "%u\n", | 171 | len = scnprintf(buf, sizeof(buf), "%u\n", |
183 | key->u.aes_cmac.replays); | 172 | key->u.aes_cmac.replays); |
184 | break; | 173 | break; |
@@ -196,8 +185,8 @@ static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, | |||
196 | char buf[20]; | 185 | char buf[20]; |
197 | int len; | 186 | int len; |
198 | 187 | ||
199 | switch (key->conf.alg) { | 188 | switch (key->conf.cipher) { |
200 | case ALG_AES_CMAC: | 189 | case WLAN_CIPHER_SUITE_AES_CMAC: |
201 | len = scnprintf(buf, sizeof(buf), "%u\n", | 190 | len = scnprintf(buf, sizeof(buf), "%u\n", |
202 | key->u.aes_cmac.icverrors); | 191 | key->u.aes_cmac.icverrors); |
203 | break; | 192 | break; |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 14123dce544b..16983825f8e8 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -54,6 +54,20 @@ static inline int drv_add_interface(struct ieee80211_local *local, | |||
54 | return ret; | 54 | return ret; |
55 | } | 55 | } |
56 | 56 | ||
57 | static inline int drv_change_interface(struct ieee80211_local *local, | ||
58 | struct ieee80211_sub_if_data *sdata, | ||
59 | enum nl80211_iftype type, bool p2p) | ||
60 | { | ||
61 | int ret; | ||
62 | |||
63 | might_sleep(); | ||
64 | |||
65 | trace_drv_change_interface(local, sdata, type, p2p); | ||
66 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); | ||
67 | trace_drv_return_int(local, ret); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
57 | static inline void drv_remove_interface(struct ieee80211_local *local, | 71 | static inline void drv_remove_interface(struct ieee80211_local *local, |
58 | struct ieee80211_vif *vif) | 72 | struct ieee80211_vif *vif) |
59 | { | 73 | { |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 5d5d2a974668..6831fb1641c8 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -25,12 +25,14 @@ 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 *, sdata) \ | 28 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ |
29 | __field(bool, p2p) \ | ||
29 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 30 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
30 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ | 31 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ |
32 | __entry->p2p = sdata->vif.p2p; \ | ||
31 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 33 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
32 | #define VIF_PR_FMT " vif:%s(%d)" | 34 | #define VIF_PR_FMT " vif:%s(%d%s)" |
33 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type | 35 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
34 | 36 | ||
35 | /* | 37 | /* |
36 | * Tracing for driver callbacks. | 38 | * Tracing for driver callbacks. |
@@ -136,6 +138,34 @@ TRACE_EVENT(drv_add_interface, | |||
136 | ) | 138 | ) |
137 | ); | 139 | ); |
138 | 140 | ||
141 | TRACE_EVENT(drv_change_interface, | ||
142 | TP_PROTO(struct ieee80211_local *local, | ||
143 | struct ieee80211_sub_if_data *sdata, | ||
144 | enum nl80211_iftype type, bool p2p), | ||
145 | |||
146 | TP_ARGS(local, sdata, type, p2p), | ||
147 | |||
148 | TP_STRUCT__entry( | ||
149 | LOCAL_ENTRY | ||
150 | VIF_ENTRY | ||
151 | __field(u32, new_type) | ||
152 | __field(bool, new_p2p) | ||
153 | ), | ||
154 | |||
155 | TP_fast_assign( | ||
156 | LOCAL_ASSIGN; | ||
157 | VIF_ASSIGN; | ||
158 | __entry->new_type = type; | ||
159 | __entry->new_p2p = p2p; | ||
160 | ), | ||
161 | |||
162 | TP_printk( | ||
163 | LOCAL_PR_FMT VIF_PR_FMT " new type:%d%s", | ||
164 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type, | ||
165 | __entry->new_p2p ? "/p2p" : "" | ||
166 | ) | ||
167 | ); | ||
168 | |||
139 | TRACE_EVENT(drv_remove_interface, | 169 | TRACE_EVENT(drv_remove_interface, |
140 | TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), | 170 | TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), |
141 | 171 | ||
@@ -336,7 +366,7 @@ TRACE_EVENT(drv_set_key, | |||
336 | LOCAL_ENTRY | 366 | LOCAL_ENTRY |
337 | VIF_ENTRY | 367 | VIF_ENTRY |
338 | STA_ENTRY | 368 | STA_ENTRY |
339 | __field(enum ieee80211_key_alg, alg) | 369 | __field(u32, cipher) |
340 | __field(u8, hw_key_idx) | 370 | __field(u8, hw_key_idx) |
341 | __field(u8, flags) | 371 | __field(u8, flags) |
342 | __field(s8, keyidx) | 372 | __field(s8, keyidx) |
@@ -346,7 +376,7 @@ TRACE_EVENT(drv_set_key, | |||
346 | LOCAL_ASSIGN; | 376 | LOCAL_ASSIGN; |
347 | VIF_ASSIGN; | 377 | VIF_ASSIGN; |
348 | STA_ASSIGN; | 378 | STA_ASSIGN; |
349 | __entry->alg = key->alg; | 379 | __entry->cipher = key->cipher; |
350 | __entry->flags = key->flags; | 380 | __entry->flags = key->flags; |
351 | __entry->keyidx = key->keyidx; | 381 | __entry->keyidx = key->keyidx; |
352 | __entry->hw_key_idx = key->hw_key_idx; | 382 | __entry->hw_key_idx = key->hw_key_idx; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 9d101fb33861..11f74f5f7b2f 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -265,3 +265,31 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
265 | 265 | ||
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | |||
269 | void ieee80211_request_smps_work(struct work_struct *work) | ||
270 | { | ||
271 | struct ieee80211_sub_if_data *sdata = | ||
272 | container_of(work, struct ieee80211_sub_if_data, | ||
273 | u.mgd.request_smps_work); | ||
274 | |||
275 | mutex_lock(&sdata->u.mgd.mtx); | ||
276 | __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode); | ||
277 | mutex_unlock(&sdata->u.mgd.mtx); | ||
278 | } | ||
279 | |||
280 | void ieee80211_request_smps(struct ieee80211_vif *vif, | ||
281 | enum ieee80211_smps_mode smps_mode) | ||
282 | { | ||
283 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
284 | |||
285 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | ||
286 | return; | ||
287 | |||
288 | if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF)) | ||
289 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | ||
290 | |||
291 | ieee80211_queue_work(&sdata->local->hw, | ||
292 | &sdata->u.mgd.request_smps_work); | ||
293 | } | ||
294 | /* this might change ... don't want non-open drivers using it */ | ||
295 | EXPORT_SYMBOL_GPL(ieee80211_request_smps); | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c691780725a7..1a3aae54f0cf 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -427,8 +427,8 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
427 | return NULL; | 427 | return NULL; |
428 | 428 | ||
429 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 429 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
430 | printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n", | 430 | wiphy_debug(local->hw.wiphy, "Adding new IBSS station %pM (dev=%s)\n", |
431 | wiphy_name(local->hw.wiphy), addr, sdata->name); | 431 | addr, sdata->name); |
432 | #endif | 432 | #endif |
433 | 433 | ||
434 | sta = sta_info_alloc(sdata, addr, gfp); | 434 | sta = sta_info_alloc(sdata, addr, gfp); |
@@ -920,12 +920,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
920 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | 920 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); |
921 | sdata->u.ibss.ssid_len = params->ssid_len; | 921 | sdata->u.ibss.ssid_len = params->ssid_len; |
922 | 922 | ||
923 | mutex_unlock(&sdata->u.ibss.mtx); | ||
924 | |||
925 | mutex_lock(&sdata->local->mtx); | ||
923 | ieee80211_recalc_idle(sdata->local); | 926 | ieee80211_recalc_idle(sdata->local); |
927 | mutex_unlock(&sdata->local->mtx); | ||
924 | 928 | ||
925 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 929 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
926 | 930 | ||
927 | mutex_unlock(&sdata->u.ibss.mtx); | ||
928 | |||
929 | return 0; | 931 | return 0; |
930 | } | 932 | } |
931 | 933 | ||
@@ -980,7 +982,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
980 | 982 | ||
981 | mutex_unlock(&sdata->u.ibss.mtx); | 983 | mutex_unlock(&sdata->u.ibss.mtx); |
982 | 984 | ||
985 | mutex_lock(&local->mtx); | ||
983 | ieee80211_recalc_idle(sdata->local); | 986 | ieee80211_recalc_idle(sdata->local); |
987 | mutex_unlock(&local->mtx); | ||
984 | 988 | ||
985 | return 0; | 989 | return 0; |
986 | } | 990 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 65e0ed6c2975..9346a6b0f400 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -50,12 +50,6 @@ struct ieee80211_local; | |||
50 | * increased memory use (about 2 kB of RAM per entry). */ | 50 | * increased memory use (about 2 kB of RAM per entry). */ |
51 | #define IEEE80211_FRAGMENT_MAX 4 | 51 | #define IEEE80211_FRAGMENT_MAX 4 |
52 | 52 | ||
53 | /* | ||
54 | * Time after which we ignore scan results and no longer report/use | ||
55 | * them in any way. | ||
56 | */ | ||
57 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | ||
58 | |||
59 | #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) | 53 | #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) |
60 | 54 | ||
61 | #define IEEE80211_DEFAULT_UAPSD_QUEUES \ | 55 | #define IEEE80211_DEFAULT_UAPSD_QUEUES \ |
@@ -170,6 +164,7 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
170 | #define IEEE80211_RX_RA_MATCH BIT(1) | 164 | #define IEEE80211_RX_RA_MATCH BIT(1) |
171 | #define IEEE80211_RX_AMSDU BIT(2) | 165 | #define IEEE80211_RX_AMSDU BIT(2) |
172 | #define IEEE80211_RX_FRAGMENTED BIT(3) | 166 | #define IEEE80211_RX_FRAGMENTED BIT(3) |
167 | #define IEEE80211_MALFORMED_ACTION_FRM BIT(4) | ||
173 | /* only add flags here that do not change with subframes of an aMPDU */ | 168 | /* only add flags here that do not change with subframes of an aMPDU */ |
174 | 169 | ||
175 | struct ieee80211_rx_data { | 170 | struct ieee80211_rx_data { |
@@ -343,7 +338,10 @@ struct ieee80211_if_managed { | |||
343 | unsigned long timers_running; /* used for quiesce/restart */ | 338 | unsigned long timers_running; /* used for quiesce/restart */ |
344 | bool powersave; /* powersave requested for this iface */ | 339 | bool powersave; /* powersave requested for this iface */ |
345 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | 340 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ |
346 | ap_smps; /* smps mode AP thinks we're in */ | 341 | ap_smps, /* smps mode AP thinks we're in */ |
342 | driver_smps_mode; /* smps mode request */ | ||
343 | |||
344 | struct work_struct request_smps_work; | ||
347 | 345 | ||
348 | unsigned int flags; | 346 | unsigned int flags; |
349 | 347 | ||
@@ -371,6 +369,13 @@ struct ieee80211_if_managed { | |||
371 | int ave_beacon_signal; | 369 | int ave_beacon_signal; |
372 | 370 | ||
373 | /* | 371 | /* |
372 | * Number of Beacon frames used in ave_beacon_signal. This can be used | ||
373 | * to avoid generating less reliable cqm events that would be based | ||
374 | * only on couple of received frames. | ||
375 | */ | ||
376 | unsigned int count_beacon_signal; | ||
377 | |||
378 | /* | ||
374 | * Last Beacon frame signal strength average (ave_beacon_signal / 16) | 379 | * Last Beacon frame signal strength average (ave_beacon_signal / 16) |
375 | * that triggered a cqm event. 0 indicates that no event has been | 380 | * that triggered a cqm event. 0 indicates that no event has been |
376 | * generated for the current association. | 381 | * generated for the current association. |
@@ -474,6 +479,19 @@ enum ieee80211_sub_if_data_flags { | |||
474 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), | 479 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(3), |
475 | }; | 480 | }; |
476 | 481 | ||
482 | /** | ||
483 | * enum ieee80211_sdata_state_bits - virtual interface state bits | ||
484 | * @SDATA_STATE_RUNNING: virtual interface is up & running; this | ||
485 | * mirrors netif_running() but is separate for interface type | ||
486 | * change handling while the interface is up | ||
487 | * @SDATA_STATE_OFFCHANNEL: This interface is currently in offchannel | ||
488 | * mode, so queues are stopped | ||
489 | */ | ||
490 | enum ieee80211_sdata_state_bits { | ||
491 | SDATA_STATE_RUNNING, | ||
492 | SDATA_STATE_OFFCHANNEL, | ||
493 | }; | ||
494 | |||
477 | struct ieee80211_sub_if_data { | 495 | struct ieee80211_sub_if_data { |
478 | struct list_head list; | 496 | struct list_head list; |
479 | 497 | ||
@@ -487,6 +505,8 @@ struct ieee80211_sub_if_data { | |||
487 | 505 | ||
488 | unsigned int flags; | 506 | unsigned int flags; |
489 | 507 | ||
508 | unsigned long state; | ||
509 | |||
490 | int drop_unencrypted; | 510 | int drop_unencrypted; |
491 | 511 | ||
492 | char name[IFNAMSIZ]; | 512 | char name[IFNAMSIZ]; |
@@ -497,6 +517,9 @@ struct ieee80211_sub_if_data { | |||
497 | */ | 517 | */ |
498 | bool ht_opmode_valid; | 518 | bool ht_opmode_valid; |
499 | 519 | ||
520 | /* to detect idle changes */ | ||
521 | bool old_idle; | ||
522 | |||
500 | /* Fragment table for host-based reassembly */ | 523 | /* Fragment table for host-based reassembly */ |
501 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 524 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
502 | unsigned int fragment_next; | 525 | unsigned int fragment_next; |
@@ -508,6 +531,8 @@ struct ieee80211_sub_if_data { | |||
508 | struct ieee80211_key *default_mgmt_key; | 531 | struct ieee80211_key *default_mgmt_key; |
509 | 532 | ||
510 | u16 sequence_number; | 533 | u16 sequence_number; |
534 | __be16 control_port_protocol; | ||
535 | bool control_port_no_encrypt; | ||
511 | 536 | ||
512 | struct work_struct work; | 537 | struct work_struct work; |
513 | struct sk_buff_head skb_queue; | 538 | struct sk_buff_head skb_queue; |
@@ -595,11 +620,17 @@ enum queue_stop_reason { | |||
595 | * determine if we are on the operating channel or not | 620 | * determine if we are on the operating channel or not |
596 | * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, | 621 | * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, |
597 | * gets only set in conjunction with SCAN_SW_SCANNING | 622 | * gets only set in conjunction with SCAN_SW_SCANNING |
623 | * @SCAN_COMPLETED: Set for our scan work function when the driver reported | ||
624 | * that the scan completed. | ||
625 | * @SCAN_ABORTED: Set for our scan work function when the driver reported | ||
626 | * a scan complete for an aborted scan. | ||
598 | */ | 627 | */ |
599 | enum { | 628 | enum { |
600 | SCAN_SW_SCANNING, | 629 | SCAN_SW_SCANNING, |
601 | SCAN_HW_SCANNING, | 630 | SCAN_HW_SCANNING, |
602 | SCAN_OFF_CHANNEL, | 631 | SCAN_OFF_CHANNEL, |
632 | SCAN_COMPLETED, | ||
633 | SCAN_ABORTED, | ||
603 | }; | 634 | }; |
604 | 635 | ||
605 | /** | 636 | /** |
@@ -634,7 +665,6 @@ struct ieee80211_local { | |||
634 | /* | 665 | /* |
635 | * work stuff, potentially off-channel (in the future) | 666 | * work stuff, potentially off-channel (in the future) |
636 | */ | 667 | */ |
637 | struct mutex work_mtx; | ||
638 | struct list_head work_list; | 668 | struct list_head work_list; |
639 | struct timer_list work_timer; | 669 | struct timer_list work_timer; |
640 | struct work_struct work_work; | 670 | struct work_struct work_work; |
@@ -656,6 +686,8 @@ struct ieee80211_local { | |||
656 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll; | 686 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll; |
657 | unsigned int filter_flags; /* FIF_* */ | 687 | unsigned int filter_flags; /* FIF_* */ |
658 | 688 | ||
689 | bool wiphy_ciphers_allocated; | ||
690 | |||
659 | /* protects the aggregated multicast list and filter calls */ | 691 | /* protects the aggregated multicast list and filter calls */ |
660 | spinlock_t filter_lock; | 692 | spinlock_t filter_lock; |
661 | 693 | ||
@@ -746,9 +778,10 @@ struct ieee80211_local { | |||
746 | */ | 778 | */ |
747 | struct mutex key_mtx; | 779 | struct mutex key_mtx; |
748 | 780 | ||
781 | /* mutex for scan and work locking */ | ||
782 | struct mutex mtx; | ||
749 | 783 | ||
750 | /* Scanning and BSS list */ | 784 | /* Scanning and BSS list */ |
751 | struct mutex scan_mtx; | ||
752 | unsigned long scanning; | 785 | unsigned long scanning; |
753 | struct cfg80211_ssid scan_ssid; | 786 | struct cfg80211_ssid scan_ssid; |
754 | struct cfg80211_scan_request *int_scan_req; | 787 | struct cfg80211_scan_request *int_scan_req; |
@@ -870,6 +903,11 @@ struct ieee80211_local { | |||
870 | struct dentry *keys; | 903 | struct dentry *keys; |
871 | } debugfs; | 904 | } debugfs; |
872 | #endif | 905 | #endif |
906 | |||
907 | /* dummy netdev for use w/ NAPI */ | ||
908 | struct net_device napi_dev; | ||
909 | |||
910 | struct napi_struct napi; | ||
873 | }; | 911 | }; |
874 | 912 | ||
875 | static inline struct ieee80211_sub_if_data * | 913 | static inline struct ieee80211_sub_if_data * |
@@ -1003,6 +1041,8 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | |||
1003 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); | 1041 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); |
1004 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1042 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1005 | struct sk_buff *skb); | 1043 | struct sk_buff *skb); |
1044 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata); | ||
1045 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | ||
1006 | 1046 | ||
1007 | /* IBSS code */ | 1047 | /* IBSS code */ |
1008 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1048 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
@@ -1071,7 +1111,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local); | |||
1071 | 1111 | ||
1072 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | 1112 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) |
1073 | { | 1113 | { |
1074 | return netif_running(sdata->dev); | 1114 | return test_bit(SDATA_STATE_RUNNING, &sdata->state); |
1075 | } | 1115 | } |
1076 | 1116 | ||
1077 | /* tx handling */ | 1117 | /* tx handling */ |
@@ -1105,6 +1145,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
1105 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | 1145 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, |
1106 | enum ieee80211_smps_mode smps, const u8 *da, | 1146 | enum ieee80211_smps_mode smps, const u8 *da, |
1107 | const u8 *bssid); | 1147 | const u8 *bssid); |
1148 | void ieee80211_request_smps_work(struct work_struct *work); | ||
1108 | 1149 | ||
1109 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1150 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1110 | u16 initiator, u16 reason); | 1151 | u16 initiator, u16 reason); |
@@ -1131,6 +1172,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); | |||
1131 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); | 1172 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); |
1132 | void ieee80211_ba_session_work(struct work_struct *work); | 1173 | void ieee80211_ba_session_work(struct work_struct *work); |
1133 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); | 1174 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); |
1175 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid); | ||
1134 | 1176 | ||
1135 | /* Spectrum management */ | 1177 | /* Spectrum management */ |
1136 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 1178 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
@@ -1146,6 +1188,12 @@ int __ieee80211_suspend(struct ieee80211_hw *hw); | |||
1146 | 1188 | ||
1147 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) | 1189 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) |
1148 | { | 1190 | { |
1191 | struct ieee80211_local *local = hw_to_local(hw); | ||
1192 | |||
1193 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | ||
1194 | "%s: resume with hardware scan still in progress\n", | ||
1195 | wiphy_name(hw->wiphy)); | ||
1196 | |||
1149 | return ieee80211_reconfig(hw_to_local(hw)); | 1197 | return ieee80211_reconfig(hw_to_local(hw)); |
1150 | } | 1198 | } |
1151 | #else | 1199 | #else |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ebbe264e2b0b..66785739dad3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -94,21 +94,14 @@ static inline int identical_mac_addr_allowed(int type1, int type2) | |||
94 | type2 == NL80211_IFTYPE_AP_VLAN)); | 94 | type2 == NL80211_IFTYPE_AP_VLAN)); |
95 | } | 95 | } |
96 | 96 | ||
97 | static int ieee80211_open(struct net_device *dev) | 97 | static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, |
98 | enum nl80211_iftype iftype) | ||
98 | { | 99 | { |
99 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
100 | struct ieee80211_sub_if_data *nsdata; | ||
101 | struct ieee80211_local *local = sdata->local; | 100 | struct ieee80211_local *local = sdata->local; |
102 | struct sta_info *sta; | 101 | struct ieee80211_sub_if_data *nsdata; |
103 | u32 changed = 0; | 102 | struct net_device *dev = sdata->dev; |
104 | int res; | ||
105 | u32 hw_reconf_flags = 0; | ||
106 | u8 null_addr[ETH_ALEN] = {0}; | ||
107 | 103 | ||
108 | /* fail early if user set an invalid address */ | 104 | ASSERT_RTNL(); |
109 | if (compare_ether_addr(dev->dev_addr, null_addr) && | ||
110 | !is_valid_ether_addr(dev->dev_addr)) | ||
111 | return -EADDRNOTAVAIL; | ||
112 | 105 | ||
113 | /* we hold the RTNL here so can safely walk the list */ | 106 | /* we hold the RTNL here so can safely walk the list */ |
114 | list_for_each_entry(nsdata, &local->interfaces, list) { | 107 | list_for_each_entry(nsdata, &local->interfaces, list) { |
@@ -125,7 +118,7 @@ static int ieee80211_open(struct net_device *dev) | |||
125 | * belonging to the same hardware. Then, however, we're | 118 | * belonging to the same hardware. Then, however, we're |
126 | * faced with having to adopt two different TSF timers... | 119 | * faced with having to adopt two different TSF timers... |
127 | */ | 120 | */ |
128 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 121 | if (iftype == NL80211_IFTYPE_ADHOC && |
129 | nsdata->vif.type == NL80211_IFTYPE_ADHOC) | 122 | nsdata->vif.type == NL80211_IFTYPE_ADHOC) |
130 | return -EBUSY; | 123 | return -EBUSY; |
131 | 124 | ||
@@ -139,19 +132,36 @@ static int ieee80211_open(struct net_device *dev) | |||
139 | /* | 132 | /* |
140 | * check whether it may have the same address | 133 | * check whether it may have the same address |
141 | */ | 134 | */ |
142 | if (!identical_mac_addr_allowed(sdata->vif.type, | 135 | if (!identical_mac_addr_allowed(iftype, |
143 | nsdata->vif.type)) | 136 | nsdata->vif.type)) |
144 | return -ENOTUNIQ; | 137 | return -ENOTUNIQ; |
145 | 138 | ||
146 | /* | 139 | /* |
147 | * can only add VLANs to enabled APs | 140 | * can only add VLANs to enabled APs |
148 | */ | 141 | */ |
149 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | 142 | if (iftype == NL80211_IFTYPE_AP_VLAN && |
150 | nsdata->vif.type == NL80211_IFTYPE_AP) | 143 | nsdata->vif.type == NL80211_IFTYPE_AP) |
151 | sdata->bss = &nsdata->u.ap; | 144 | sdata->bss = &nsdata->u.ap; |
152 | } | 145 | } |
153 | } | 146 | } |
154 | 147 | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * NOTE: Be very careful when changing this function, it must NOT return | ||
153 | * an error on interface type changes that have been pre-checked, so most | ||
154 | * checks should be in ieee80211_check_concurrent_iface. | ||
155 | */ | ||
156 | static int ieee80211_do_open(struct net_device *dev, bool coming_up) | ||
157 | { | ||
158 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
159 | struct ieee80211_local *local = sdata->local; | ||
160 | struct sta_info *sta; | ||
161 | u32 changed = 0; | ||
162 | int res; | ||
163 | u32 hw_reconf_flags = 0; | ||
164 | |||
155 | switch (sdata->vif.type) { | 165 | switch (sdata->vif.type) { |
156 | case NL80211_IFTYPE_WDS: | 166 | case NL80211_IFTYPE_WDS: |
157 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) | 167 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) |
@@ -177,7 +187,9 @@ static int ieee80211_open(struct net_device *dev) | |||
177 | /* no special treatment */ | 187 | /* no special treatment */ |
178 | break; | 188 | break; |
179 | case NL80211_IFTYPE_UNSPECIFIED: | 189 | case NL80211_IFTYPE_UNSPECIFIED: |
180 | case __NL80211_IFTYPE_AFTER_LAST: | 190 | case NUM_NL80211_IFTYPES: |
191 | case NL80211_IFTYPE_P2P_CLIENT: | ||
192 | case NL80211_IFTYPE_P2P_GO: | ||
181 | /* cannot happen */ | 193 | /* cannot happen */ |
182 | WARN_ON(1); | 194 | WARN_ON(1); |
183 | break; | 195 | break; |
@@ -187,39 +199,30 @@ static int ieee80211_open(struct net_device *dev) | |||
187 | res = drv_start(local); | 199 | res = drv_start(local); |
188 | if (res) | 200 | if (res) |
189 | goto err_del_bss; | 201 | goto err_del_bss; |
202 | if (local->ops->napi_poll) | ||
203 | napi_enable(&local->napi); | ||
190 | /* we're brought up, everything changes */ | 204 | /* we're brought up, everything changes */ |
191 | hw_reconf_flags = ~0; | 205 | hw_reconf_flags = ~0; |
192 | ieee80211_led_radio(local, true); | 206 | ieee80211_led_radio(local, true); |
193 | } | 207 | } |
194 | 208 | ||
195 | /* | 209 | /* |
196 | * Check all interfaces and copy the hopefully now-present | 210 | * Copy the hopefully now-present MAC address to |
197 | * MAC address to those that have the special null one. | 211 | * this interface, if it has the special null one. |
198 | */ | 212 | */ |
199 | list_for_each_entry(nsdata, &local->interfaces, list) { | 213 | if (is_zero_ether_addr(dev->dev_addr)) { |
200 | struct net_device *ndev = nsdata->dev; | 214 | memcpy(dev->dev_addr, |
201 | 215 | local->hw.wiphy->perm_addr, | |
202 | /* | 216 | ETH_ALEN); |
203 | * No need to check running since we do not allow | 217 | memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); |
204 | * it to start up with this invalid address. | 218 | |
205 | */ | 219 | if (!is_valid_ether_addr(dev->dev_addr)) { |
206 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { | 220 | if (!local->open_count) |
207 | memcpy(ndev->dev_addr, | 221 | drv_stop(local); |
208 | local->hw.wiphy->perm_addr, | 222 | return -EADDRNOTAVAIL; |
209 | ETH_ALEN); | ||
210 | memcpy(ndev->perm_addr, ndev->dev_addr, ETH_ALEN); | ||
211 | } | 223 | } |
212 | } | 224 | } |
213 | 225 | ||
214 | /* | ||
215 | * Validate the MAC address for this device. | ||
216 | */ | ||
217 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
218 | if (!local->open_count) | ||
219 | drv_stop(local); | ||
220 | return -EADDRNOTAVAIL; | ||
221 | } | ||
222 | |||
223 | switch (sdata->vif.type) { | 226 | switch (sdata->vif.type) { |
224 | case NL80211_IFTYPE_AP_VLAN: | 227 | case NL80211_IFTYPE_AP_VLAN: |
225 | /* no need to tell driver */ | 228 | /* no need to tell driver */ |
@@ -253,9 +256,11 @@ static int ieee80211_open(struct net_device *dev) | |||
253 | netif_carrier_on(dev); | 256 | netif_carrier_on(dev); |
254 | break; | 257 | break; |
255 | default: | 258 | default: |
256 | res = drv_add_interface(local, &sdata->vif); | 259 | if (coming_up) { |
257 | if (res) | 260 | res = drv_add_interface(local, &sdata->vif); |
258 | goto err_stop; | 261 | if (res) |
262 | goto err_stop; | ||
263 | } | ||
259 | 264 | ||
260 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 265 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
261 | local->fif_other_bss++; | 266 | local->fif_other_bss++; |
@@ -277,6 +282,8 @@ static int ieee80211_open(struct net_device *dev) | |||
277 | netif_carrier_on(dev); | 282 | netif_carrier_on(dev); |
278 | } | 283 | } |
279 | 284 | ||
285 | set_bit(SDATA_STATE_RUNNING, &sdata->state); | ||
286 | |||
280 | if (sdata->vif.type == NL80211_IFTYPE_WDS) { | 287 | if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
281 | /* Create STA entry for the WDS peer */ | 288 | /* Create STA entry for the WDS peer */ |
282 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, | 289 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, |
@@ -307,9 +314,13 @@ static int ieee80211_open(struct net_device *dev) | |||
307 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 314 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
308 | atomic_inc(&local->iff_promiscs); | 315 | atomic_inc(&local->iff_promiscs); |
309 | 316 | ||
317 | mutex_lock(&local->mtx); | ||
310 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | 318 | hw_reconf_flags |= __ieee80211_recalc_idle(local); |
319 | mutex_unlock(&local->mtx); | ||
320 | |||
321 | if (coming_up) | ||
322 | local->open_count++; | ||
311 | 323 | ||
312 | local->open_count++; | ||
313 | if (hw_reconf_flags) { | 324 | if (hw_reconf_flags) { |
314 | ieee80211_hw_config(local, hw_reconf_flags); | 325 | ieee80211_hw_config(local, hw_reconf_flags); |
315 | /* | 326 | /* |
@@ -334,22 +345,42 @@ static int ieee80211_open(struct net_device *dev) | |||
334 | sdata->bss = NULL; | 345 | sdata->bss = NULL; |
335 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 346 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
336 | list_del(&sdata->u.vlan.list); | 347 | list_del(&sdata->u.vlan.list); |
348 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | ||
337 | return res; | 349 | return res; |
338 | } | 350 | } |
339 | 351 | ||
340 | static int ieee80211_stop(struct net_device *dev) | 352 | static int ieee80211_open(struct net_device *dev) |
341 | { | 353 | { |
342 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 354 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
355 | int err; | ||
356 | |||
357 | /* fail early if user set an invalid address */ | ||
358 | if (!is_zero_ether_addr(dev->dev_addr) && | ||
359 | !is_valid_ether_addr(dev->dev_addr)) | ||
360 | return -EADDRNOTAVAIL; | ||
361 | |||
362 | err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); | ||
363 | if (err) | ||
364 | return err; | ||
365 | |||
366 | return ieee80211_do_open(dev, true); | ||
367 | } | ||
368 | |||
369 | static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | ||
370 | bool going_down) | ||
371 | { | ||
343 | struct ieee80211_local *local = sdata->local; | 372 | struct ieee80211_local *local = sdata->local; |
344 | unsigned long flags; | 373 | unsigned long flags; |
345 | struct sk_buff *skb, *tmp; | 374 | struct sk_buff *skb, *tmp; |
346 | u32 hw_reconf_flags = 0; | 375 | u32 hw_reconf_flags = 0; |
347 | int i; | 376 | int i; |
348 | 377 | ||
378 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | ||
379 | |||
349 | /* | 380 | /* |
350 | * Stop TX on this interface first. | 381 | * Stop TX on this interface first. |
351 | */ | 382 | */ |
352 | netif_tx_stop_all_queues(dev); | 383 | netif_tx_stop_all_queues(sdata->dev); |
353 | 384 | ||
354 | /* | 385 | /* |
355 | * Purge work for this interface. | 386 | * Purge work for this interface. |
@@ -366,12 +397,9 @@ static int ieee80211_stop(struct net_device *dev) | |||
366 | * (because if we remove a STA after ops->remove_interface() | 397 | * (because if we remove a STA after ops->remove_interface() |
367 | * the driver will have removed the vif info already!) | 398 | * the driver will have removed the vif info already!) |
368 | * | 399 | * |
369 | * We could relax this and only unlink the stations from the | 400 | * This is relevant only in AP, WDS and mesh modes, since in |
370 | * hash table and list but keep them on a per-sdata list that | 401 | * all other modes we've already removed all stations when |
371 | * will be inserted back again when the interface is brought | 402 | * disconnecting etc. |
372 | * up again, but I don't currently see a use case for that, | ||
373 | * except with WDS which gets a STA entry created when it is | ||
374 | * brought up. | ||
375 | */ | 403 | */ |
376 | sta_info_flush(local, sdata); | 404 | sta_info_flush(local, sdata); |
377 | 405 | ||
@@ -390,11 +418,12 @@ static int ieee80211_stop(struct net_device *dev) | |||
390 | if (sdata->vif.type == NL80211_IFTYPE_AP) | 418 | if (sdata->vif.type == NL80211_IFTYPE_AP) |
391 | local->fif_pspoll--; | 419 | local->fif_pspoll--; |
392 | 420 | ||
393 | netif_addr_lock_bh(dev); | 421 | netif_addr_lock_bh(sdata->dev); |
394 | spin_lock_bh(&local->filter_lock); | 422 | spin_lock_bh(&local->filter_lock); |
395 | __hw_addr_unsync(&local->mc_list, &dev->mc, dev->addr_len); | 423 | __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, |
424 | sdata->dev->addr_len); | ||
396 | spin_unlock_bh(&local->filter_lock); | 425 | spin_unlock_bh(&local->filter_lock); |
397 | netif_addr_unlock_bh(dev); | 426 | netif_addr_unlock_bh(sdata->dev); |
398 | 427 | ||
399 | ieee80211_configure_filter(local); | 428 | ieee80211_configure_filter(local); |
400 | 429 | ||
@@ -406,11 +435,21 @@ static int ieee80211_stop(struct net_device *dev) | |||
406 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 435 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
407 | struct beacon_data *old_beacon = sdata->u.ap.beacon; | 436 | struct beacon_data *old_beacon = sdata->u.ap.beacon; |
408 | 437 | ||
438 | /* sdata_running will return false, so this will disable */ | ||
439 | ieee80211_bss_info_change_notify(sdata, | ||
440 | BSS_CHANGED_BEACON_ENABLED); | ||
441 | |||
409 | /* remove beacon */ | 442 | /* remove beacon */ |
410 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | 443 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); |
411 | synchronize_rcu(); | 444 | synchronize_rcu(); |
412 | kfree(old_beacon); | 445 | kfree(old_beacon); |
413 | 446 | ||
447 | /* free all potentially still buffered bcast frames */ | ||
448 | while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { | ||
449 | local->total_ps_buffered--; | ||
450 | dev_kfree_skb(skb); | ||
451 | } | ||
452 | |||
414 | /* down all dependent devices, that is VLANs */ | 453 | /* down all dependent devices, that is VLANs */ |
415 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 454 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
416 | u.vlan.list) | 455 | u.vlan.list) |
@@ -418,7 +457,8 @@ static int ieee80211_stop(struct net_device *dev) | |||
418 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | 457 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); |
419 | } | 458 | } |
420 | 459 | ||
421 | local->open_count--; | 460 | if (going_down) |
461 | local->open_count--; | ||
422 | 462 | ||
423 | switch (sdata->vif.type) { | 463 | switch (sdata->vif.type) { |
424 | case NL80211_IFTYPE_AP_VLAN: | 464 | case NL80211_IFTYPE_AP_VLAN: |
@@ -450,27 +490,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
450 | 490 | ||
451 | ieee80211_configure_filter(local); | 491 | ieee80211_configure_filter(local); |
452 | break; | 492 | break; |
453 | case NL80211_IFTYPE_STATION: | ||
454 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | ||
455 | del_timer_sync(&sdata->u.mgd.timer); | ||
456 | del_timer_sync(&sdata->u.mgd.conn_mon_timer); | ||
457 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); | ||
458 | /* | ||
459 | * If any of the timers fired while we waited for it, it will | ||
460 | * have queued its work. Now the work will be running again | ||
461 | * but will not rearm the timer again because it checks | ||
462 | * whether the interface is running, which, at this point, | ||
463 | * it no longer is. | ||
464 | */ | ||
465 | cancel_work_sync(&sdata->u.mgd.chswitch_work); | ||
466 | cancel_work_sync(&sdata->u.mgd.monitor_work); | ||
467 | cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work); | ||
468 | |||
469 | /* fall through */ | ||
470 | case NL80211_IFTYPE_ADHOC: | ||
471 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
472 | del_timer_sync(&sdata->u.ibss.timer); | ||
473 | /* fall through */ | ||
474 | case NL80211_IFTYPE_MESH_POINT: | 493 | case NL80211_IFTYPE_MESH_POINT: |
475 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 494 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
476 | /* other_bss and allmulti are always set on mesh | 495 | /* other_bss and allmulti are always set on mesh |
@@ -498,27 +517,34 @@ static int ieee80211_stop(struct net_device *dev) | |||
498 | ieee80211_scan_cancel(local); | 517 | ieee80211_scan_cancel(local); |
499 | 518 | ||
500 | /* | 519 | /* |
501 | * Disable beaconing for AP and mesh, IBSS can't | 520 | * Disable beaconing here for mesh only, AP and IBSS |
502 | * still be joined to a network at this point. | 521 | * are already taken care of. |
503 | */ | 522 | */ |
504 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 523 | if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
505 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) { | ||
506 | ieee80211_bss_info_change_notify(sdata, | 524 | ieee80211_bss_info_change_notify(sdata, |
507 | BSS_CHANGED_BEACON_ENABLED); | 525 | BSS_CHANGED_BEACON_ENABLED); |
508 | } | ||
509 | 526 | ||
510 | /* free all remaining keys, there shouldn't be any */ | 527 | /* |
528 | * Free all remaining keys, there shouldn't be any, | ||
529 | * except maybe group keys in AP more or WDS? | ||
530 | */ | ||
511 | ieee80211_free_keys(sdata); | 531 | ieee80211_free_keys(sdata); |
512 | drv_remove_interface(local, &sdata->vif); | 532 | |
533 | if (going_down) | ||
534 | drv_remove_interface(local, &sdata->vif); | ||
513 | } | 535 | } |
514 | 536 | ||
515 | sdata->bss = NULL; | 537 | sdata->bss = NULL; |
516 | 538 | ||
539 | mutex_lock(&local->mtx); | ||
517 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | 540 | hw_reconf_flags |= __ieee80211_recalc_idle(local); |
541 | mutex_unlock(&local->mtx); | ||
518 | 542 | ||
519 | ieee80211_recalc_ps(local, -1); | 543 | ieee80211_recalc_ps(local, -1); |
520 | 544 | ||
521 | if (local->open_count == 0) { | 545 | if (local->open_count == 0) { |
546 | if (local->ops->napi_poll) | ||
547 | napi_disable(&local->napi); | ||
522 | ieee80211_clear_tx_pending(local); | 548 | ieee80211_clear_tx_pending(local); |
523 | ieee80211_stop_device(local); | 549 | ieee80211_stop_device(local); |
524 | 550 | ||
@@ -541,6 +567,13 @@ static int ieee80211_stop(struct net_device *dev) | |||
541 | } | 567 | } |
542 | } | 568 | } |
543 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 569 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
570 | } | ||
571 | |||
572 | static int ieee80211_stop(struct net_device *dev) | ||
573 | { | ||
574 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
575 | |||
576 | ieee80211_do_stop(sdata, true); | ||
544 | 577 | ||
545 | return 0; | 578 | return 0; |
546 | } | 579 | } |
@@ -585,8 +618,6 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
585 | { | 618 | { |
586 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 619 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
587 | struct ieee80211_local *local = sdata->local; | 620 | struct ieee80211_local *local = sdata->local; |
588 | struct beacon_data *beacon; | ||
589 | struct sk_buff *skb; | ||
590 | int flushed; | 621 | int flushed; |
591 | int i; | 622 | int i; |
592 | 623 | ||
@@ -599,37 +630,8 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
599 | __skb_queue_purge(&sdata->fragments[i].skb_list); | 630 | __skb_queue_purge(&sdata->fragments[i].skb_list); |
600 | sdata->fragment_next = 0; | 631 | sdata->fragment_next = 0; |
601 | 632 | ||
602 | switch (sdata->vif.type) { | 633 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
603 | case NL80211_IFTYPE_AP: | 634 | mesh_rmc_free(sdata); |
604 | beacon = sdata->u.ap.beacon; | ||
605 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | ||
606 | synchronize_rcu(); | ||
607 | kfree(beacon); | ||
608 | |||
609 | while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { | ||
610 | local->total_ps_buffered--; | ||
611 | dev_kfree_skb(skb); | ||
612 | } | ||
613 | |||
614 | break; | ||
615 | case NL80211_IFTYPE_MESH_POINT: | ||
616 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
617 | mesh_rmc_free(sdata); | ||
618 | break; | ||
619 | case NL80211_IFTYPE_ADHOC: | ||
620 | if (WARN_ON(sdata->u.ibss.presp)) | ||
621 | kfree_skb(sdata->u.ibss.presp); | ||
622 | break; | ||
623 | case NL80211_IFTYPE_STATION: | ||
624 | case NL80211_IFTYPE_WDS: | ||
625 | case NL80211_IFTYPE_AP_VLAN: | ||
626 | case NL80211_IFTYPE_MONITOR: | ||
627 | break; | ||
628 | case NL80211_IFTYPE_UNSPECIFIED: | ||
629 | case __NL80211_IFTYPE_AFTER_LAST: | ||
630 | BUG(); | ||
631 | break; | ||
632 | } | ||
633 | 635 | ||
634 | flushed = sta_info_flush(local, sdata); | 636 | flushed = sta_info_flush(local, sdata); |
635 | WARN_ON(flushed); | 637 | WARN_ON(flushed); |
@@ -844,9 +846,13 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
844 | 846 | ||
845 | /* and set some type-dependent values */ | 847 | /* and set some type-dependent values */ |
846 | sdata->vif.type = type; | 848 | sdata->vif.type = type; |
849 | sdata->vif.p2p = false; | ||
847 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; | 850 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; |
848 | sdata->wdev.iftype = type; | 851 | sdata->wdev.iftype = type; |
849 | 852 | ||
853 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); | ||
854 | sdata->control_port_no_encrypt = false; | ||
855 | |||
850 | /* only monitor differs */ | 856 | /* only monitor differs */ |
851 | sdata->dev->type = ARPHRD_ETHER; | 857 | sdata->dev->type = ARPHRD_ETHER; |
852 | 858 | ||
@@ -854,10 +860,20 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
854 | INIT_WORK(&sdata->work, ieee80211_iface_work); | 860 | INIT_WORK(&sdata->work, ieee80211_iface_work); |
855 | 861 | ||
856 | switch (type) { | 862 | switch (type) { |
863 | case NL80211_IFTYPE_P2P_GO: | ||
864 | type = NL80211_IFTYPE_AP; | ||
865 | sdata->vif.type = type; | ||
866 | sdata->vif.p2p = true; | ||
867 | /* fall through */ | ||
857 | case NL80211_IFTYPE_AP: | 868 | case NL80211_IFTYPE_AP: |
858 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 869 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
859 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 870 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
860 | break; | 871 | break; |
872 | case NL80211_IFTYPE_P2P_CLIENT: | ||
873 | type = NL80211_IFTYPE_STATION; | ||
874 | sdata->vif.type = type; | ||
875 | sdata->vif.p2p = true; | ||
876 | /* fall through */ | ||
861 | case NL80211_IFTYPE_STATION: | 877 | case NL80211_IFTYPE_STATION: |
862 | ieee80211_sta_setup_sdata(sdata); | 878 | ieee80211_sta_setup_sdata(sdata); |
863 | break; | 879 | break; |
@@ -878,7 +894,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
878 | case NL80211_IFTYPE_AP_VLAN: | 894 | case NL80211_IFTYPE_AP_VLAN: |
879 | break; | 895 | break; |
880 | case NL80211_IFTYPE_UNSPECIFIED: | 896 | case NL80211_IFTYPE_UNSPECIFIED: |
881 | case __NL80211_IFTYPE_AFTER_LAST: | 897 | case NUM_NL80211_IFTYPES: |
882 | BUG(); | 898 | BUG(); |
883 | break; | 899 | break; |
884 | } | 900 | } |
@@ -886,12 +902,85 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
886 | ieee80211_debugfs_add_netdev(sdata); | 902 | ieee80211_debugfs_add_netdev(sdata); |
887 | } | 903 | } |
888 | 904 | ||
905 | static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | ||
906 | enum nl80211_iftype type) | ||
907 | { | ||
908 | struct ieee80211_local *local = sdata->local; | ||
909 | int ret, err; | ||
910 | enum nl80211_iftype internal_type = type; | ||
911 | bool p2p = false; | ||
912 | |||
913 | ASSERT_RTNL(); | ||
914 | |||
915 | if (!local->ops->change_interface) | ||
916 | return -EBUSY; | ||
917 | |||
918 | switch (sdata->vif.type) { | ||
919 | case NL80211_IFTYPE_AP: | ||
920 | case NL80211_IFTYPE_STATION: | ||
921 | case NL80211_IFTYPE_ADHOC: | ||
922 | /* | ||
923 | * Could maybe also all others here? | ||
924 | * Just not sure how that interacts | ||
925 | * with the RX/config path e.g. for | ||
926 | * mesh. | ||
927 | */ | ||
928 | break; | ||
929 | default: | ||
930 | return -EBUSY; | ||
931 | } | ||
932 | |||
933 | switch (type) { | ||
934 | case NL80211_IFTYPE_AP: | ||
935 | case NL80211_IFTYPE_STATION: | ||
936 | case NL80211_IFTYPE_ADHOC: | ||
937 | /* | ||
938 | * Could probably support everything | ||
939 | * but WDS here (WDS do_open can fail | ||
940 | * under memory pressure, which this | ||
941 | * code isn't prepared to handle). | ||
942 | */ | ||
943 | break; | ||
944 | case NL80211_IFTYPE_P2P_CLIENT: | ||
945 | p2p = true; | ||
946 | internal_type = NL80211_IFTYPE_STATION; | ||
947 | break; | ||
948 | case NL80211_IFTYPE_P2P_GO: | ||
949 | p2p = true; | ||
950 | internal_type = NL80211_IFTYPE_AP; | ||
951 | break; | ||
952 | default: | ||
953 | return -EBUSY; | ||
954 | } | ||
955 | |||
956 | ret = ieee80211_check_concurrent_iface(sdata, internal_type); | ||
957 | if (ret) | ||
958 | return ret; | ||
959 | |||
960 | ieee80211_do_stop(sdata, false); | ||
961 | |||
962 | ieee80211_teardown_sdata(sdata->dev); | ||
963 | |||
964 | ret = drv_change_interface(local, sdata, internal_type, p2p); | ||
965 | if (ret) | ||
966 | type = sdata->vif.type; | ||
967 | |||
968 | ieee80211_setup_sdata(sdata, type); | ||
969 | |||
970 | err = ieee80211_do_open(sdata->dev, false); | ||
971 | WARN(err, "type change: do_open returned %d", err); | ||
972 | |||
973 | return ret; | ||
974 | } | ||
975 | |||
889 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | 976 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
890 | enum nl80211_iftype type) | 977 | enum nl80211_iftype type) |
891 | { | 978 | { |
979 | int ret; | ||
980 | |||
892 | ASSERT_RTNL(); | 981 | ASSERT_RTNL(); |
893 | 982 | ||
894 | if (type == sdata->vif.type) | 983 | if (type == ieee80211_vif_type_p2p(&sdata->vif)) |
895 | return 0; | 984 | return 0; |
896 | 985 | ||
897 | /* Setting ad-hoc mode on non-IBSS channel is not supported. */ | 986 | /* Setting ad-hoc mode on non-IBSS channel is not supported. */ |
@@ -899,18 +988,15 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
899 | type == NL80211_IFTYPE_ADHOC) | 988 | type == NL80211_IFTYPE_ADHOC) |
900 | return -EOPNOTSUPP; | 989 | return -EOPNOTSUPP; |
901 | 990 | ||
902 | /* | 991 | if (ieee80211_sdata_running(sdata)) { |
903 | * We could, here, on changes between IBSS/STA/MESH modes, | 992 | ret = ieee80211_runtime_change_iftype(sdata, type); |
904 | * invoke an MLME function instead that disassociates etc. | 993 | if (ret) |
905 | * and goes into the requested mode. | 994 | return ret; |
906 | */ | 995 | } else { |
907 | 996 | /* Purge and reset type-dependent state. */ | |
908 | if (ieee80211_sdata_running(sdata)) | 997 | ieee80211_teardown_sdata(sdata->dev); |
909 | return -EBUSY; | 998 | ieee80211_setup_sdata(sdata, type); |
910 | 999 | } | |
911 | /* Purge and reset type-dependent state. */ | ||
912 | ieee80211_teardown_sdata(sdata->dev); | ||
913 | ieee80211_setup_sdata(sdata, type); | ||
914 | 1000 | ||
915 | /* reset some values that shouldn't be kept across type changes */ | 1001 | /* reset some values that shouldn't be kept across type changes */ |
916 | sdata->vif.bss_conf.basic_rates = | 1002 | sdata->vif.bss_conf.basic_rates = |
@@ -1167,8 +1253,7 @@ static u32 ieee80211_idle_off(struct ieee80211_local *local, | |||
1167 | return 0; | 1253 | return 0; |
1168 | 1254 | ||
1169 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1255 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1170 | printk(KERN_DEBUG "%s: device no longer idle - %s\n", | 1256 | wiphy_debug(local->hw.wiphy, "device no longer idle - %s\n", reason); |
1171 | wiphy_name(local->hw.wiphy), reason); | ||
1172 | #endif | 1257 | #endif |
1173 | 1258 | ||
1174 | local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; | 1259 | local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; |
@@ -1181,8 +1266,7 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
1181 | return 0; | 1266 | return 0; |
1182 | 1267 | ||
1183 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1268 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1184 | printk(KERN_DEBUG "%s: device now idle\n", | 1269 | wiphy_debug(local->hw.wiphy, "device now idle\n"); |
1185 | wiphy_name(local->hw.wiphy)); | ||
1186 | #endif | 1270 | #endif |
1187 | 1271 | ||
1188 | drv_flush(local, false); | 1272 | drv_flush(local, false); |
@@ -1195,28 +1279,61 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1195 | { | 1279 | { |
1196 | struct ieee80211_sub_if_data *sdata; | 1280 | struct ieee80211_sub_if_data *sdata; |
1197 | int count = 0; | 1281 | int count = 0; |
1282 | bool working = false, scanning = false; | ||
1283 | struct ieee80211_work *wk; | ||
1198 | 1284 | ||
1199 | if (!list_empty(&local->work_list)) | 1285 | #ifdef CONFIG_PROVE_LOCKING |
1200 | return ieee80211_idle_off(local, "working"); | 1286 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && |
1201 | 1287 | !lockdep_is_held(&local->iflist_mtx)); | |
1202 | if (local->scanning) | 1288 | #endif |
1203 | return ieee80211_idle_off(local, "scanning"); | 1289 | lockdep_assert_held(&local->mtx); |
1204 | 1290 | ||
1205 | list_for_each_entry(sdata, &local->interfaces, list) { | 1291 | list_for_each_entry(sdata, &local->interfaces, list) { |
1206 | if (!ieee80211_sdata_running(sdata)) | 1292 | if (!ieee80211_sdata_running(sdata)) { |
1293 | sdata->vif.bss_conf.idle = true; | ||
1207 | continue; | 1294 | continue; |
1295 | } | ||
1296 | |||
1297 | sdata->old_idle = sdata->vif.bss_conf.idle; | ||
1298 | |||
1208 | /* do not count disabled managed interfaces */ | 1299 | /* do not count disabled managed interfaces */ |
1209 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1300 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1210 | !sdata->u.mgd.associated) | 1301 | !sdata->u.mgd.associated) { |
1302 | sdata->vif.bss_conf.idle = true; | ||
1211 | continue; | 1303 | continue; |
1304 | } | ||
1212 | /* do not count unused IBSS interfaces */ | 1305 | /* do not count unused IBSS interfaces */ |
1213 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 1306 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
1214 | !sdata->u.ibss.ssid_len) | 1307 | !sdata->u.ibss.ssid_len) { |
1308 | sdata->vif.bss_conf.idle = true; | ||
1215 | continue; | 1309 | continue; |
1310 | } | ||
1216 | /* count everything else */ | 1311 | /* count everything else */ |
1217 | count++; | 1312 | count++; |
1218 | } | 1313 | } |
1219 | 1314 | ||
1315 | list_for_each_entry(wk, &local->work_list, list) { | ||
1316 | working = true; | ||
1317 | wk->sdata->vif.bss_conf.idle = false; | ||
1318 | } | ||
1319 | |||
1320 | if (local->scan_sdata) { | ||
1321 | scanning = true; | ||
1322 | local->scan_sdata->vif.bss_conf.idle = false; | ||
1323 | } | ||
1324 | |||
1325 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1326 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | ||
1327 | continue; | ||
1328 | if (!ieee80211_sdata_running(sdata)) | ||
1329 | continue; | ||
1330 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
1331 | } | ||
1332 | |||
1333 | if (working) | ||
1334 | return ieee80211_idle_off(local, "working"); | ||
1335 | if (scanning) | ||
1336 | return ieee80211_idle_off(local, "scanning"); | ||
1220 | if (!count) | 1337 | if (!count) |
1221 | return ieee80211_idle_on(local); | 1338 | return ieee80211_idle_on(local); |
1222 | else | 1339 | else |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 1b9d87ed143a..6a63d1abd14d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -49,7 +49,7 @@ static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | |||
49 | 49 | ||
50 | static void assert_key_lock(struct ieee80211_local *local) | 50 | static void assert_key_lock(struct ieee80211_local *local) |
51 | { | 51 | { |
52 | WARN_ON(!mutex_is_locked(&local->key_mtx)); | 52 | lockdep_assert_held(&local->key_mtx); |
53 | } | 53 | } |
54 | 54 | ||
55 | static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) | 55 | static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) |
@@ -60,7 +60,7 @@ static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) | |||
60 | return NULL; | 60 | return NULL; |
61 | } | 61 | } |
62 | 62 | ||
63 | static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | 63 | static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) |
64 | { | 64 | { |
65 | struct ieee80211_sub_if_data *sdata; | 65 | struct ieee80211_sub_if_data *sdata; |
66 | struct ieee80211_sta *sta; | 66 | struct ieee80211_sta *sta; |
@@ -68,8 +68,10 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
68 | 68 | ||
69 | might_sleep(); | 69 | might_sleep(); |
70 | 70 | ||
71 | if (!key->local->ops->set_key) | 71 | if (!key->local->ops->set_key) { |
72 | return; | 72 | ret = -EOPNOTSUPP; |
73 | goto out_unsupported; | ||
74 | } | ||
73 | 75 | ||
74 | assert_key_lock(key->local); | 76 | assert_key_lock(key->local); |
75 | 77 | ||
@@ -87,10 +89,27 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
87 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 89 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
88 | 90 | ||
89 | if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) | 91 | if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) |
90 | printk(KERN_ERR "mac80211-%s: failed to set key " | 92 | wiphy_err(key->local->hw.wiphy, |
91 | "(%d, %pM) to hardware (%d)\n", | 93 | "failed to set key (%d, %pM) to hardware (%d)\n", |
92 | wiphy_name(key->local->hw.wiphy), | 94 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
93 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); | 95 | |
96 | out_unsupported: | ||
97 | if (ret) { | ||
98 | switch (key->conf.cipher) { | ||
99 | case WLAN_CIPHER_SUITE_WEP40: | ||
100 | case WLAN_CIPHER_SUITE_WEP104: | ||
101 | case WLAN_CIPHER_SUITE_TKIP: | ||
102 | case WLAN_CIPHER_SUITE_CCMP: | ||
103 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
104 | /* all of these we can do in software */ | ||
105 | ret = 0; | ||
106 | break; | ||
107 | default: | ||
108 | ret = -EINVAL; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | return ret; | ||
94 | } | 113 | } |
95 | 114 | ||
96 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | 115 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) |
@@ -121,10 +140,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
121 | sta, &key->conf); | 140 | sta, &key->conf); |
122 | 141 | ||
123 | if (ret) | 142 | if (ret) |
124 | printk(KERN_ERR "mac80211-%s: failed to remove key " | 143 | wiphy_err(key->local->hw.wiphy, |
125 | "(%d, %pM) from hardware (%d)\n", | 144 | "failed to remove key (%d, %pM) from hardware (%d)\n", |
126 | wiphy_name(key->local->hw.wiphy), | 145 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
127 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); | ||
128 | 146 | ||
129 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 147 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
130 | } | 148 | } |
@@ -227,20 +245,18 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
227 | } | 245 | } |
228 | } | 246 | } |
229 | 247 | ||
230 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 248 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
231 | int idx, | ||
232 | size_t key_len, | ||
233 | const u8 *key_data, | 249 | const u8 *key_data, |
234 | size_t seq_len, const u8 *seq) | 250 | size_t seq_len, const u8 *seq) |
235 | { | 251 | { |
236 | struct ieee80211_key *key; | 252 | struct ieee80211_key *key; |
237 | int i, j; | 253 | int i, j, err; |
238 | 254 | ||
239 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); | 255 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); |
240 | 256 | ||
241 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); | 257 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); |
242 | if (!key) | 258 | if (!key) |
243 | return NULL; | 259 | return ERR_PTR(-ENOMEM); |
244 | 260 | ||
245 | /* | 261 | /* |
246 | * Default to software encryption; we'll later upload the | 262 | * Default to software encryption; we'll later upload the |
@@ -249,15 +265,16 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
249 | key->conf.flags = 0; | 265 | key->conf.flags = 0; |
250 | key->flags = 0; | 266 | key->flags = 0; |
251 | 267 | ||
252 | key->conf.alg = alg; | 268 | key->conf.cipher = cipher; |
253 | key->conf.keyidx = idx; | 269 | key->conf.keyidx = idx; |
254 | key->conf.keylen = key_len; | 270 | key->conf.keylen = key_len; |
255 | switch (alg) { | 271 | switch (cipher) { |
256 | case ALG_WEP: | 272 | case WLAN_CIPHER_SUITE_WEP40: |
273 | case WLAN_CIPHER_SUITE_WEP104: | ||
257 | key->conf.iv_len = WEP_IV_LEN; | 274 | key->conf.iv_len = WEP_IV_LEN; |
258 | key->conf.icv_len = WEP_ICV_LEN; | 275 | key->conf.icv_len = WEP_ICV_LEN; |
259 | break; | 276 | break; |
260 | case ALG_TKIP: | 277 | case WLAN_CIPHER_SUITE_TKIP: |
261 | key->conf.iv_len = TKIP_IV_LEN; | 278 | key->conf.iv_len = TKIP_IV_LEN; |
262 | key->conf.icv_len = TKIP_ICV_LEN; | 279 | key->conf.icv_len = TKIP_ICV_LEN; |
263 | if (seq) { | 280 | if (seq) { |
@@ -269,7 +286,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
269 | } | 286 | } |
270 | } | 287 | } |
271 | break; | 288 | break; |
272 | case ALG_CCMP: | 289 | case WLAN_CIPHER_SUITE_CCMP: |
273 | key->conf.iv_len = CCMP_HDR_LEN; | 290 | key->conf.iv_len = CCMP_HDR_LEN; |
274 | key->conf.icv_len = CCMP_MIC_LEN; | 291 | key->conf.icv_len = CCMP_MIC_LEN; |
275 | if (seq) { | 292 | if (seq) { |
@@ -278,42 +295,38 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
278 | key->u.ccmp.rx_pn[i][j] = | 295 | key->u.ccmp.rx_pn[i][j] = |
279 | seq[CCMP_PN_LEN - j - 1]; | 296 | seq[CCMP_PN_LEN - j - 1]; |
280 | } | 297 | } |
281 | break; | ||
282 | case ALG_AES_CMAC: | ||
283 | key->conf.iv_len = 0; | ||
284 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | ||
285 | if (seq) | ||
286 | for (j = 0; j < 6; j++) | ||
287 | key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; | ||
288 | break; | ||
289 | } | ||
290 | memcpy(key->conf.key, key_data, key_len); | ||
291 | INIT_LIST_HEAD(&key->list); | ||
292 | |||
293 | if (alg == ALG_CCMP) { | ||
294 | /* | 298 | /* |
295 | * Initialize AES key state here as an optimization so that | 299 | * Initialize AES key state here as an optimization so that |
296 | * it does not need to be initialized for every packet. | 300 | * it does not need to be initialized for every packet. |
297 | */ | 301 | */ |
298 | key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); | 302 | key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); |
299 | if (!key->u.ccmp.tfm) { | 303 | if (IS_ERR(key->u.ccmp.tfm)) { |
304 | err = PTR_ERR(key->u.ccmp.tfm); | ||
300 | kfree(key); | 305 | kfree(key); |
301 | return NULL; | 306 | key = ERR_PTR(err); |
302 | } | 307 | } |
303 | } | 308 | break; |
304 | 309 | case WLAN_CIPHER_SUITE_AES_CMAC: | |
305 | if (alg == ALG_AES_CMAC) { | 310 | key->conf.iv_len = 0; |
311 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | ||
312 | if (seq) | ||
313 | for (j = 0; j < 6; j++) | ||
314 | key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; | ||
306 | /* | 315 | /* |
307 | * Initialize AES key state here as an optimization so that | 316 | * Initialize AES key state here as an optimization so that |
308 | * it does not need to be initialized for every packet. | 317 | * it does not need to be initialized for every packet. |
309 | */ | 318 | */ |
310 | key->u.aes_cmac.tfm = | 319 | key->u.aes_cmac.tfm = |
311 | ieee80211_aes_cmac_key_setup(key_data); | 320 | ieee80211_aes_cmac_key_setup(key_data); |
312 | if (!key->u.aes_cmac.tfm) { | 321 | if (IS_ERR(key->u.aes_cmac.tfm)) { |
322 | err = PTR_ERR(key->u.aes_cmac.tfm); | ||
313 | kfree(key); | 323 | kfree(key); |
314 | return NULL; | 324 | key = ERR_PTR(err); |
315 | } | 325 | } |
326 | break; | ||
316 | } | 327 | } |
328 | memcpy(key->conf.key, key_data, key_len); | ||
329 | INIT_LIST_HEAD(&key->list); | ||
317 | 330 | ||
318 | return key; | 331 | return key; |
319 | } | 332 | } |
@@ -326,9 +339,9 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
326 | if (key->local) | 339 | if (key->local) |
327 | ieee80211_key_disable_hw_accel(key); | 340 | ieee80211_key_disable_hw_accel(key); |
328 | 341 | ||
329 | if (key->conf.alg == ALG_CCMP) | 342 | if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) |
330 | ieee80211_aes_key_free(key->u.ccmp.tfm); | 343 | ieee80211_aes_key_free(key->u.ccmp.tfm); |
331 | if (key->conf.alg == ALG_AES_CMAC) | 344 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) |
332 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | 345 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); |
333 | if (key->local) | 346 | if (key->local) |
334 | ieee80211_debugfs_key_remove(key); | 347 | ieee80211_debugfs_key_remove(key); |
@@ -336,12 +349,12 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
336 | kfree(key); | 349 | kfree(key); |
337 | } | 350 | } |
338 | 351 | ||
339 | void ieee80211_key_link(struct ieee80211_key *key, | 352 | int ieee80211_key_link(struct ieee80211_key *key, |
340 | struct ieee80211_sub_if_data *sdata, | 353 | struct ieee80211_sub_if_data *sdata, |
341 | struct sta_info *sta) | 354 | struct sta_info *sta) |
342 | { | 355 | { |
343 | struct ieee80211_key *old_key; | 356 | struct ieee80211_key *old_key; |
344 | int idx; | 357 | int idx, ret; |
345 | 358 | ||
346 | BUG_ON(!sdata); | 359 | BUG_ON(!sdata); |
347 | BUG_ON(!key); | 360 | BUG_ON(!key); |
@@ -396,9 +409,11 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
396 | 409 | ||
397 | ieee80211_debugfs_key_add(key); | 410 | ieee80211_debugfs_key_add(key); |
398 | 411 | ||
399 | ieee80211_key_enable_hw_accel(key); | 412 | ret = ieee80211_key_enable_hw_accel(key); |
400 | 413 | ||
401 | mutex_unlock(&sdata->local->key_mtx); | 414 | mutex_unlock(&sdata->local->key_mtx); |
415 | |||
416 | return ret; | ||
402 | } | 417 | } |
403 | 418 | ||
404 | static void __ieee80211_key_free(struct ieee80211_key *key) | 419 | static void __ieee80211_key_free(struct ieee80211_key *key) |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index b665bbb7a471..cb9a4a65cc68 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -123,18 +123,16 @@ struct ieee80211_key { | |||
123 | struct ieee80211_key_conf conf; | 123 | struct ieee80211_key_conf conf; |
124 | }; | 124 | }; |
125 | 125 | ||
126 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 126 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
127 | int idx, | ||
128 | size_t key_len, | ||
129 | const u8 *key_data, | 127 | const u8 *key_data, |
130 | size_t seq_len, const u8 *seq); | 128 | size_t seq_len, const u8 *seq); |
131 | /* | 129 | /* |
132 | * Insert a key into data structures (sdata, sta if necessary) | 130 | * Insert a key into data structures (sdata, sta if necessary) |
133 | * to make it used, free old key. | 131 | * to make it used, free old key. |
134 | */ | 132 | */ |
135 | void ieee80211_key_link(struct ieee80211_key *key, | 133 | int __must_check ieee80211_key_link(struct ieee80211_key *key, |
136 | struct ieee80211_sub_if_data *sdata, | 134 | struct ieee80211_sub_if_data *sdata, |
137 | struct sta_info *sta); | 135 | struct sta_info *sta); |
138 | void ieee80211_key_free(struct ieee80211_local *local, | 136 | void ieee80211_key_free(struct ieee80211_local *local, |
139 | struct ieee80211_key *key); | 137 | struct ieee80211_key *key); |
140 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); | 138 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ded5c3843e06..7c8542627351 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -99,11 +99,13 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
99 | int ret = 0; | 99 | int ret = 0; |
100 | int power; | 100 | int power; |
101 | enum nl80211_channel_type channel_type; | 101 | enum nl80211_channel_type channel_type; |
102 | u32 offchannel_flag; | ||
102 | 103 | ||
103 | might_sleep(); | 104 | might_sleep(); |
104 | 105 | ||
105 | scan_chan = local->scan_channel; | 106 | scan_chan = local->scan_channel; |
106 | 107 | ||
108 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
107 | if (scan_chan) { | 109 | if (scan_chan) { |
108 | chan = scan_chan; | 110 | chan = scan_chan; |
109 | channel_type = NL80211_CHAN_NO_HT; | 111 | channel_type = NL80211_CHAN_NO_HT; |
@@ -117,8 +119,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
117 | channel_type = local->_oper_channel_type; | 119 | channel_type = local->_oper_channel_type; |
118 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | 120 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; |
119 | } | 121 | } |
122 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
120 | 123 | ||
121 | if (chan != local->hw.conf.channel || | 124 | if (offchannel_flag || chan != local->hw.conf.channel || |
122 | channel_type != local->hw.conf.channel_type) { | 125 | channel_type != local->hw.conf.channel_type) { |
123 | local->hw.conf.channel = chan; | 126 | local->hw.conf.channel = chan; |
124 | local->hw.conf.channel_type = channel_type; | 127 | local->hw.conf.channel_type = channel_type; |
@@ -302,7 +305,16 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
302 | 305 | ||
303 | trace_api_restart_hw(local); | 306 | trace_api_restart_hw(local); |
304 | 307 | ||
305 | /* use this reason, __ieee80211_resume will unblock it */ | 308 | /* wait for scan work complete */ |
309 | flush_workqueue(local->workqueue); | ||
310 | |||
311 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | ||
312 | "%s called with hardware scan in progress\n", __func__); | ||
313 | |||
314 | if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) | ||
315 | ieee80211_scan_cancel(local); | ||
316 | |||
317 | /* use this reason, ieee80211_reconfig will unblock it */ | ||
306 | ieee80211_stop_queues_by_reason(hw, | 318 | ieee80211_stop_queues_by_reason(hw, |
307 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 319 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
308 | 320 | ||
@@ -336,9 +348,6 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
336 | struct ieee80211_if_managed *ifmgd; | 348 | struct ieee80211_if_managed *ifmgd; |
337 | int c = 0; | 349 | int c = 0; |
338 | 350 | ||
339 | if (!netif_running(ndev)) | ||
340 | return NOTIFY_DONE; | ||
341 | |||
342 | /* Make sure it's our interface that got changed */ | 351 | /* Make sure it's our interface that got changed */ |
343 | if (!wdev) | 352 | if (!wdev) |
344 | return NOTIFY_DONE; | 353 | return NOTIFY_DONE; |
@@ -349,6 +358,9 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
349 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); | 358 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); |
350 | bss_conf = &sdata->vif.bss_conf; | 359 | bss_conf = &sdata->vif.bss_conf; |
351 | 360 | ||
361 | if (!ieee80211_sdata_running(sdata)) | ||
362 | return NOTIFY_DONE; | ||
363 | |||
352 | /* ARP filtering is only supported in managed mode */ | 364 | /* ARP filtering is only supported in managed mode */ |
353 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 365 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
354 | return NOTIFY_DONE; | 366 | return NOTIFY_DONE; |
@@ -390,6 +402,80 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
390 | } | 402 | } |
391 | #endif | 403 | #endif |
392 | 404 | ||
405 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) | ||
406 | { | ||
407 | struct ieee80211_local *local = | ||
408 | container_of(napi, struct ieee80211_local, napi); | ||
409 | |||
410 | return local->ops->napi_poll(&local->hw, budget); | ||
411 | } | ||
412 | |||
413 | void ieee80211_napi_schedule(struct ieee80211_hw *hw) | ||
414 | { | ||
415 | struct ieee80211_local *local = hw_to_local(hw); | ||
416 | |||
417 | napi_schedule(&local->napi); | ||
418 | } | ||
419 | EXPORT_SYMBOL(ieee80211_napi_schedule); | ||
420 | |||
421 | void ieee80211_napi_complete(struct ieee80211_hw *hw) | ||
422 | { | ||
423 | struct ieee80211_local *local = hw_to_local(hw); | ||
424 | |||
425 | napi_complete(&local->napi); | ||
426 | } | ||
427 | EXPORT_SYMBOL(ieee80211_napi_complete); | ||
428 | |||
429 | /* There isn't a lot of sense in it, but you can transmit anything you like */ | ||
430 | static const struct ieee80211_txrx_stypes | ||
431 | ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | ||
432 | [NL80211_IFTYPE_ADHOC] = { | ||
433 | .tx = 0xffff, | ||
434 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4), | ||
435 | }, | ||
436 | [NL80211_IFTYPE_STATION] = { | ||
437 | .tx = 0xffff, | ||
438 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
439 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
440 | }, | ||
441 | [NL80211_IFTYPE_AP] = { | ||
442 | .tx = 0xffff, | ||
443 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
444 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
445 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
446 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
447 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
448 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
449 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
450 | }, | ||
451 | [NL80211_IFTYPE_AP_VLAN] = { | ||
452 | /* copy AP */ | ||
453 | .tx = 0xffff, | ||
454 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
455 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
456 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
457 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
458 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
459 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
460 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
461 | }, | ||
462 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
463 | .tx = 0xffff, | ||
464 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
465 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
466 | }, | ||
467 | [NL80211_IFTYPE_P2P_GO] = { | ||
468 | .tx = 0xffff, | ||
469 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
470 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
471 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
472 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
473 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
474 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
475 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
476 | }, | ||
477 | }; | ||
478 | |||
393 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 479 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
394 | const struct ieee80211_ops *ops) | 480 | const struct ieee80211_ops *ops) |
395 | { | 481 | { |
@@ -419,6 +505,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
419 | if (!wiphy) | 505 | if (!wiphy) |
420 | return NULL; | 506 | return NULL; |
421 | 507 | ||
508 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; | ||
509 | |||
422 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 510 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
423 | WIPHY_FLAG_4ADDR_AP | | 511 | WIPHY_FLAG_4ADDR_AP | |
424 | WIPHY_FLAG_4ADDR_STATION; | 512 | WIPHY_FLAG_4ADDR_STATION; |
@@ -455,7 +543,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
455 | __hw_addr_init(&local->mc_list); | 543 | __hw_addr_init(&local->mc_list); |
456 | 544 | ||
457 | mutex_init(&local->iflist_mtx); | 545 | mutex_init(&local->iflist_mtx); |
458 | mutex_init(&local->scan_mtx); | 546 | mutex_init(&local->mtx); |
459 | 547 | ||
460 | mutex_init(&local->key_mtx); | 548 | mutex_init(&local->key_mtx); |
461 | spin_lock_init(&local->filter_lock); | 549 | spin_lock_init(&local->filter_lock); |
@@ -494,6 +582,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
494 | skb_queue_head_init(&local->skb_queue); | 582 | skb_queue_head_init(&local->skb_queue); |
495 | skb_queue_head_init(&local->skb_queue_unreliable); | 583 | skb_queue_head_init(&local->skb_queue_unreliable); |
496 | 584 | ||
585 | /* init dummy netdev for use w/ NAPI */ | ||
586 | init_dummy_netdev(&local->napi_dev); | ||
587 | |||
497 | return local_to_hw(local); | 588 | return local_to_hw(local); |
498 | } | 589 | } |
499 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 590 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
@@ -506,6 +597,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
506 | int channels, max_bitrates; | 597 | int channels, max_bitrates; |
507 | bool supp_ht; | 598 | bool supp_ht; |
508 | static const u32 cipher_suites[] = { | 599 | static const u32 cipher_suites[] = { |
600 | /* keep WEP first, it may be removed below */ | ||
509 | WLAN_CIPHER_SUITE_WEP40, | 601 | WLAN_CIPHER_SUITE_WEP40, |
510 | WLAN_CIPHER_SUITE_WEP104, | 602 | WLAN_CIPHER_SUITE_WEP104, |
511 | WLAN_CIPHER_SUITE_TKIP, | 603 | WLAN_CIPHER_SUITE_TKIP, |
@@ -554,6 +646,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
554 | /* mac80211 always supports monitor */ | 646 | /* mac80211 always supports monitor */ |
555 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | 647 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); |
556 | 648 | ||
649 | #ifndef CONFIG_MAC80211_MESH | ||
650 | /* mesh depends on Kconfig, but drivers should set it if they want */ | ||
651 | local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT); | ||
652 | #endif | ||
653 | |||
654 | /* mac80211 supports control port protocol changing */ | ||
655 | local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; | ||
656 | |||
557 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 657 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
558 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 658 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
559 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 659 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
@@ -589,10 +689,41 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
589 | if (local->hw.wiphy->max_scan_ie_len) | 689 | if (local->hw.wiphy->max_scan_ie_len) |
590 | local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; | 690 | local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; |
591 | 691 | ||
592 | local->hw.wiphy->cipher_suites = cipher_suites; | 692 | /* Set up cipher suites unless driver already did */ |
593 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 693 | if (!local->hw.wiphy->cipher_suites) { |
594 | if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) | 694 | local->hw.wiphy->cipher_suites = cipher_suites; |
595 | local->hw.wiphy->n_cipher_suites--; | 695 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
696 | if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) | ||
697 | local->hw.wiphy->n_cipher_suites--; | ||
698 | } | ||
699 | if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) { | ||
700 | if (local->hw.wiphy->cipher_suites == cipher_suites) { | ||
701 | local->hw.wiphy->cipher_suites += 2; | ||
702 | local->hw.wiphy->n_cipher_suites -= 2; | ||
703 | } else { | ||
704 | u32 *suites; | ||
705 | int r, w = 0; | ||
706 | |||
707 | /* Filter out WEP */ | ||
708 | |||
709 | suites = kmemdup( | ||
710 | local->hw.wiphy->cipher_suites, | ||
711 | sizeof(u32) * local->hw.wiphy->n_cipher_suites, | ||
712 | GFP_KERNEL); | ||
713 | if (!suites) | ||
714 | return -ENOMEM; | ||
715 | for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { | ||
716 | u32 suite = local->hw.wiphy->cipher_suites[r]; | ||
717 | if (suite == WLAN_CIPHER_SUITE_WEP40 || | ||
718 | suite == WLAN_CIPHER_SUITE_WEP104) | ||
719 | continue; | ||
720 | suites[w++] = suite; | ||
721 | } | ||
722 | local->hw.wiphy->cipher_suites = suites; | ||
723 | local->hw.wiphy->n_cipher_suites = w; | ||
724 | local->wiphy_ciphers_allocated = true; | ||
725 | } | ||
726 | } | ||
596 | 727 | ||
597 | result = wiphy_register(local->hw.wiphy); | 728 | result = wiphy_register(local->hw.wiphy); |
598 | if (result < 0) | 729 | if (result < 0) |
@@ -641,16 +772,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
641 | 772 | ||
642 | result = ieee80211_wep_init(local); | 773 | result = ieee80211_wep_init(local); |
643 | if (result < 0) | 774 | if (result < 0) |
644 | printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", | 775 | wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", |
645 | wiphy_name(local->hw.wiphy), result); | 776 | result); |
646 | 777 | ||
647 | rtnl_lock(); | 778 | rtnl_lock(); |
648 | 779 | ||
649 | result = ieee80211_init_rate_ctrl_alg(local, | 780 | result = ieee80211_init_rate_ctrl_alg(local, |
650 | hw->rate_control_algorithm); | 781 | hw->rate_control_algorithm); |
651 | if (result < 0) { | 782 | if (result < 0) { |
652 | printk(KERN_DEBUG "%s: Failed to initialize rate control " | 783 | wiphy_debug(local->hw.wiphy, |
653 | "algorithm\n", wiphy_name(local->hw.wiphy)); | 784 | "Failed to initialize rate control algorithm\n"); |
654 | goto fail_rate; | 785 | goto fail_rate; |
655 | } | 786 | } |
656 | 787 | ||
@@ -659,8 +790,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
659 | result = ieee80211_if_add(local, "wlan%d", NULL, | 790 | result = ieee80211_if_add(local, "wlan%d", NULL, |
660 | NL80211_IFTYPE_STATION, NULL); | 791 | NL80211_IFTYPE_STATION, NULL); |
661 | if (result) | 792 | if (result) |
662 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", | 793 | wiphy_warn(local->hw.wiphy, |
663 | wiphy_name(local->hw.wiphy)); | 794 | "Failed to add default virtual iface\n"); |
664 | } | 795 | } |
665 | 796 | ||
666 | rtnl_unlock(); | 797 | rtnl_unlock(); |
@@ -683,6 +814,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
683 | goto fail_ifa; | 814 | goto fail_ifa; |
684 | #endif | 815 | #endif |
685 | 816 | ||
817 | netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, | ||
818 | local->hw.napi_weight); | ||
819 | |||
686 | return 0; | 820 | return 0; |
687 | 821 | ||
688 | #ifdef CONFIG_INET | 822 | #ifdef CONFIG_INET |
@@ -703,6 +837,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
703 | fail_workqueue: | 837 | fail_workqueue: |
704 | wiphy_unregister(local->hw.wiphy); | 838 | wiphy_unregister(local->hw.wiphy); |
705 | fail_wiphy_register: | 839 | fail_wiphy_register: |
840 | if (local->wiphy_ciphers_allocated) | ||
841 | kfree(local->hw.wiphy->cipher_suites); | ||
706 | kfree(local->int_scan_req); | 842 | kfree(local->int_scan_req); |
707 | return result; | 843 | return result; |
708 | } | 844 | } |
@@ -738,6 +874,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
738 | */ | 874 | */ |
739 | del_timer_sync(&local->work_timer); | 875 | del_timer_sync(&local->work_timer); |
740 | 876 | ||
877 | cancel_work_sync(&local->restart_work); | ||
741 | cancel_work_sync(&local->reconfig_filter); | 878 | cancel_work_sync(&local->reconfig_filter); |
742 | 879 | ||
743 | ieee80211_clear_tx_pending(local); | 880 | ieee80211_clear_tx_pending(local); |
@@ -746,8 +883,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
746 | 883 | ||
747 | if (skb_queue_len(&local->skb_queue) || | 884 | if (skb_queue_len(&local->skb_queue) || |
748 | skb_queue_len(&local->skb_queue_unreliable)) | 885 | skb_queue_len(&local->skb_queue_unreliable)) |
749 | printk(KERN_WARNING "%s: skb_queue not empty\n", | 886 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); |
750 | wiphy_name(local->hw.wiphy)); | ||
751 | skb_queue_purge(&local->skb_queue); | 887 | skb_queue_purge(&local->skb_queue); |
752 | skb_queue_purge(&local->skb_queue_unreliable); | 888 | skb_queue_purge(&local->skb_queue_unreliable); |
753 | 889 | ||
@@ -764,7 +900,10 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
764 | struct ieee80211_local *local = hw_to_local(hw); | 900 | struct ieee80211_local *local = hw_to_local(hw); |
765 | 901 | ||
766 | mutex_destroy(&local->iflist_mtx); | 902 | mutex_destroy(&local->iflist_mtx); |
767 | mutex_destroy(&local->scan_mtx); | 903 | mutex_destroy(&local->mtx); |
904 | |||
905 | if (local->wiphy_ciphers_allocated) | ||
906 | kfree(local->hw.wiphy->cipher_suites); | ||
768 | 907 | ||
769 | wiphy_free(local->hw.wiphy); | 908 | wiphy_free(local->hw.wiphy); |
770 | } | 909 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b6c163ac22da..8b733cf6f3ea 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -54,6 +54,12 @@ | |||
54 | */ | 54 | */ |
55 | #define IEEE80211_SIGNAL_AVE_WEIGHT 3 | 55 | #define IEEE80211_SIGNAL_AVE_WEIGHT 3 |
56 | 56 | ||
57 | /* | ||
58 | * How many Beacon frames need to have been used in average signal strength | ||
59 | * before starting to indicate signal change events. | ||
60 | */ | ||
61 | #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 | ||
62 | |||
57 | #define TMR_RUNNING_TIMER 0 | 63 | #define TMR_RUNNING_TIMER 0 |
58 | #define TMR_RUNNING_CHANSW 1 | 64 | #define TMR_RUNNING_CHANSW 1 |
59 | 65 | ||
@@ -86,7 +92,7 @@ enum rx_mgmt_action { | |||
86 | /* utils */ | 92 | /* utils */ |
87 | static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) | 93 | static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) |
88 | { | 94 | { |
89 | WARN_ON(!mutex_is_locked(&ifmgd->mtx)); | 95 | lockdep_assert_held(&ifmgd->mtx); |
90 | } | 96 | } |
91 | 97 | ||
92 | /* | 98 | /* |
@@ -109,7 +115,7 @@ static void run_again(struct ieee80211_if_managed *ifmgd, | |||
109 | mod_timer(&ifmgd->timer, timeout); | 115 | mod_timer(&ifmgd->timer, timeout); |
110 | } | 116 | } |
111 | 117 | ||
112 | static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) | 118 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) |
113 | { | 119 | { |
114 | if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) | 120 | if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) |
115 | return; | 121 | return; |
@@ -118,6 +124,19 @@ static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) | |||
118 | round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); | 124 | round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); |
119 | } | 125 | } |
120 | 126 | ||
127 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) | ||
128 | { | ||
129 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
130 | |||
131 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
132 | return; | ||
133 | |||
134 | mod_timer(&sdata->u.mgd.conn_mon_timer, | ||
135 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | ||
136 | |||
137 | ifmgd->probe_send_count = 0; | ||
138 | } | ||
139 | |||
121 | static int ecw2cw(int ecw) | 140 | static int ecw2cw(int ecw) |
122 | { | 141 | { |
123 | return (1 << ecw) - 1; | 142 | return (1 << ecw) - 1; |
@@ -778,16 +797,17 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
778 | params.uapsd = uapsd; | 797 | params.uapsd = uapsd; |
779 | 798 | ||
780 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 799 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
781 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " | 800 | wiphy_debug(local->hw.wiphy, |
782 | "cWmin=%d cWmax=%d txop=%d uapsd=%d\n", | 801 | "WMM queue=%d aci=%d acm=%d aifs=%d " |
783 | wiphy_name(local->hw.wiphy), queue, aci, acm, | 802 | "cWmin=%d cWmax=%d txop=%d uapsd=%d\n", |
784 | params.aifs, params.cw_min, params.cw_max, params.txop, | 803 | queue, aci, acm, |
785 | params.uapsd); | 804 | params.aifs, params.cw_min, params.cw_max, |
805 | params.txop, params.uapsd); | ||
786 | #endif | 806 | #endif |
787 | if (drv_conf_tx(local, queue, ¶ms)) | 807 | if (drv_conf_tx(local, queue, ¶ms)) |
788 | printk(KERN_DEBUG "%s: failed to set TX queue " | 808 | wiphy_debug(local->hw.wiphy, |
789 | "parameters for queue %d\n", | 809 | "failed to set TX queue parameters for queue %d\n", |
790 | wiphy_name(local->hw.wiphy), queue); | 810 | queue); |
791 | } | 811 | } |
792 | 812 | ||
793 | /* enable WMM or activate new settings */ | 813 | /* enable WMM or activate new settings */ |
@@ -990,6 +1010,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
990 | 1010 | ||
991 | if (remove_sta) | 1011 | if (remove_sta) |
992 | sta_info_destroy_addr(sdata, bssid); | 1012 | sta_info_destroy_addr(sdata, bssid); |
1013 | |||
1014 | del_timer_sync(&sdata->u.mgd.conn_mon_timer); | ||
1015 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); | ||
1016 | del_timer_sync(&sdata->u.mgd.timer); | ||
1017 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | ||
993 | } | 1018 | } |
994 | 1019 | ||
995 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1020 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -1006,21 +1031,26 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
1006 | if (is_multicast_ether_addr(hdr->addr1)) | 1031 | if (is_multicast_ether_addr(hdr->addr1)) |
1007 | return; | 1032 | return; |
1008 | 1033 | ||
1009 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | 1034 | ieee80211_sta_reset_conn_monitor(sdata); |
1010 | return; | ||
1011 | |||
1012 | mod_timer(&sdata->u.mgd.conn_mon_timer, | ||
1013 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | ||
1014 | } | 1035 | } |
1015 | 1036 | ||
1016 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | 1037 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) |
1017 | { | 1038 | { |
1018 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1039 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1019 | const u8 *ssid; | 1040 | const u8 *ssid; |
1041 | u8 *dst = ifmgd->associated->bssid; | ||
1042 | u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3); | ||
1043 | |||
1044 | /* | ||
1045 | * Try sending broadcast probe requests for the last three | ||
1046 | * probe requests after the first ones failed since some | ||
1047 | * buggy APs only support broadcast probe requests. | ||
1048 | */ | ||
1049 | if (ifmgd->probe_send_count >= unicast_limit) | ||
1050 | dst = NULL; | ||
1020 | 1051 | ||
1021 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1052 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1022 | ieee80211_send_probe_req(sdata, ifmgd->associated->bssid, | 1053 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); |
1023 | ssid + 2, ssid[1], NULL, 0); | ||
1024 | 1054 | ||
1025 | ifmgd->probe_send_count++; | 1055 | ifmgd->probe_send_count++; |
1026 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | 1056 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; |
@@ -1103,8 +1133,11 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1103 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | 1133 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); |
1104 | 1134 | ||
1105 | ieee80211_set_disassoc(sdata, true); | 1135 | ieee80211_set_disassoc(sdata, true); |
1106 | ieee80211_recalc_idle(local); | ||
1107 | mutex_unlock(&ifmgd->mtx); | 1136 | mutex_unlock(&ifmgd->mtx); |
1137 | |||
1138 | mutex_lock(&local->mtx); | ||
1139 | ieee80211_recalc_idle(local); | ||
1140 | mutex_unlock(&local->mtx); | ||
1108 | /* | 1141 | /* |
1109 | * must be outside lock due to cfg80211, | 1142 | * must be outside lock due to cfg80211, |
1110 | * but that's not a problem. | 1143 | * but that's not a problem. |
@@ -1173,7 +1206,9 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1173 | sdata->name, bssid, reason_code); | 1206 | sdata->name, bssid, reason_code); |
1174 | 1207 | ||
1175 | ieee80211_set_disassoc(sdata, true); | 1208 | ieee80211_set_disassoc(sdata, true); |
1209 | mutex_lock(&sdata->local->mtx); | ||
1176 | ieee80211_recalc_idle(sdata->local); | 1210 | ieee80211_recalc_idle(sdata->local); |
1211 | mutex_unlock(&sdata->local->mtx); | ||
1177 | 1212 | ||
1178 | return RX_MGMT_CFG80211_DEAUTH; | 1213 | return RX_MGMT_CFG80211_DEAUTH; |
1179 | } | 1214 | } |
@@ -1203,7 +1238,9 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1203 | sdata->name, mgmt->sa, reason_code); | 1238 | sdata->name, mgmt->sa, reason_code); |
1204 | 1239 | ||
1205 | ieee80211_set_disassoc(sdata, true); | 1240 | ieee80211_set_disassoc(sdata, true); |
1241 | mutex_lock(&sdata->local->mtx); | ||
1206 | ieee80211_recalc_idle(sdata->local); | 1242 | ieee80211_recalc_idle(sdata->local); |
1243 | mutex_unlock(&sdata->local->mtx); | ||
1207 | return RX_MGMT_CFG80211_DISASSOC; | 1244 | return RX_MGMT_CFG80211_DISASSOC; |
1208 | } | 1245 | } |
1209 | 1246 | ||
@@ -1362,7 +1399,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1362 | * Also start the timer that will detect beacon loss. | 1399 | * Also start the timer that will detect beacon loss. |
1363 | */ | 1400 | */ |
1364 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | 1401 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
1365 | mod_beacon_timer(sdata); | 1402 | ieee80211_sta_reset_beacon_monitor(sdata); |
1366 | 1403 | ||
1367 | return true; | 1404 | return true; |
1368 | } | 1405 | } |
@@ -1465,7 +1502,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1465 | * we have or will be receiving any beacons or data, so let's | 1502 | * we have or will be receiving any beacons or data, so let's |
1466 | * schedule the timers again, just in case. | 1503 | * schedule the timers again, just in case. |
1467 | */ | 1504 | */ |
1468 | mod_beacon_timer(sdata); | 1505 | ieee80211_sta_reset_beacon_monitor(sdata); |
1469 | 1506 | ||
1470 | mod_timer(&ifmgd->conn_mon_timer, | 1507 | mod_timer(&ifmgd->conn_mon_timer, |
1471 | round_jiffies_up(jiffies + | 1508 | round_jiffies_up(jiffies + |
@@ -1540,15 +1577,18 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1540 | ifmgd->last_beacon_signal = rx_status->signal; | 1577 | ifmgd->last_beacon_signal = rx_status->signal; |
1541 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { | 1578 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { |
1542 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; | 1579 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; |
1543 | ifmgd->ave_beacon_signal = rx_status->signal; | 1580 | ifmgd->ave_beacon_signal = rx_status->signal * 16; |
1544 | ifmgd->last_cqm_event_signal = 0; | 1581 | ifmgd->last_cqm_event_signal = 0; |
1582 | ifmgd->count_beacon_signal = 1; | ||
1545 | } else { | 1583 | } else { |
1546 | ifmgd->ave_beacon_signal = | 1584 | ifmgd->ave_beacon_signal = |
1547 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + | 1585 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + |
1548 | (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * | 1586 | (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * |
1549 | ifmgd->ave_beacon_signal) / 16; | 1587 | ifmgd->ave_beacon_signal) / 16; |
1588 | ifmgd->count_beacon_signal++; | ||
1550 | } | 1589 | } |
1551 | if (bss_conf->cqm_rssi_thold && | 1590 | if (bss_conf->cqm_rssi_thold && |
1591 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && | ||
1552 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | 1592 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { |
1553 | int sig = ifmgd->ave_beacon_signal / 16; | 1593 | int sig = ifmgd->ave_beacon_signal / 16; |
1554 | int last_event = ifmgd->last_cqm_event_signal; | 1594 | int last_event = ifmgd->last_cqm_event_signal; |
@@ -1588,7 +1628,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1588 | * Push the beacon loss detection into the future since | 1628 | * Push the beacon loss detection into the future since |
1589 | * we are processing a beacon from the AP just now. | 1629 | * we are processing a beacon from the AP just now. |
1590 | */ | 1630 | */ |
1591 | mod_beacon_timer(sdata); | 1631 | ieee80211_sta_reset_beacon_monitor(sdata); |
1592 | 1632 | ||
1593 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); | 1633 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); |
1594 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, | 1634 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, |
@@ -1751,7 +1791,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1751 | struct ieee80211_local *local = sdata->local; | 1791 | struct ieee80211_local *local = sdata->local; |
1752 | struct ieee80211_work *wk; | 1792 | struct ieee80211_work *wk; |
1753 | 1793 | ||
1754 | mutex_lock(&local->work_mtx); | 1794 | mutex_lock(&local->mtx); |
1755 | list_for_each_entry(wk, &local->work_list, list) { | 1795 | list_for_each_entry(wk, &local->work_list, list) { |
1756 | if (wk->sdata != sdata) | 1796 | if (wk->sdata != sdata) |
1757 | continue; | 1797 | continue; |
@@ -1783,7 +1823,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1783 | free_work(wk); | 1823 | free_work(wk); |
1784 | break; | 1824 | break; |
1785 | } | 1825 | } |
1786 | mutex_unlock(&local->work_mtx); | 1826 | mutex_unlock(&local->mtx); |
1787 | 1827 | ||
1788 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | 1828 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); |
1789 | } | 1829 | } |
@@ -1840,8 +1880,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1840 | " after %dms, disconnecting.\n", | 1880 | " after %dms, disconnecting.\n", |
1841 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1881 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1842 | ieee80211_set_disassoc(sdata, true); | 1882 | ieee80211_set_disassoc(sdata, true); |
1843 | ieee80211_recalc_idle(local); | ||
1844 | mutex_unlock(&ifmgd->mtx); | 1883 | mutex_unlock(&ifmgd->mtx); |
1884 | mutex_lock(&local->mtx); | ||
1885 | ieee80211_recalc_idle(local); | ||
1886 | mutex_unlock(&local->mtx); | ||
1845 | /* | 1887 | /* |
1846 | * must be outside lock due to cfg80211, | 1888 | * must be outside lock due to cfg80211, |
1847 | * but that's not a problem. | 1889 | * but that's not a problem. |
@@ -1917,6 +1959,8 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
1917 | * time -- the code here is properly synchronised. | 1959 | * time -- the code here is properly synchronised. |
1918 | */ | 1960 | */ |
1919 | 1961 | ||
1962 | cancel_work_sync(&ifmgd->request_smps_work); | ||
1963 | |||
1920 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | 1964 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
1921 | if (del_timer_sync(&ifmgd->timer)) | 1965 | if (del_timer_sync(&ifmgd->timer)) |
1922 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 1966 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
@@ -1952,6 +1996,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
1952 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 1996 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
1953 | INIT_WORK(&ifmgd->beacon_connection_loss_work, | 1997 | INIT_WORK(&ifmgd->beacon_connection_loss_work, |
1954 | ieee80211_beacon_connection_loss_work); | 1998 | ieee80211_beacon_connection_loss_work); |
1999 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); | ||
1955 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 2000 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
1956 | (unsigned long) sdata); | 2001 | (unsigned long) sdata); |
1957 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 2002 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
@@ -2249,6 +2294,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2249 | else | 2294 | else |
2250 | ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; | 2295 | ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; |
2251 | 2296 | ||
2297 | sdata->control_port_protocol = req->crypto.control_port_ethertype; | ||
2298 | sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; | ||
2299 | |||
2252 | ieee80211_add_work(wk); | 2300 | ieee80211_add_work(wk); |
2253 | return 0; | 2301 | return 0; |
2254 | } | 2302 | } |
@@ -2275,7 +2323,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2275 | 2323 | ||
2276 | mutex_unlock(&ifmgd->mtx); | 2324 | mutex_unlock(&ifmgd->mtx); |
2277 | 2325 | ||
2278 | mutex_lock(&local->work_mtx); | 2326 | mutex_lock(&local->mtx); |
2279 | list_for_each_entry(wk, &local->work_list, list) { | 2327 | list_for_each_entry(wk, &local->work_list, list) { |
2280 | if (wk->sdata != sdata) | 2328 | if (wk->sdata != sdata) |
2281 | continue; | 2329 | continue; |
@@ -2294,7 +2342,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2294 | free_work(wk); | 2342 | free_work(wk); |
2295 | break; | 2343 | break; |
2296 | } | 2344 | } |
2297 | mutex_unlock(&local->work_mtx); | 2345 | mutex_unlock(&local->mtx); |
2298 | 2346 | ||
2299 | /* | 2347 | /* |
2300 | * If somebody requests authentication and we haven't | 2348 | * If somebody requests authentication and we haven't |
@@ -2319,7 +2367,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2319 | if (assoc_bss) | 2367 | if (assoc_bss) |
2320 | sta_info_destroy_addr(sdata, bssid); | 2368 | sta_info_destroy_addr(sdata, bssid); |
2321 | 2369 | ||
2370 | mutex_lock(&sdata->local->mtx); | ||
2322 | ieee80211_recalc_idle(sdata->local); | 2371 | ieee80211_recalc_idle(sdata->local); |
2372 | mutex_unlock(&sdata->local->mtx); | ||
2323 | 2373 | ||
2324 | return 0; | 2374 | return 0; |
2325 | } | 2375 | } |
@@ -2357,7 +2407,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2357 | cookie, !req->local_state_change); | 2407 | cookie, !req->local_state_change); |
2358 | sta_info_destroy_addr(sdata, bssid); | 2408 | sta_info_destroy_addr(sdata, bssid); |
2359 | 2409 | ||
2410 | mutex_lock(&sdata->local->mtx); | ||
2360 | ieee80211_recalc_idle(sdata->local); | 2411 | ieee80211_recalc_idle(sdata->local); |
2412 | mutex_unlock(&sdata->local->mtx); | ||
2361 | 2413 | ||
2362 | return 0; | 2414 | return 0; |
2363 | } | 2415 | } |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index c36b1911987a..4b564091e51d 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -22,12 +22,16 @@ | |||
22 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | 22 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) |
23 | { | 23 | { |
24 | struct ieee80211_local *local = sdata->local; | 24 | struct ieee80211_local *local = sdata->local; |
25 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
25 | 26 | ||
26 | local->offchannel_ps_enabled = false; | 27 | local->offchannel_ps_enabled = false; |
27 | 28 | ||
28 | /* FIXME: what to do when local->pspolling is true? */ | 29 | /* FIXME: what to do when local->pspolling is true? */ |
29 | 30 | ||
30 | del_timer_sync(&local->dynamic_ps_timer); | 31 | del_timer_sync(&local->dynamic_ps_timer); |
32 | del_timer_sync(&ifmgd->bcn_mon_timer); | ||
33 | del_timer_sync(&ifmgd->conn_mon_timer); | ||
34 | |||
31 | cancel_work_sync(&local->dynamic_ps_enable_work); | 35 | cancel_work_sync(&local->dynamic_ps_enable_work); |
32 | 36 | ||
33 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 37 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
@@ -85,6 +89,9 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
85 | mod_timer(&local->dynamic_ps_timer, jiffies + | 89 | mod_timer(&local->dynamic_ps_timer, jiffies + |
86 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 90 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
87 | } | 91 | } |
92 | |||
93 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
94 | ieee80211_sta_reset_conn_monitor(sdata); | ||
88 | } | 95 | } |
89 | 96 | ||
90 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) | 97 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) |
@@ -112,8 +119,10 @@ void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) | |||
112 | * used from user space controlled off-channel operations. | 119 | * used from user space controlled off-channel operations. |
113 | */ | 120 | */ |
114 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 121 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
115 | sdata->vif.type != NL80211_IFTYPE_MONITOR) | 122 | sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
123 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
116 | netif_tx_stop_all_queues(sdata->dev); | 124 | netif_tx_stop_all_queues(sdata->dev); |
125 | } | ||
117 | } | 126 | } |
118 | mutex_unlock(&local->iflist_mtx); | 127 | mutex_unlock(&local->iflist_mtx); |
119 | } | 128 | } |
@@ -131,6 +140,7 @@ void ieee80211_offchannel_stop_station(struct ieee80211_local *local) | |||
131 | continue; | 140 | continue; |
132 | 141 | ||
133 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 142 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
143 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
134 | netif_tx_stop_all_queues(sdata->dev); | 144 | netif_tx_stop_all_queues(sdata->dev); |
135 | if (sdata->u.mgd.associated) | 145 | if (sdata->u.mgd.associated) |
136 | ieee80211_offchannel_ps_enable(sdata); | 146 | ieee80211_offchannel_ps_enable(sdata); |
@@ -155,8 +165,20 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
155 | ieee80211_offchannel_ps_disable(sdata); | 165 | ieee80211_offchannel_ps_disable(sdata); |
156 | } | 166 | } |
157 | 167 | ||
158 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 168 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
169 | clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
170 | /* | ||
171 | * This may wake up queues even though the driver | ||
172 | * currently has them stopped. This is not very | ||
173 | * likely, since the driver won't have gotten any | ||
174 | * (or hardly any) new packets while we weren't | ||
175 | * on the right channel, and even if it happens | ||
176 | * it will at most lead to queueing up one more | ||
177 | * packet per queue in mac80211 rather than on | ||
178 | * the interface qdisc. | ||
179 | */ | ||
159 | netif_tx_wake_all_queues(sdata->dev); | 180 | netif_tx_wake_all_queues(sdata->dev); |
181 | } | ||
160 | 182 | ||
161 | /* re-enable beaconing */ | 183 | /* re-enable beaconing */ |
162 | if (enable_beaconing && | 184 | if (enable_beaconing && |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index d287fde0431d..ce671dfd238c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -12,7 +12,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
13 | struct sta_info *sta; | 13 | struct sta_info *sta; |
14 | 14 | ||
15 | ieee80211_scan_cancel(local); | 15 | if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) |
16 | ieee80211_scan_cancel(local); | ||
16 | 17 | ||
17 | ieee80211_stop_queues_by_reason(hw, | 18 | ieee80211_stop_queues_by_reason(hw, |
18 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 19 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 6d0bd198af19..f77a45625c0b 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -366,8 +366,8 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | |||
366 | 366 | ||
367 | ref = rate_control_alloc(name, local); | 367 | ref = rate_control_alloc(name, local); |
368 | if (!ref) { | 368 | if (!ref) { |
369 | printk(KERN_WARNING "%s: Failed to select rate control " | 369 | wiphy_warn(local->hw.wiphy, |
370 | "algorithm\n", wiphy_name(local->hw.wiphy)); | 370 | "Failed to select rate control algorithm\n"); |
371 | return -ENOENT; | 371 | return -ENOENT; |
372 | } | 372 | } |
373 | 373 | ||
@@ -378,9 +378,8 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | |||
378 | sta_info_flush(local, NULL); | 378 | sta_info_flush(local, NULL); |
379 | } | 379 | } |
380 | 380 | ||
381 | printk(KERN_DEBUG "%s: Selected rate control " | 381 | wiphy_debug(local->hw.wiphy, "Selected rate control algorithm '%s'\n", |
382 | "algorithm '%s'\n", wiphy_name(local->hw.wiphy), | 382 | ref->ops->name); |
383 | ref->ops->name); | ||
384 | 383 | ||
385 | return 0; | 384 | return 0; |
386 | } | 385 | } |
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index 47438b4a9af5..135f36fd4d5d 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c | |||
@@ -162,7 +162,7 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, | |||
162 | file_info->next_entry = (file_info->next_entry + 1) % | 162 | file_info->next_entry = (file_info->next_entry + 1) % |
163 | RC_PID_EVENT_RING_SIZE; | 163 | RC_PID_EVENT_RING_SIZE; |
164 | 164 | ||
165 | /* Print information about the event. Note that userpace needs to | 165 | /* Print information about the event. Note that userspace needs to |
166 | * provide large enough buffers. */ | 166 | * provide large enough buffers. */ |
167 | length = length < RC_PID_PRINT_BUF_SIZE ? | 167 | length = length < RC_PID_PRINT_BUF_SIZE ? |
168 | length : RC_PID_PRINT_BUF_SIZE; | 168 | length : RC_PID_PRINT_BUF_SIZE; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 28624282c5f3..308e502a80eb 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -538,20 +538,12 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
538 | int index, | 538 | int index, |
539 | struct sk_buff_head *frames) | 539 | struct sk_buff_head *frames) |
540 | { | 540 | { |
541 | struct ieee80211_supported_band *sband; | ||
542 | struct ieee80211_rate *rate = NULL; | ||
543 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 541 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
544 | struct ieee80211_rx_status *status; | ||
545 | 542 | ||
546 | if (!skb) | 543 | if (!skb) |
547 | goto no_frame; | 544 | goto no_frame; |
548 | 545 | ||
549 | status = IEEE80211_SKB_RXCB(skb); | 546 | /* release the frame from the reorder ring buffer */ |
550 | |||
551 | /* release the reordered frames to stack */ | ||
552 | sband = hw->wiphy->bands[status->band]; | ||
553 | if (!(status->flag & RX_FLAG_HT)) | ||
554 | rate = &sband->bitrates[status->rate_idx]; | ||
555 | tid_agg_rx->stored_mpdu_num--; | 547 | tid_agg_rx->stored_mpdu_num--; |
556 | tid_agg_rx->reorder_buf[index] = NULL; | 548 | tid_agg_rx->reorder_buf[index] = NULL; |
557 | __skb_queue_tail(frames, skb); | 549 | __skb_queue_tail(frames, skb); |
@@ -580,9 +572,78 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | |||
580 | * frames that have not yet been received are assumed to be lost and the skb | 572 | * frames that have not yet been received are assumed to be lost and the skb |
581 | * can be released for processing. This may also release other skb's from the | 573 | * can be released for processing. This may also release other skb's from the |
582 | * reorder buffer if there are no additional gaps between the frames. | 574 | * reorder buffer if there are no additional gaps between the frames. |
575 | * | ||
576 | * Callers must hold tid_agg_rx->reorder_lock. | ||
583 | */ | 577 | */ |
584 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | 578 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) |
585 | 579 | ||
580 | static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | ||
581 | struct tid_ampdu_rx *tid_agg_rx, | ||
582 | struct sk_buff_head *frames) | ||
583 | { | ||
584 | int index, j; | ||
585 | |||
586 | /* release the buffer until next missing frame */ | ||
587 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
588 | tid_agg_rx->buf_size; | ||
589 | if (!tid_agg_rx->reorder_buf[index] && | ||
590 | tid_agg_rx->stored_mpdu_num > 1) { | ||
591 | /* | ||
592 | * No buffers ready to be released, but check whether any | ||
593 | * frames in the reorder buffer have timed out. | ||
594 | */ | ||
595 | int skipped = 1; | ||
596 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | ||
597 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
598 | if (!tid_agg_rx->reorder_buf[j]) { | ||
599 | skipped++; | ||
600 | continue; | ||
601 | } | ||
602 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
603 | HT_RX_REORDER_BUF_TIMEOUT)) | ||
604 | goto set_release_timer; | ||
605 | |||
606 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
607 | if (net_ratelimit()) | ||
608 | wiphy_debug(hw->wiphy, | ||
609 | "release an RX reorder frame due to timeout on earlier frames\n"); | ||
610 | #endif | ||
611 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | ||
612 | j, frames); | ||
613 | |||
614 | /* | ||
615 | * Increment the head seq# also for the skipped slots. | ||
616 | */ | ||
617 | tid_agg_rx->head_seq_num = | ||
618 | (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; | ||
619 | skipped = 0; | ||
620 | } | ||
621 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
622 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | ||
623 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
624 | tid_agg_rx->buf_size; | ||
625 | } | ||
626 | |||
627 | if (tid_agg_rx->stored_mpdu_num) { | ||
628 | j = index = seq_sub(tid_agg_rx->head_seq_num, | ||
629 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | ||
630 | |||
631 | for (; j != (index - 1) % tid_agg_rx->buf_size; | ||
632 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
633 | if (tid_agg_rx->reorder_buf[j]) | ||
634 | break; | ||
635 | } | ||
636 | |||
637 | set_release_timer: | ||
638 | |||
639 | mod_timer(&tid_agg_rx->reorder_timer, | ||
640 | tid_agg_rx->reorder_time[j] + | ||
641 | HT_RX_REORDER_BUF_TIMEOUT); | ||
642 | } else { | ||
643 | del_timer(&tid_agg_rx->reorder_timer); | ||
644 | } | ||
645 | } | ||
646 | |||
586 | /* | 647 | /* |
587 | * As this function belongs to the RX path it must be under | 648 | * As this function belongs to the RX path it must be under |
588 | * rcu_read_lock protection. It returns false if the frame | 649 | * rcu_read_lock protection. It returns false if the frame |
@@ -598,14 +659,16 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
598 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; | 659 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; |
599 | u16 head_seq_num, buf_size; | 660 | u16 head_seq_num, buf_size; |
600 | int index; | 661 | int index; |
662 | bool ret = true; | ||
601 | 663 | ||
602 | buf_size = tid_agg_rx->buf_size; | 664 | buf_size = tid_agg_rx->buf_size; |
603 | head_seq_num = tid_agg_rx->head_seq_num; | 665 | head_seq_num = tid_agg_rx->head_seq_num; |
604 | 666 | ||
667 | spin_lock(&tid_agg_rx->reorder_lock); | ||
605 | /* frame with out of date sequence number */ | 668 | /* frame with out of date sequence number */ |
606 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 669 | if (seq_less(mpdu_seq_num, head_seq_num)) { |
607 | dev_kfree_skb(skb); | 670 | dev_kfree_skb(skb); |
608 | return true; | 671 | goto out; |
609 | } | 672 | } |
610 | 673 | ||
611 | /* | 674 | /* |
@@ -626,7 +689,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
626 | /* check if we already stored this frame */ | 689 | /* check if we already stored this frame */ |
627 | if (tid_agg_rx->reorder_buf[index]) { | 690 | if (tid_agg_rx->reorder_buf[index]) { |
628 | dev_kfree_skb(skb); | 691 | dev_kfree_skb(skb); |
629 | return true; | 692 | goto out; |
630 | } | 693 | } |
631 | 694 | ||
632 | /* | 695 | /* |
@@ -636,58 +699,19 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
636 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 699 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
637 | tid_agg_rx->stored_mpdu_num == 0) { | 700 | tid_agg_rx->stored_mpdu_num == 0) { |
638 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 701 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
639 | return false; | 702 | ret = false; |
703 | goto out; | ||
640 | } | 704 | } |
641 | 705 | ||
642 | /* put the frame in the reordering buffer */ | 706 | /* put the frame in the reordering buffer */ |
643 | tid_agg_rx->reorder_buf[index] = skb; | 707 | tid_agg_rx->reorder_buf[index] = skb; |
644 | tid_agg_rx->reorder_time[index] = jiffies; | 708 | tid_agg_rx->reorder_time[index] = jiffies; |
645 | tid_agg_rx->stored_mpdu_num++; | 709 | tid_agg_rx->stored_mpdu_num++; |
646 | /* release the buffer until next missing frame */ | 710 | ieee80211_sta_reorder_release(hw, tid_agg_rx, frames); |
647 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
648 | tid_agg_rx->buf_size; | ||
649 | if (!tid_agg_rx->reorder_buf[index] && | ||
650 | tid_agg_rx->stored_mpdu_num > 1) { | ||
651 | /* | ||
652 | * No buffers ready to be released, but check whether any | ||
653 | * frames in the reorder buffer have timed out. | ||
654 | */ | ||
655 | int j; | ||
656 | int skipped = 1; | ||
657 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | ||
658 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
659 | if (!tid_agg_rx->reorder_buf[j]) { | ||
660 | skipped++; | ||
661 | continue; | ||
662 | } | ||
663 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
664 | HT_RX_REORDER_BUF_TIMEOUT)) | ||
665 | break; | ||
666 | |||
667 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
668 | if (net_ratelimit()) | ||
669 | printk(KERN_DEBUG "%s: release an RX reorder " | ||
670 | "frame due to timeout on earlier " | ||
671 | "frames\n", | ||
672 | wiphy_name(hw->wiphy)); | ||
673 | #endif | ||
674 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | ||
675 | j, frames); | ||
676 | |||
677 | /* | ||
678 | * Increment the head seq# also for the skipped slots. | ||
679 | */ | ||
680 | tid_agg_rx->head_seq_num = | ||
681 | (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; | ||
682 | skipped = 0; | ||
683 | } | ||
684 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
685 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | ||
686 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
687 | tid_agg_rx->buf_size; | ||
688 | } | ||
689 | 711 | ||
690 | return true; | 712 | out: |
713 | spin_unlock(&tid_agg_rx->reorder_lock); | ||
714 | return ret; | ||
691 | } | 715 | } |
692 | 716 | ||
693 | /* | 717 | /* |
@@ -873,6 +897,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
873 | 897 | ||
874 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 898 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { |
875 | rx->key = stakey; | 899 | rx->key = stakey; |
900 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
901 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
902 | return RX_CONTINUE; | ||
876 | /* Skip decryption if the frame is not protected. */ | 903 | /* Skip decryption if the frame is not protected. */ |
877 | if (!ieee80211_has_protected(fc)) | 904 | if (!ieee80211_has_protected(fc)) |
878 | return RX_CONTINUE; | 905 | return RX_CONTINUE; |
@@ -935,7 +962,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
935 | * pairwise or station-to-station keys, but for WEP we allow | 962 | * pairwise or station-to-station keys, but for WEP we allow |
936 | * using a key index as well. | 963 | * using a key index as well. |
937 | */ | 964 | */ |
938 | if (rx->key && rx->key->conf.alg != ALG_WEP && | 965 | if (rx->key && rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && |
966 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && | ||
939 | !is_multicast_ether_addr(hdr->addr1)) | 967 | !is_multicast_ether_addr(hdr->addr1)) |
940 | rx->key = NULL; | 968 | rx->key = NULL; |
941 | } | 969 | } |
@@ -951,8 +979,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
951 | return RX_DROP_UNUSABLE; | 979 | return RX_DROP_UNUSABLE; |
952 | /* the hdr variable is invalid now! */ | 980 | /* the hdr variable is invalid now! */ |
953 | 981 | ||
954 | switch (rx->key->conf.alg) { | 982 | switch (rx->key->conf.cipher) { |
955 | case ALG_WEP: | 983 | case WLAN_CIPHER_SUITE_WEP40: |
984 | case WLAN_CIPHER_SUITE_WEP104: | ||
956 | /* Check for weak IVs if possible */ | 985 | /* Check for weak IVs if possible */ |
957 | if (rx->sta && ieee80211_is_data(fc) && | 986 | if (rx->sta && ieee80211_is_data(fc) && |
958 | (!(status->flag & RX_FLAG_IV_STRIPPED) || | 987 | (!(status->flag & RX_FLAG_IV_STRIPPED) || |
@@ -962,15 +991,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
962 | 991 | ||
963 | result = ieee80211_crypto_wep_decrypt(rx); | 992 | result = ieee80211_crypto_wep_decrypt(rx); |
964 | break; | 993 | break; |
965 | case ALG_TKIP: | 994 | case WLAN_CIPHER_SUITE_TKIP: |
966 | result = ieee80211_crypto_tkip_decrypt(rx); | 995 | result = ieee80211_crypto_tkip_decrypt(rx); |
967 | break; | 996 | break; |
968 | case ALG_CCMP: | 997 | case WLAN_CIPHER_SUITE_CCMP: |
969 | result = ieee80211_crypto_ccmp_decrypt(rx); | 998 | result = ieee80211_crypto_ccmp_decrypt(rx); |
970 | break; | 999 | break; |
971 | case ALG_AES_CMAC: | 1000 | case WLAN_CIPHER_SUITE_AES_CMAC: |
972 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | 1001 | result = ieee80211_crypto_aes_cmac_decrypt(rx); |
973 | break; | 1002 | break; |
1003 | default: | ||
1004 | /* | ||
1005 | * We can reach here only with HW-only algorithms | ||
1006 | * but why didn't it decrypt the frame?! | ||
1007 | */ | ||
1008 | return RX_DROP_UNUSABLE; | ||
974 | } | 1009 | } |
975 | 1010 | ||
976 | /* either the frame has been decrypted or will be dropped */ | 1011 | /* either the frame has been decrypted or will be dropped */ |
@@ -1265,7 +1300,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1265 | /* This is the first fragment of a new frame. */ | 1300 | /* This is the first fragment of a new frame. */ |
1266 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 1301 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
1267 | rx->queue, &(rx->skb)); | 1302 | rx->queue, &(rx->skb)); |
1268 | if (rx->key && rx->key->conf.alg == ALG_CCMP && | 1303 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && |
1269 | ieee80211_has_protected(fc)) { | 1304 | ieee80211_has_protected(fc)) { |
1270 | int queue = ieee80211_is_mgmt(fc) ? | 1305 | int queue = ieee80211_is_mgmt(fc) ? |
1271 | NUM_RX_DATA_QUEUES : rx->queue; | 1306 | NUM_RX_DATA_QUEUES : rx->queue; |
@@ -1294,7 +1329,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1294 | int i; | 1329 | int i; |
1295 | u8 pn[CCMP_PN_LEN], *rpn; | 1330 | u8 pn[CCMP_PN_LEN], *rpn; |
1296 | int queue; | 1331 | int queue; |
1297 | if (!rx->key || rx->key->conf.alg != ALG_CCMP) | 1332 | if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) |
1298 | return RX_DROP_UNUSABLE; | 1333 | return RX_DROP_UNUSABLE; |
1299 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); | 1334 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); |
1300 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { | 1335 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { |
@@ -1492,7 +1527,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) | |||
1492 | * Allow EAPOL frames to us/the PAE group address regardless | 1527 | * Allow EAPOL frames to us/the PAE group address regardless |
1493 | * of whether the frame was encrypted or not. | 1528 | * of whether the frame was encrypted or not. |
1494 | */ | 1529 | */ |
1495 | if (ehdr->h_proto == htons(ETH_P_PAE) && | 1530 | if (ehdr->h_proto == rx->sdata->control_port_protocol && |
1496 | (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 || | 1531 | (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 || |
1497 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) | 1532 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) |
1498 | return true; | 1533 | return true; |
@@ -1909,13 +1944,36 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | |||
1909 | } | 1944 | } |
1910 | 1945 | ||
1911 | static ieee80211_rx_result debug_noinline | 1946 | static ieee80211_rx_result debug_noinline |
1947 | ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | ||
1948 | { | ||
1949 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1950 | |||
1951 | /* | ||
1952 | * From here on, look only at management frames. | ||
1953 | * Data and control frames are already handled, | ||
1954 | * and unknown (reserved) frames are useless. | ||
1955 | */ | ||
1956 | if (rx->skb->len < 24) | ||
1957 | return RX_DROP_MONITOR; | ||
1958 | |||
1959 | if (!ieee80211_is_mgmt(mgmt->frame_control)) | ||
1960 | return RX_DROP_MONITOR; | ||
1961 | |||
1962 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | ||
1963 | return RX_DROP_MONITOR; | ||
1964 | |||
1965 | if (ieee80211_drop_unencrypted_mgmt(rx)) | ||
1966 | return RX_DROP_UNUSABLE; | ||
1967 | |||
1968 | return RX_CONTINUE; | ||
1969 | } | ||
1970 | |||
1971 | static ieee80211_rx_result debug_noinline | ||
1912 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | 1972 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) |
1913 | { | 1973 | { |
1914 | struct ieee80211_local *local = rx->local; | 1974 | struct ieee80211_local *local = rx->local; |
1915 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1975 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1916 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1976 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1917 | struct sk_buff *nskb; | ||
1918 | struct ieee80211_rx_status *status; | ||
1919 | int len = rx->skb->len; | 1977 | int len = rx->skb->len; |
1920 | 1978 | ||
1921 | if (!ieee80211_is_action(mgmt->frame_control)) | 1979 | if (!ieee80211_is_action(mgmt->frame_control)) |
@@ -1931,9 +1989,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1931 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1989 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1932 | return RX_DROP_UNUSABLE; | 1990 | return RX_DROP_UNUSABLE; |
1933 | 1991 | ||
1934 | if (ieee80211_drop_unencrypted_mgmt(rx)) | ||
1935 | return RX_DROP_UNUSABLE; | ||
1936 | |||
1937 | switch (mgmt->u.action.category) { | 1992 | switch (mgmt->u.action.category) { |
1938 | case WLAN_CATEGORY_BACK: | 1993 | case WLAN_CATEGORY_BACK: |
1939 | /* | 1994 | /* |
@@ -2024,17 +2079,36 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2024 | goto queue; | 2079 | goto queue; |
2025 | } | 2080 | } |
2026 | 2081 | ||
2082 | return RX_CONTINUE; | ||
2083 | |||
2027 | invalid: | 2084 | invalid: |
2028 | /* | 2085 | rx->flags |= IEEE80211_MALFORMED_ACTION_FRM; |
2029 | * For AP mode, hostapd is responsible for handling any action | 2086 | /* will return in the next handlers */ |
2030 | * frames that we didn't handle, including returning unknown | 2087 | return RX_CONTINUE; |
2031 | * ones. For all other modes we will return them to the sender, | 2088 | |
2032 | * setting the 0x80 bit in the action category, as required by | 2089 | handled: |
2033 | * 802.11-2007 7.3.1.11. | 2090 | if (rx->sta) |
2034 | */ | 2091 | rx->sta->rx_packets++; |
2035 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 2092 | dev_kfree_skb(rx->skb); |
2036 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 2093 | return RX_QUEUED; |
2037 | return RX_DROP_MONITOR; | 2094 | |
2095 | queue: | ||
2096 | rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; | ||
2097 | skb_queue_tail(&sdata->skb_queue, rx->skb); | ||
2098 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
2099 | if (rx->sta) | ||
2100 | rx->sta->rx_packets++; | ||
2101 | return RX_QUEUED; | ||
2102 | } | ||
2103 | |||
2104 | static ieee80211_rx_result debug_noinline | ||
2105 | ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) | ||
2106 | { | ||
2107 | struct ieee80211_rx_status *status; | ||
2108 | |||
2109 | /* skip known-bad action frames and return them in the next handler */ | ||
2110 | if (rx->flags & IEEE80211_MALFORMED_ACTION_FRM) | ||
2111 | return RX_CONTINUE; | ||
2038 | 2112 | ||
2039 | /* | 2113 | /* |
2040 | * Getting here means the kernel doesn't know how to handle | 2114 | * Getting here means the kernel doesn't know how to handle |
@@ -2044,10 +2118,44 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2044 | */ | 2118 | */ |
2045 | status = IEEE80211_SKB_RXCB(rx->skb); | 2119 | status = IEEE80211_SKB_RXCB(rx->skb); |
2046 | 2120 | ||
2047 | if (cfg80211_rx_action(rx->sdata->dev, status->freq, | 2121 | if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, |
2048 | rx->skb->data, rx->skb->len, | 2122 | rx->skb->data, rx->skb->len, |
2049 | GFP_ATOMIC)) | 2123 | GFP_ATOMIC)) { |
2050 | goto handled; | 2124 | if (rx->sta) |
2125 | rx->sta->rx_packets++; | ||
2126 | dev_kfree_skb(rx->skb); | ||
2127 | return RX_QUEUED; | ||
2128 | } | ||
2129 | |||
2130 | |||
2131 | return RX_CONTINUE; | ||
2132 | } | ||
2133 | |||
2134 | static ieee80211_rx_result debug_noinline | ||
2135 | ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) | ||
2136 | { | ||
2137 | struct ieee80211_local *local = rx->local; | ||
2138 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
2139 | struct sk_buff *nskb; | ||
2140 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
2141 | |||
2142 | if (!ieee80211_is_action(mgmt->frame_control)) | ||
2143 | return RX_CONTINUE; | ||
2144 | |||
2145 | /* | ||
2146 | * For AP mode, hostapd is responsible for handling any action | ||
2147 | * frames that we didn't handle, including returning unknown | ||
2148 | * ones. For all other modes we will return them to the sender, | ||
2149 | * setting the 0x80 bit in the action category, as required by | ||
2150 | * 802.11-2007 7.3.1.11. | ||
2151 | * Newer versions of hostapd shall also use the management frame | ||
2152 | * registration mechanisms, but older ones still use cooked | ||
2153 | * monitor interfaces so push all frames there. | ||
2154 | */ | ||
2155 | if (!(rx->flags & IEEE80211_MALFORMED_ACTION_FRM) && | ||
2156 | (sdata->vif.type == NL80211_IFTYPE_AP || | ||
2157 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) | ||
2158 | return RX_DROP_MONITOR; | ||
2051 | 2159 | ||
2052 | /* do not return rejected action frames */ | 2160 | /* do not return rejected action frames */ |
2053 | if (mgmt->u.action.category & 0x80) | 2161 | if (mgmt->u.action.category & 0x80) |
@@ -2066,20 +2174,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2066 | 2174 | ||
2067 | ieee80211_tx_skb(rx->sdata, nskb); | 2175 | ieee80211_tx_skb(rx->sdata, nskb); |
2068 | } | 2176 | } |
2069 | |||
2070 | handled: | ||
2071 | if (rx->sta) | ||
2072 | rx->sta->rx_packets++; | ||
2073 | dev_kfree_skb(rx->skb); | 2177 | dev_kfree_skb(rx->skb); |
2074 | return RX_QUEUED; | 2178 | return RX_QUEUED; |
2075 | |||
2076 | queue: | ||
2077 | rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; | ||
2078 | skb_queue_tail(&sdata->skb_queue, rx->skb); | ||
2079 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
2080 | if (rx->sta) | ||
2081 | rx->sta->rx_packets++; | ||
2082 | return RX_QUEUED; | ||
2083 | } | 2179 | } |
2084 | 2180 | ||
2085 | static ieee80211_rx_result debug_noinline | 2181 | static ieee80211_rx_result debug_noinline |
@@ -2090,15 +2186,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2090 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; | 2186 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; |
2091 | __le16 stype; | 2187 | __le16 stype; |
2092 | 2188 | ||
2093 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | ||
2094 | return RX_DROP_MONITOR; | ||
2095 | |||
2096 | if (rx->skb->len < 24) | ||
2097 | return RX_DROP_MONITOR; | ||
2098 | |||
2099 | if (ieee80211_drop_unencrypted_mgmt(rx)) | ||
2100 | return RX_DROP_UNUSABLE; | ||
2101 | |||
2102 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); | 2189 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); |
2103 | if (rxs != RX_CONTINUE) | 2190 | if (rxs != RX_CONTINUE) |
2104 | return rxs; | 2191 | return rxs; |
@@ -2263,19 +2350,46 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2263 | dev_kfree_skb(skb); | 2350 | dev_kfree_skb(skb); |
2264 | } | 2351 | } |
2265 | 2352 | ||
2353 | static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | ||
2354 | ieee80211_rx_result res) | ||
2355 | { | ||
2356 | switch (res) { | ||
2357 | case RX_DROP_MONITOR: | ||
2358 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); | ||
2359 | if (rx->sta) | ||
2360 | rx->sta->rx_dropped++; | ||
2361 | /* fall through */ | ||
2362 | case RX_CONTINUE: { | ||
2363 | struct ieee80211_rate *rate = NULL; | ||
2364 | struct ieee80211_supported_band *sband; | ||
2365 | struct ieee80211_rx_status *status; | ||
2366 | |||
2367 | status = IEEE80211_SKB_RXCB((rx->skb)); | ||
2368 | |||
2369 | sband = rx->local->hw.wiphy->bands[status->band]; | ||
2370 | if (!(status->flag & RX_FLAG_HT)) | ||
2371 | rate = &sband->bitrates[status->rate_idx]; | ||
2372 | |||
2373 | ieee80211_rx_cooked_monitor(rx, rate); | ||
2374 | break; | ||
2375 | } | ||
2376 | case RX_DROP_UNUSABLE: | ||
2377 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); | ||
2378 | if (rx->sta) | ||
2379 | rx->sta->rx_dropped++; | ||
2380 | dev_kfree_skb(rx->skb); | ||
2381 | break; | ||
2382 | case RX_QUEUED: | ||
2383 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued); | ||
2384 | break; | ||
2385 | } | ||
2386 | } | ||
2266 | 2387 | ||
2267 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | 2388 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, |
2268 | struct ieee80211_rx_data *rx, | 2389 | struct sk_buff_head *frames) |
2269 | struct sk_buff *skb, | ||
2270 | struct ieee80211_rate *rate) | ||
2271 | { | 2390 | { |
2272 | struct sk_buff_head reorder_release; | ||
2273 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2391 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2274 | 2392 | struct sk_buff *skb; | |
2275 | __skb_queue_head_init(&reorder_release); | ||
2276 | |||
2277 | rx->skb = skb; | ||
2278 | rx->sdata = sdata; | ||
2279 | 2393 | ||
2280 | #define CALL_RXH(rxh) \ | 2394 | #define CALL_RXH(rxh) \ |
2281 | do { \ | 2395 | do { \ |
@@ -2284,17 +2398,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
2284 | goto rxh_next; \ | 2398 | goto rxh_next; \ |
2285 | } while (0); | 2399 | } while (0); |
2286 | 2400 | ||
2287 | /* | 2401 | while ((skb = __skb_dequeue(frames))) { |
2288 | * NB: the rxh_next label works even if we jump | ||
2289 | * to it from here because then the list will | ||
2290 | * be empty, which is a trivial check | ||
2291 | */ | ||
2292 | CALL_RXH(ieee80211_rx_h_passive_scan) | ||
2293 | CALL_RXH(ieee80211_rx_h_check) | ||
2294 | |||
2295 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); | ||
2296 | |||
2297 | while ((skb = __skb_dequeue(&reorder_release))) { | ||
2298 | /* | 2402 | /* |
2299 | * all the other fields are valid across frames | 2403 | * all the other fields are valid across frames |
2300 | * that belong to an aMPDU since they are on the | 2404 | * that belong to an aMPDU since they are on the |
@@ -2312,42 +2416,95 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
2312 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | 2416 | CALL_RXH(ieee80211_rx_h_remove_qos_control) |
2313 | CALL_RXH(ieee80211_rx_h_amsdu) | 2417 | CALL_RXH(ieee80211_rx_h_amsdu) |
2314 | #ifdef CONFIG_MAC80211_MESH | 2418 | #ifdef CONFIG_MAC80211_MESH |
2315 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2419 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) |
2316 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 2420 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
2317 | #endif | 2421 | #endif |
2318 | CALL_RXH(ieee80211_rx_h_data) | 2422 | CALL_RXH(ieee80211_rx_h_data) |
2319 | 2423 | ||
2320 | /* special treatment -- needs the queue */ | 2424 | /* special treatment -- needs the queue */ |
2321 | res = ieee80211_rx_h_ctrl(rx, &reorder_release); | 2425 | res = ieee80211_rx_h_ctrl(rx, frames); |
2322 | if (res != RX_CONTINUE) | 2426 | if (res != RX_CONTINUE) |
2323 | goto rxh_next; | 2427 | goto rxh_next; |
2324 | 2428 | ||
2429 | CALL_RXH(ieee80211_rx_h_mgmt_check) | ||
2325 | CALL_RXH(ieee80211_rx_h_action) | 2430 | CALL_RXH(ieee80211_rx_h_action) |
2431 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) | ||
2432 | CALL_RXH(ieee80211_rx_h_action_return) | ||
2326 | CALL_RXH(ieee80211_rx_h_mgmt) | 2433 | CALL_RXH(ieee80211_rx_h_mgmt) |
2327 | 2434 | ||
2435 | rxh_next: | ||
2436 | ieee80211_rx_handlers_result(rx, res); | ||
2437 | |||
2328 | #undef CALL_RXH | 2438 | #undef CALL_RXH |
2439 | } | ||
2440 | } | ||
2441 | |||
2442 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | ||
2443 | struct ieee80211_rx_data *rx, | ||
2444 | struct sk_buff *skb) | ||
2445 | { | ||
2446 | struct sk_buff_head reorder_release; | ||
2447 | ieee80211_rx_result res = RX_DROP_MONITOR; | ||
2448 | |||
2449 | __skb_queue_head_init(&reorder_release); | ||
2450 | |||
2451 | rx->skb = skb; | ||
2452 | rx->sdata = sdata; | ||
2453 | |||
2454 | #define CALL_RXH(rxh) \ | ||
2455 | do { \ | ||
2456 | res = rxh(rx); \ | ||
2457 | if (res != RX_CONTINUE) \ | ||
2458 | goto rxh_next; \ | ||
2459 | } while (0); | ||
2460 | |||
2461 | CALL_RXH(ieee80211_rx_h_passive_scan) | ||
2462 | CALL_RXH(ieee80211_rx_h_check) | ||
2463 | |||
2464 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); | ||
2465 | |||
2466 | ieee80211_rx_handlers(rx, &reorder_release); | ||
2467 | return; | ||
2329 | 2468 | ||
2330 | rxh_next: | 2469 | rxh_next: |
2331 | switch (res) { | 2470 | ieee80211_rx_handlers_result(rx, res); |
2332 | case RX_DROP_MONITOR: | 2471 | |
2333 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); | 2472 | #undef CALL_RXH |
2334 | if (rx->sta) | 2473 | } |
2335 | rx->sta->rx_dropped++; | 2474 | |
2336 | /* fall through */ | 2475 | /* |
2337 | case RX_CONTINUE: | 2476 | * This function makes calls into the RX path. Therefore the |
2338 | ieee80211_rx_cooked_monitor(rx, rate); | 2477 | * caller must hold the sta_info->lock and everything has to |
2339 | break; | 2478 | * be under rcu_read_lock protection as well. |
2340 | case RX_DROP_UNUSABLE: | 2479 | */ |
2341 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); | 2480 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) |
2342 | if (rx->sta) | 2481 | { |
2343 | rx->sta->rx_dropped++; | 2482 | struct sk_buff_head frames; |
2344 | dev_kfree_skb(rx->skb); | 2483 | struct ieee80211_rx_data rx = { }; |
2345 | break; | 2484 | struct tid_ampdu_rx *tid_agg_rx; |
2346 | case RX_QUEUED: | 2485 | |
2347 | I802_DEBUG_INC(sdata->local->rx_handlers_queued); | 2486 | tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); |
2348 | break; | 2487 | if (!tid_agg_rx) |
2349 | } | 2488 | return; |
2350 | } | 2489 | |
2490 | __skb_queue_head_init(&frames); | ||
2491 | |||
2492 | /* construct rx struct */ | ||
2493 | rx.sta = sta; | ||
2494 | rx.sdata = sta->sdata; | ||
2495 | rx.local = sta->local; | ||
2496 | rx.queue = tid; | ||
2497 | rx.flags |= IEEE80211_RX_RA_MATCH; | ||
2498 | |||
2499 | if (unlikely(test_bit(SCAN_HW_SCANNING, &sta->local->scanning) || | ||
2500 | test_bit(SCAN_OFF_CHANNEL, &sta->local->scanning))) | ||
2501 | rx.flags |= IEEE80211_RX_IN_SCAN; | ||
2502 | |||
2503 | spin_lock(&tid_agg_rx->reorder_lock); | ||
2504 | ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx, &frames); | ||
2505 | spin_unlock(&tid_agg_rx->reorder_lock); | ||
2506 | |||
2507 | ieee80211_rx_handlers(&rx, &frames); | ||
2351 | } | 2508 | } |
2352 | 2509 | ||
2353 | /* main receive path */ | 2510 | /* main receive path */ |
@@ -2427,9 +2584,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2427 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) | 2584 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
2428 | return 0; | 2585 | return 0; |
2429 | break; | 2586 | break; |
2430 | case NL80211_IFTYPE_MONITOR: | 2587 | default: |
2431 | case NL80211_IFTYPE_UNSPECIFIED: | ||
2432 | case __NL80211_IFTYPE_AFTER_LAST: | ||
2433 | /* should never get here */ | 2588 | /* should never get here */ |
2434 | WARN_ON(1); | 2589 | WARN_ON(1); |
2435 | break; | 2590 | break; |
@@ -2443,8 +2598,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2443 | * be called with rcu_read_lock protection. | 2598 | * be called with rcu_read_lock protection. |
2444 | */ | 2599 | */ |
2445 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | 2600 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, |
2446 | struct sk_buff *skb, | 2601 | struct sk_buff *skb) |
2447 | struct ieee80211_rate *rate) | ||
2448 | { | 2602 | { |
2449 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 2603 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
2450 | struct ieee80211_local *local = hw_to_local(hw); | 2604 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -2546,13 +2700,12 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2546 | skb_new = skb_copy(skb, GFP_ATOMIC); | 2700 | skb_new = skb_copy(skb, GFP_ATOMIC); |
2547 | if (!skb_new) { | 2701 | if (!skb_new) { |
2548 | if (net_ratelimit()) | 2702 | if (net_ratelimit()) |
2549 | printk(KERN_DEBUG "%s: failed to copy " | 2703 | wiphy_debug(local->hw.wiphy, |
2550 | "multicast frame for %s\n", | 2704 | "failed to copy multicast frame for %s\n", |
2551 | wiphy_name(local->hw.wiphy), | 2705 | prev->name); |
2552 | prev->name); | ||
2553 | goto next; | 2706 | goto next; |
2554 | } | 2707 | } |
2555 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); | 2708 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); |
2556 | next: | 2709 | next: |
2557 | prev = sdata; | 2710 | prev = sdata; |
2558 | } | 2711 | } |
@@ -2568,7 +2721,7 @@ next: | |||
2568 | } | 2721 | } |
2569 | } | 2722 | } |
2570 | if (prev) | 2723 | if (prev) |
2571 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); | 2724 | ieee80211_invoke_rx_handlers(prev, &rx, skb); |
2572 | else | 2725 | else |
2573 | dev_kfree_skb(skb); | 2726 | dev_kfree_skb(skb); |
2574 | } | 2727 | } |
@@ -2611,28 +2764,37 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2611 | if (WARN_ON(!local->started)) | 2764 | if (WARN_ON(!local->started)) |
2612 | goto drop; | 2765 | goto drop; |
2613 | 2766 | ||
2614 | if (status->flag & RX_FLAG_HT) { | 2767 | if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { |
2615 | /* | 2768 | /* |
2616 | * rate_idx is MCS index, which can be [0-76] as documented on: | 2769 | * Validate the rate, unless a PLCP error means that |
2617 | * | 2770 | * we probably can't have a valid rate here anyway. |
2618 | * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n | ||
2619 | * | ||
2620 | * Anything else would be some sort of driver or hardware error. | ||
2621 | * The driver should catch hardware errors. | ||
2622 | */ | 2771 | */ |
2623 | if (WARN((status->rate_idx < 0 || | 2772 | |
2624 | status->rate_idx > 76), | 2773 | if (status->flag & RX_FLAG_HT) { |
2625 | "Rate marked as an HT rate but passed " | 2774 | /* |
2626 | "status->rate_idx is not " | 2775 | * rate_idx is MCS index, which can be [0-76] |
2627 | "an MCS index [0-76]: %d (0x%02x)\n", | 2776 | * as documented on: |
2628 | status->rate_idx, | 2777 | * |
2629 | status->rate_idx)) | 2778 | * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n |
2630 | goto drop; | 2779 | * |
2631 | } else { | 2780 | * Anything else would be some sort of driver or |
2632 | if (WARN_ON(status->rate_idx < 0 || | 2781 | * hardware error. The driver should catch hardware |
2633 | status->rate_idx >= sband->n_bitrates)) | 2782 | * errors. |
2634 | goto drop; | 2783 | */ |
2635 | rate = &sband->bitrates[status->rate_idx]; | 2784 | if (WARN((status->rate_idx < 0 || |
2785 | status->rate_idx > 76), | ||
2786 | "Rate marked as an HT rate but passed " | ||
2787 | "status->rate_idx is not " | ||
2788 | "an MCS index [0-76]: %d (0x%02x)\n", | ||
2789 | status->rate_idx, | ||
2790 | status->rate_idx)) | ||
2791 | goto drop; | ||
2792 | } else { | ||
2793 | if (WARN_ON(status->rate_idx < 0 || | ||
2794 | status->rate_idx >= sband->n_bitrates)) | ||
2795 | goto drop; | ||
2796 | rate = &sband->bitrates[status->rate_idx]; | ||
2797 | } | ||
2636 | } | 2798 | } |
2637 | 2799 | ||
2638 | /* | 2800 | /* |
@@ -2654,7 +2816,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2654 | return; | 2816 | return; |
2655 | } | 2817 | } |
2656 | 2818 | ||
2657 | __ieee80211_rx_handle_packet(hw, skb, rate); | 2819 | __ieee80211_rx_handle_packet(hw, skb); |
2658 | 2820 | ||
2659 | rcu_read_unlock(); | 2821 | rcu_read_unlock(); |
2660 | 2822 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 872d7b6ef6b3..d60389ba9b95 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -248,14 +248,12 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
248 | return true; | 248 | return true; |
249 | } | 249 | } |
250 | 250 | ||
251 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 251 | static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
252 | { | 252 | { |
253 | struct ieee80211_local *local = hw_to_local(hw); | 253 | struct ieee80211_local *local = hw_to_local(hw); |
254 | bool was_hw_scan; | 254 | bool was_hw_scan; |
255 | 255 | ||
256 | trace_api_scan_completed(local, aborted); | 256 | mutex_lock(&local->mtx); |
257 | |||
258 | mutex_lock(&local->scan_mtx); | ||
259 | 257 | ||
260 | /* | 258 | /* |
261 | * It's ok to abort a not-yet-running scan (that | 259 | * It's ok to abort a not-yet-running scan (that |
@@ -267,7 +265,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
267 | aborted = true; | 265 | aborted = true; |
268 | 266 | ||
269 | if (WARN_ON(!local->scan_req)) { | 267 | if (WARN_ON(!local->scan_req)) { |
270 | mutex_unlock(&local->scan_mtx); | 268 | mutex_unlock(&local->mtx); |
271 | return; | 269 | return; |
272 | } | 270 | } |
273 | 271 | ||
@@ -275,7 +273,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
275 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 273 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { |
276 | ieee80211_queue_delayed_work(&local->hw, | 274 | ieee80211_queue_delayed_work(&local->hw, |
277 | &local->scan_work, 0); | 275 | &local->scan_work, 0); |
278 | mutex_unlock(&local->scan_mtx); | 276 | mutex_unlock(&local->mtx); |
279 | return; | 277 | return; |
280 | } | 278 | } |
281 | 279 | ||
@@ -291,7 +289,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
291 | local->scan_channel = NULL; | 289 | local->scan_channel = NULL; |
292 | 290 | ||
293 | /* we only have to protect scan_req and hw/sw scan */ | 291 | /* we only have to protect scan_req and hw/sw scan */ |
294 | mutex_unlock(&local->scan_mtx); | 292 | mutex_unlock(&local->mtx); |
295 | 293 | ||
296 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 294 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
297 | if (was_hw_scan) | 295 | if (was_hw_scan) |
@@ -304,12 +302,26 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
304 | ieee80211_offchannel_return(local, true); | 302 | ieee80211_offchannel_return(local, true); |
305 | 303 | ||
306 | done: | 304 | done: |
305 | mutex_lock(&local->mtx); | ||
307 | ieee80211_recalc_idle(local); | 306 | ieee80211_recalc_idle(local); |
307 | mutex_unlock(&local->mtx); | ||
308 | ieee80211_mlme_notify_scan_completed(local); | 308 | ieee80211_mlme_notify_scan_completed(local); |
309 | ieee80211_ibss_notify_scan_completed(local); | 309 | ieee80211_ibss_notify_scan_completed(local); |
310 | ieee80211_mesh_notify_scan_completed(local); | 310 | ieee80211_mesh_notify_scan_completed(local); |
311 | ieee80211_queue_work(&local->hw, &local->work_work); | 311 | ieee80211_queue_work(&local->hw, &local->work_work); |
312 | } | 312 | } |
313 | |||
314 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | ||
315 | { | ||
316 | struct ieee80211_local *local = hw_to_local(hw); | ||
317 | |||
318 | trace_api_scan_completed(local, aborted); | ||
319 | |||
320 | set_bit(SCAN_COMPLETED, &local->scanning); | ||
321 | if (aborted) | ||
322 | set_bit(SCAN_ABORTED, &local->scanning); | ||
323 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); | ||
324 | } | ||
313 | EXPORT_SYMBOL(ieee80211_scan_completed); | 325 | EXPORT_SYMBOL(ieee80211_scan_completed); |
314 | 326 | ||
315 | static int ieee80211_start_sw_scan(struct ieee80211_local *local) | 327 | static int ieee80211_start_sw_scan(struct ieee80211_local *local) |
@@ -447,7 +459,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
447 | 459 | ||
448 | /* if no more bands/channels left, complete scan and advance to the idle state */ | 460 | /* if no more bands/channels left, complete scan and advance to the idle state */ |
449 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | 461 | if (local->scan_channel_idx >= local->scan_req->n_channels) { |
450 | ieee80211_scan_completed(&local->hw, false); | 462 | __ieee80211_scan_completed(&local->hw, false); |
451 | return 1; | 463 | return 1; |
452 | } | 464 | } |
453 | 465 | ||
@@ -639,17 +651,25 @@ void ieee80211_scan_work(struct work_struct *work) | |||
639 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 651 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
640 | unsigned long next_delay = 0; | 652 | unsigned long next_delay = 0; |
641 | 653 | ||
642 | mutex_lock(&local->scan_mtx); | 654 | if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { |
655 | bool aborted; | ||
656 | |||
657 | aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); | ||
658 | __ieee80211_scan_completed(&local->hw, aborted); | ||
659 | return; | ||
660 | } | ||
661 | |||
662 | mutex_lock(&local->mtx); | ||
643 | if (!sdata || !local->scan_req) { | 663 | if (!sdata || !local->scan_req) { |
644 | mutex_unlock(&local->scan_mtx); | 664 | mutex_unlock(&local->mtx); |
645 | return; | 665 | return; |
646 | } | 666 | } |
647 | 667 | ||
648 | if (local->hw_scan_req) { | 668 | if (local->hw_scan_req) { |
649 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); | 669 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); |
650 | mutex_unlock(&local->scan_mtx); | 670 | mutex_unlock(&local->mtx); |
651 | if (rc) | 671 | if (rc) |
652 | ieee80211_scan_completed(&local->hw, true); | 672 | __ieee80211_scan_completed(&local->hw, true); |
653 | return; | 673 | return; |
654 | } | 674 | } |
655 | 675 | ||
@@ -661,20 +681,20 @@ void ieee80211_scan_work(struct work_struct *work) | |||
661 | local->scan_sdata = NULL; | 681 | local->scan_sdata = NULL; |
662 | 682 | ||
663 | rc = __ieee80211_start_scan(sdata, req); | 683 | rc = __ieee80211_start_scan(sdata, req); |
664 | mutex_unlock(&local->scan_mtx); | 684 | mutex_unlock(&local->mtx); |
665 | 685 | ||
666 | if (rc) | 686 | if (rc) |
667 | ieee80211_scan_completed(&local->hw, true); | 687 | __ieee80211_scan_completed(&local->hw, true); |
668 | return; | 688 | return; |
669 | } | 689 | } |
670 | 690 | ||
671 | mutex_unlock(&local->scan_mtx); | 691 | mutex_unlock(&local->mtx); |
672 | 692 | ||
673 | /* | 693 | /* |
674 | * Avoid re-scheduling when the sdata is going away. | 694 | * Avoid re-scheduling when the sdata is going away. |
675 | */ | 695 | */ |
676 | if (!ieee80211_sdata_running(sdata)) { | 696 | if (!ieee80211_sdata_running(sdata)) { |
677 | ieee80211_scan_completed(&local->hw, true); | 697 | __ieee80211_scan_completed(&local->hw, true); |
678 | return; | 698 | return; |
679 | } | 699 | } |
680 | 700 | ||
@@ -711,9 +731,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
711 | { | 731 | { |
712 | int res; | 732 | int res; |
713 | 733 | ||
714 | mutex_lock(&sdata->local->scan_mtx); | 734 | mutex_lock(&sdata->local->mtx); |
715 | res = __ieee80211_start_scan(sdata, req); | 735 | res = __ieee80211_start_scan(sdata, req); |
716 | mutex_unlock(&sdata->local->scan_mtx); | 736 | mutex_unlock(&sdata->local->mtx); |
717 | 737 | ||
718 | return res; | 738 | return res; |
719 | } | 739 | } |
@@ -726,7 +746,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
726 | int ret = -EBUSY; | 746 | int ret = -EBUSY; |
727 | enum ieee80211_band band; | 747 | enum ieee80211_band band; |
728 | 748 | ||
729 | mutex_lock(&local->scan_mtx); | 749 | mutex_lock(&local->mtx); |
730 | 750 | ||
731 | /* busy scanning */ | 751 | /* busy scanning */ |
732 | if (local->scan_req) | 752 | if (local->scan_req) |
@@ -761,7 +781,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
761 | 781 | ||
762 | ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); | 782 | ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); |
763 | unlock: | 783 | unlock: |
764 | mutex_unlock(&local->scan_mtx); | 784 | mutex_unlock(&local->mtx); |
765 | return ret; | 785 | return ret; |
766 | } | 786 | } |
767 | 787 | ||
@@ -775,11 +795,11 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
775 | * Only call this function when a scan can't be | 795 | * Only call this function when a scan can't be |
776 | * queued -- mostly at suspend under RTNL. | 796 | * queued -- mostly at suspend under RTNL. |
777 | */ | 797 | */ |
778 | mutex_lock(&local->scan_mtx); | 798 | mutex_lock(&local->mtx); |
779 | abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || | 799 | abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || |
780 | (!local->scanning && local->scan_req); | 800 | (!local->scanning && local->scan_req); |
781 | mutex_unlock(&local->scan_mtx); | 801 | mutex_unlock(&local->mtx); |
782 | 802 | ||
783 | if (abortscan) | 803 | if (abortscan) |
784 | ieee80211_scan_completed(&local->hw, true); | 804 | __ieee80211_scan_completed(&local->hw, true); |
785 | } | 805 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 6d86f0c1ad04..44e10a9de0a7 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -125,7 +125,7 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
125 | lockdep_is_held(&local->sta_mtx)); | 125 | lockdep_is_held(&local->sta_mtx)); |
126 | while (sta) { | 126 | while (sta) { |
127 | if ((sta->sdata == sdata || | 127 | if ((sta->sdata == sdata || |
128 | sta->sdata->bss == sdata->bss) && | 128 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && |
129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
130 | break; | 130 | break; |
131 | sta = rcu_dereference_check(sta->hnext, | 131 | sta = rcu_dereference_check(sta->hnext, |
@@ -174,8 +174,7 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
174 | } | 174 | } |
175 | 175 | ||
176 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 176 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
177 | printk(KERN_DEBUG "%s: Destroyed STA %pM\n", | 177 | wiphy_debug(local->hw.wiphy, "Destroyed STA %pM\n", sta->sta.addr); |
178 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
179 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 178 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
180 | 179 | ||
181 | kfree(sta); | 180 | kfree(sta); |
@@ -262,8 +261,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
262 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); | 261 | sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX); |
263 | 262 | ||
264 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 263 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
265 | printk(KERN_DEBUG "%s: Allocated STA %pM\n", | 264 | wiphy_debug(local->hw.wiphy, "Allocated STA %pM\n", sta->sta.addr); |
266 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
267 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 265 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
268 | 266 | ||
269 | #ifdef CONFIG_MAC80211_MESH | 267 | #ifdef CONFIG_MAC80211_MESH |
@@ -282,7 +280,7 @@ static int sta_info_finish_insert(struct sta_info *sta, bool async) | |||
282 | unsigned long flags; | 280 | unsigned long flags; |
283 | int err = 0; | 281 | int err = 0; |
284 | 282 | ||
285 | WARN_ON(!mutex_is_locked(&local->sta_mtx)); | 283 | lockdep_assert_held(&local->sta_mtx); |
286 | 284 | ||
287 | /* notify driver */ | 285 | /* notify driver */ |
288 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 286 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -300,8 +298,9 @@ static int sta_info_finish_insert(struct sta_info *sta, bool async) | |||
300 | sta->uploaded = true; | 298 | sta->uploaded = true; |
301 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 299 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
302 | if (async) | 300 | if (async) |
303 | printk(KERN_DEBUG "%s: Finished adding IBSS STA %pM\n", | 301 | wiphy_debug(local->hw.wiphy, |
304 | wiphy_name(local->hw.wiphy), sta->sta.addr); | 302 | "Finished adding IBSS STA %pM\n", |
303 | sta->sta.addr); | ||
305 | #endif | 304 | #endif |
306 | } | 305 | } |
307 | 306 | ||
@@ -411,8 +410,8 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | |||
411 | spin_unlock_irqrestore(&local->sta_lock, flags); | 410 | spin_unlock_irqrestore(&local->sta_lock, flags); |
412 | 411 | ||
413 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 412 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
414 | printk(KERN_DEBUG "%s: Added IBSS STA %pM\n", | 413 | wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", |
415 | wiphy_name(local->hw.wiphy), sta->sta.addr); | 414 | sta->sta.addr); |
416 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 415 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
417 | 416 | ||
418 | ieee80211_queue_work(&local->hw, &local->sta_finish_work); | 417 | ieee80211_queue_work(&local->hw, &local->sta_finish_work); |
@@ -459,8 +458,7 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | |||
459 | } | 458 | } |
460 | 459 | ||
461 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 460 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
462 | printk(KERN_DEBUG "%s: Inserted STA %pM\n", | 461 | wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); |
463 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
464 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 462 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
465 | 463 | ||
466 | /* move reference to rcu-protected */ | 464 | /* move reference to rcu-protected */ |
@@ -690,8 +688,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
690 | #endif | 688 | #endif |
691 | 689 | ||
692 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 690 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
693 | printk(KERN_DEBUG "%s: Removed STA %pM\n", | 691 | wiphy_debug(local->hw.wiphy, "Removed STA %pM\n", sta->sta.addr); |
694 | wiphy_name(local->hw.wiphy), sta->sta.addr); | ||
695 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 692 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
696 | cancel_work_sync(&sta->drv_unblock_wk); | 693 | cancel_work_sync(&sta->drv_unblock_wk); |
697 | 694 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 54262e72376d..810c5ce98316 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -103,6 +103,7 @@ struct tid_ampdu_tx { | |||
103 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs | 103 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs |
104 | * @reorder_time: jiffies when skb was added | 104 | * @reorder_time: jiffies when skb was added |
105 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) | 105 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) |
106 | * @reorder_timer: releases expired frames from the reorder buffer. | ||
106 | * @head_seq_num: head sequence number in reordering buffer. | 107 | * @head_seq_num: head sequence number in reordering buffer. |
107 | * @stored_mpdu_num: number of MPDUs in reordering buffer | 108 | * @stored_mpdu_num: number of MPDUs in reordering buffer |
108 | * @ssn: Starting Sequence Number expected to be aggregated. | 109 | * @ssn: Starting Sequence Number expected to be aggregated. |
@@ -110,20 +111,25 @@ struct tid_ampdu_tx { | |||
110 | * @timeout: reset timer value (in TUs). | 111 | * @timeout: reset timer value (in TUs). |
111 | * @dialog_token: dialog token for aggregation session | 112 | * @dialog_token: dialog token for aggregation session |
112 | * @rcu_head: RCU head used for freeing this struct | 113 | * @rcu_head: RCU head used for freeing this struct |
114 | * @reorder_lock: serializes access to reorder buffer, see below. | ||
113 | * | 115 | * |
114 | * This structure is protected by RCU and the per-station | 116 | * This structure is protected by RCU and the per-station |
115 | * spinlock. Assignments to the array holding it must hold | 117 | * spinlock. Assignments to the array holding it must hold |
116 | * the spinlock, only the RX path can access it under RCU | 118 | * the spinlock. |
117 | * lock-free. The RX path, since it is single-threaded, | 119 | * |
118 | * can even modify the structure without locking since the | 120 | * The @reorder_lock is used to protect the variables and |
119 | * only other modifications to it are done when the struct | 121 | * arrays such as @reorder_buf, @reorder_time, @head_seq_num, |
120 | * can not yet or no longer be found by the RX path. | 122 | * @stored_mpdu_num and @reorder_time from being corrupted by |
123 | * concurrent access of the RX path and the expired frame | ||
124 | * release timer. | ||
121 | */ | 125 | */ |
122 | struct tid_ampdu_rx { | 126 | struct tid_ampdu_rx { |
123 | struct rcu_head rcu_head; | 127 | struct rcu_head rcu_head; |
128 | spinlock_t reorder_lock; | ||
124 | struct sk_buff **reorder_buf; | 129 | struct sk_buff **reorder_buf; |
125 | unsigned long *reorder_time; | 130 | unsigned long *reorder_time; |
126 | struct timer_list session_timer; | 131 | struct timer_list session_timer; |
132 | struct timer_list reorder_timer; | ||
127 | u16 head_seq_num; | 133 | u16 head_seq_num; |
128 | u16 stored_mpdu_num; | 134 | u16 stored_mpdu_num; |
129 | u16 ssn; | 135 | u16 ssn; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 10caec5ea8fa..571b32bfc54c 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -114,11 +114,10 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
114 | 114 | ||
115 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 115 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
116 | if (net_ratelimit()) | 116 | if (net_ratelimit()) |
117 | printk(KERN_DEBUG "%s: dropped TX filtered frame, " | 117 | wiphy_debug(local->hw.wiphy, |
118 | "queue_len=%d PS=%d @%lu\n", | 118 | "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", |
119 | wiphy_name(local->hw.wiphy), | 119 | skb_queue_len(&sta->tx_filtered), |
120 | skb_queue_len(&sta->tx_filtered), | 120 | !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); |
121 | !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); | ||
122 | #endif | 121 | #endif |
123 | dev_kfree_skb(skb); | 122 | dev_kfree_skb(skb); |
124 | } | 123 | } |
@@ -296,7 +295,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
296 | } | 295 | } |
297 | 296 | ||
298 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) | 297 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) |
299 | cfg80211_action_tx_status( | 298 | cfg80211_mgmt_tx_status( |
300 | skb->dev, (unsigned long) skb, skb->data, skb->len, | 299 | skb->dev, (unsigned long) skb, skb->data, skb->len, |
301 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); | 300 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); |
302 | 301 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c54db966926b..e1733dcb58a7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -351,8 +351,8 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
351 | 351 | ||
352 | local->total_ps_buffered = total; | 352 | local->total_ps_buffered = total; |
353 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 353 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
354 | printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n", | 354 | wiphy_debug(local->hw.wiphy, "PS buffers full - purged %d frames\n", |
355 | wiphy_name(local->hw.wiphy), purged); | 355 | purged); |
356 | #endif | 356 | #endif |
357 | } | 357 | } |
358 | 358 | ||
@@ -509,6 +509,18 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) | |||
509 | } | 509 | } |
510 | 510 | ||
511 | static ieee80211_tx_result debug_noinline | 511 | static ieee80211_tx_result debug_noinline |
512 | ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx) | ||
513 | { | ||
514 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
515 | |||
516 | if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol && | ||
517 | tx->sdata->control_port_no_encrypt)) | ||
518 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
519 | |||
520 | return TX_CONTINUE; | ||
521 | } | ||
522 | |||
523 | static ieee80211_tx_result debug_noinline | ||
512 | ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | 524 | ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) |
513 | { | 525 | { |
514 | struct ieee80211_key *key = NULL; | 526 | struct ieee80211_key *key = NULL; |
@@ -527,7 +539,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
527 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 539 | else if ((key = rcu_dereference(tx->sdata->default_key))) |
528 | tx->key = key; | 540 | tx->key = key; |
529 | else if (tx->sdata->drop_unencrypted && | 541 | else if (tx->sdata->drop_unencrypted && |
530 | (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) && | 542 | (tx->skb->protocol != tx->sdata->control_port_protocol) && |
531 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | 543 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && |
532 | (!ieee80211_is_robust_mgmt_frame(hdr) || | 544 | (!ieee80211_is_robust_mgmt_frame(hdr) || |
533 | (ieee80211_is_action(hdr->frame_control) && | 545 | (ieee80211_is_action(hdr->frame_control) && |
@@ -543,15 +555,16 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
543 | tx->key->tx_rx_count++; | 555 | tx->key->tx_rx_count++; |
544 | /* TODO: add threshold stuff again */ | 556 | /* TODO: add threshold stuff again */ |
545 | 557 | ||
546 | switch (tx->key->conf.alg) { | 558 | switch (tx->key->conf.cipher) { |
547 | case ALG_WEP: | 559 | case WLAN_CIPHER_SUITE_WEP40: |
560 | case WLAN_CIPHER_SUITE_WEP104: | ||
548 | if (ieee80211_is_auth(hdr->frame_control)) | 561 | if (ieee80211_is_auth(hdr->frame_control)) |
549 | break; | 562 | break; |
550 | case ALG_TKIP: | 563 | case WLAN_CIPHER_SUITE_TKIP: |
551 | if (!ieee80211_is_data_present(hdr->frame_control)) | 564 | if (!ieee80211_is_data_present(hdr->frame_control)) |
552 | tx->key = NULL; | 565 | tx->key = NULL; |
553 | break; | 566 | break; |
554 | case ALG_CCMP: | 567 | case WLAN_CIPHER_SUITE_CCMP: |
555 | if (!ieee80211_is_data_present(hdr->frame_control) && | 568 | if (!ieee80211_is_data_present(hdr->frame_control) && |
556 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, | 569 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, |
557 | tx->skb)) | 570 | tx->skb)) |
@@ -561,7 +574,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
561 | IEEE80211_KEY_FLAG_SW_MGMT) && | 574 | IEEE80211_KEY_FLAG_SW_MGMT) && |
562 | ieee80211_is_mgmt(hdr->frame_control); | 575 | ieee80211_is_mgmt(hdr->frame_control); |
563 | break; | 576 | break; |
564 | case ALG_AES_CMAC: | 577 | case WLAN_CIPHER_SUITE_AES_CMAC: |
565 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 578 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
566 | tx->key = NULL; | 579 | tx->key = NULL; |
567 | break; | 580 | break; |
@@ -946,22 +959,31 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | |||
946 | static ieee80211_tx_result debug_noinline | 959 | static ieee80211_tx_result debug_noinline |
947 | ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | 960 | ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) |
948 | { | 961 | { |
962 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
963 | |||
949 | if (!tx->key) | 964 | if (!tx->key) |
950 | return TX_CONTINUE; | 965 | return TX_CONTINUE; |
951 | 966 | ||
952 | switch (tx->key->conf.alg) { | 967 | switch (tx->key->conf.cipher) { |
953 | case ALG_WEP: | 968 | case WLAN_CIPHER_SUITE_WEP40: |
969 | case WLAN_CIPHER_SUITE_WEP104: | ||
954 | return ieee80211_crypto_wep_encrypt(tx); | 970 | return ieee80211_crypto_wep_encrypt(tx); |
955 | case ALG_TKIP: | 971 | case WLAN_CIPHER_SUITE_TKIP: |
956 | return ieee80211_crypto_tkip_encrypt(tx); | 972 | return ieee80211_crypto_tkip_encrypt(tx); |
957 | case ALG_CCMP: | 973 | case WLAN_CIPHER_SUITE_CCMP: |
958 | return ieee80211_crypto_ccmp_encrypt(tx); | 974 | return ieee80211_crypto_ccmp_encrypt(tx); |
959 | case ALG_AES_CMAC: | 975 | case WLAN_CIPHER_SUITE_AES_CMAC: |
960 | return ieee80211_crypto_aes_cmac_encrypt(tx); | 976 | return ieee80211_crypto_aes_cmac_encrypt(tx); |
977 | default: | ||
978 | /* handle hw-only algorithm */ | ||
979 | if (info->control.hw_key) { | ||
980 | ieee80211_tx_set_protected(tx); | ||
981 | return TX_CONTINUE; | ||
982 | } | ||
983 | break; | ||
984 | |||
961 | } | 985 | } |
962 | 986 | ||
963 | /* not reached */ | ||
964 | WARN_ON(1); | ||
965 | return TX_DROP; | 987 | return TX_DROP; |
966 | } | 988 | } |
967 | 989 | ||
@@ -1339,6 +1361,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1339 | CALL_TXH(ieee80211_tx_h_dynamic_ps); | 1361 | CALL_TXH(ieee80211_tx_h_dynamic_ps); |
1340 | CALL_TXH(ieee80211_tx_h_check_assoc); | 1362 | CALL_TXH(ieee80211_tx_h_check_assoc); |
1341 | CALL_TXH(ieee80211_tx_h_ps_buf); | 1363 | CALL_TXH(ieee80211_tx_h_ps_buf); |
1364 | CALL_TXH(ieee80211_tx_h_check_control_port_protocol); | ||
1342 | CALL_TXH(ieee80211_tx_h_select_key); | 1365 | CALL_TXH(ieee80211_tx_h_select_key); |
1343 | if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) | 1366 | if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) |
1344 | CALL_TXH(ieee80211_tx_h_rate_ctrl); | 1367 | CALL_TXH(ieee80211_tx_h_rate_ctrl); |
@@ -1511,8 +1534,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1511 | I802_DEBUG_INC(local->tx_expand_skb_head); | 1534 | I802_DEBUG_INC(local->tx_expand_skb_head); |
1512 | 1535 | ||
1513 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { | 1536 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { |
1514 | printk(KERN_DEBUG "%s: failed to reallocate TX buffer\n", | 1537 | wiphy_debug(local->hw.wiphy, |
1515 | wiphy_name(local->hw.wiphy)); | 1538 | "failed to reallocate TX buffer\n"); |
1516 | return -ENOMEM; | 1539 | return -ENOMEM; |
1517 | } | 1540 | } |
1518 | 1541 | ||
@@ -1586,6 +1609,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1586 | return; | 1609 | return; |
1587 | } | 1610 | } |
1588 | 1611 | ||
1612 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1589 | info->control.vif = &sdata->vif; | 1613 | info->control.vif = &sdata->vif; |
1590 | 1614 | ||
1591 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 1615 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
@@ -1699,7 +1723,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1699 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1723 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1700 | __le16 fc; | 1724 | __le16 fc; |
1701 | struct ieee80211_hdr hdr; | 1725 | struct ieee80211_hdr hdr; |
1702 | struct ieee80211s_hdr mesh_hdr; | 1726 | struct ieee80211s_hdr mesh_hdr __maybe_unused; |
1703 | const u8 *encaps_data; | 1727 | const u8 *encaps_data; |
1704 | int encaps_len, skip_header_bytes; | 1728 | int encaps_len, skip_header_bytes; |
1705 | int nh_pos, h_pos; | 1729 | int nh_pos, h_pos; |
@@ -1816,7 +1840,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1816 | #endif | 1840 | #endif |
1817 | case NL80211_IFTYPE_STATION: | 1841 | case NL80211_IFTYPE_STATION: |
1818 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); | 1842 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); |
1819 | if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) { | 1843 | if (sdata->u.mgd.use_4addr && |
1844 | cpu_to_be16(ethertype) != sdata->control_port_protocol) { | ||
1820 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1845 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1821 | /* RA TA DA SA */ | 1846 | /* RA TA DA SA */ |
1822 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); | 1847 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
@@ -1869,7 +1894,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1869 | if (!ieee80211_vif_is_mesh(&sdata->vif) && | 1894 | if (!ieee80211_vif_is_mesh(&sdata->vif) && |
1870 | unlikely(!is_multicast_ether_addr(hdr.addr1) && | 1895 | unlikely(!is_multicast_ether_addr(hdr.addr1) && |
1871 | !(sta_flags & WLAN_STA_AUTHORIZED) && | 1896 | !(sta_flags & WLAN_STA_AUTHORIZED) && |
1872 | !(ethertype == ETH_P_PAE && | 1897 | !(cpu_to_be16(ethertype) == sdata->control_port_protocol && |
1873 | compare_ether_addr(sdata->vif.addr, | 1898 | compare_ether_addr(sdata->vif.addr, |
1874 | skb->data + ETH_ALEN) == 0))) { | 1899 | skb->data + ETH_ALEN) == 0))) { |
1875 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1900 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -2068,8 +2093,7 @@ void ieee80211_tx_pending(unsigned long data) | |||
2068 | 2093 | ||
2069 | if (skb_queue_empty(&local->pending[i])) | 2094 | if (skb_queue_empty(&local->pending[i])) |
2070 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 2095 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
2071 | netif_tx_wake_queue( | 2096 | netif_wake_subqueue(sdata->dev, i); |
2072 | netdev_get_tx_queue(sdata->dev, i)); | ||
2073 | } | 2097 | } |
2074 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 2098 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
2075 | 2099 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 748387d45bc0..737f4267c335 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -283,8 +283,11 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
283 | 283 | ||
284 | if (skb_queue_empty(&local->pending[queue])) { | 284 | if (skb_queue_empty(&local->pending[queue])) { |
285 | rcu_read_lock(); | 285 | rcu_read_lock(); |
286 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 286 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
287 | netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); | 287 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) |
288 | continue; | ||
289 | netif_wake_subqueue(sdata->dev, queue); | ||
290 | } | ||
288 | rcu_read_unlock(); | 291 | rcu_read_unlock(); |
289 | } else | 292 | } else |
290 | tasklet_schedule(&local->tx_pending_tasklet); | 293 | tasklet_schedule(&local->tx_pending_tasklet); |
@@ -323,7 +326,7 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
323 | 326 | ||
324 | rcu_read_lock(); | 327 | rcu_read_lock(); |
325 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 328 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
326 | netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue)); | 329 | netif_stop_subqueue(sdata->dev, queue); |
327 | rcu_read_unlock(); | 330 | rcu_read_unlock(); |
328 | } | 331 | } |
329 | 332 | ||
@@ -471,16 +474,10 @@ void ieee80211_iterate_active_interfaces( | |||
471 | 474 | ||
472 | list_for_each_entry(sdata, &local->interfaces, list) { | 475 | list_for_each_entry(sdata, &local->interfaces, list) { |
473 | switch (sdata->vif.type) { | 476 | switch (sdata->vif.type) { |
474 | case __NL80211_IFTYPE_AFTER_LAST: | ||
475 | case NL80211_IFTYPE_UNSPECIFIED: | ||
476 | case NL80211_IFTYPE_MONITOR: | 477 | case NL80211_IFTYPE_MONITOR: |
477 | case NL80211_IFTYPE_AP_VLAN: | 478 | case NL80211_IFTYPE_AP_VLAN: |
478 | continue; | 479 | continue; |
479 | case NL80211_IFTYPE_AP: | 480 | default: |
480 | case NL80211_IFTYPE_STATION: | ||
481 | case NL80211_IFTYPE_ADHOC: | ||
482 | case NL80211_IFTYPE_WDS: | ||
483 | case NL80211_IFTYPE_MESH_POINT: | ||
484 | break; | 481 | break; |
485 | } | 482 | } |
486 | if (ieee80211_sdata_running(sdata)) | 483 | if (ieee80211_sdata_running(sdata)) |
@@ -505,16 +502,10 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
505 | 502 | ||
506 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 503 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
507 | switch (sdata->vif.type) { | 504 | switch (sdata->vif.type) { |
508 | case __NL80211_IFTYPE_AFTER_LAST: | ||
509 | case NL80211_IFTYPE_UNSPECIFIED: | ||
510 | case NL80211_IFTYPE_MONITOR: | 505 | case NL80211_IFTYPE_MONITOR: |
511 | case NL80211_IFTYPE_AP_VLAN: | 506 | case NL80211_IFTYPE_AP_VLAN: |
512 | continue; | 507 | continue; |
513 | case NL80211_IFTYPE_AP: | 508 | default: |
514 | case NL80211_IFTYPE_STATION: | ||
515 | case NL80211_IFTYPE_ADHOC: | ||
516 | case NL80211_IFTYPE_WDS: | ||
517 | case NL80211_IFTYPE_MESH_POINT: | ||
518 | break; | 509 | break; |
519 | } | 510 | } |
520 | if (ieee80211_sdata_running(sdata)) | 511 | if (ieee80211_sdata_running(sdata)) |
@@ -1189,7 +1180,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1189 | /* ignore virtual */ | 1180 | /* ignore virtual */ |
1190 | break; | 1181 | break; |
1191 | case NL80211_IFTYPE_UNSPECIFIED: | 1182 | case NL80211_IFTYPE_UNSPECIFIED: |
1192 | case __NL80211_IFTYPE_AFTER_LAST: | 1183 | case NUM_NL80211_IFTYPES: |
1184 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1185 | case NL80211_IFTYPE_P2P_GO: | ||
1193 | WARN_ON(1); | 1186 | WARN_ON(1); |
1194 | break; | 1187 | break; |
1195 | } | 1188 | } |
@@ -1293,9 +1286,9 @@ void ieee80211_recalc_smps(struct ieee80211_local *local, | |||
1293 | int count = 0; | 1286 | int count = 0; |
1294 | 1287 | ||
1295 | if (forsdata) | 1288 | if (forsdata) |
1296 | WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx)); | 1289 | lockdep_assert_held(&forsdata->u.mgd.mtx); |
1297 | 1290 | ||
1298 | WARN_ON(!mutex_is_locked(&local->iflist_mtx)); | 1291 | lockdep_assert_held(&local->iflist_mtx); |
1299 | 1292 | ||
1300 | /* | 1293 | /* |
1301 | * This function could be improved to handle multiple | 1294 | * This function could be improved to handle multiple |
@@ -1308,7 +1301,7 @@ void ieee80211_recalc_smps(struct ieee80211_local *local, | |||
1308 | */ | 1301 | */ |
1309 | 1302 | ||
1310 | list_for_each_entry(sdata, &local->interfaces, list) { | 1303 | list_for_each_entry(sdata, &local->interfaces, list) { |
1311 | if (!netif_running(sdata->dev)) | 1304 | if (!ieee80211_sdata_running(sdata)) |
1312 | continue; | 1305 | continue; |
1313 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1306 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1314 | goto set; | 1307 | goto set; |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 9ebc8d8a1f5b..f27484c22b9f 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -240,7 +240,7 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, | |||
240 | 240 | ||
241 | keyidx = skb->data[hdrlen + 3] >> 6; | 241 | keyidx = skb->data[hdrlen + 3] >> 6; |
242 | 242 | ||
243 | if (!key || keyidx != key->conf.keyidx || key->conf.alg != ALG_WEP) | 243 | if (!key || keyidx != key->conf.keyidx) |
244 | return -1; | 244 | return -1; |
245 | 245 | ||
246 | klen = 3 + key->conf.keylen; | 246 | klen = 3 + key->conf.keylen; |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 81d4ad64184a..ae344d1ba056 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -43,7 +43,7 @@ enum work_action { | |||
43 | /* utils */ | 43 | /* utils */ |
44 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) | 44 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) |
45 | { | 45 | { |
46 | WARN_ON(!mutex_is_locked(&local->work_mtx)); | 46 | lockdep_assert_held(&local->mtx); |
47 | } | 47 | } |
48 | 48 | ||
49 | /* | 49 | /* |
@@ -757,7 +757,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
757 | mgmt = (struct ieee80211_mgmt *) skb->data; | 757 | mgmt = (struct ieee80211_mgmt *) skb->data; |
758 | fc = le16_to_cpu(mgmt->frame_control); | 758 | fc = le16_to_cpu(mgmt->frame_control); |
759 | 759 | ||
760 | mutex_lock(&local->work_mtx); | 760 | mutex_lock(&local->mtx); |
761 | 761 | ||
762 | list_for_each_entry(wk, &local->work_list, list) { | 762 | list_for_each_entry(wk, &local->work_list, list) { |
763 | const u8 *bssid = NULL; | 763 | const u8 *bssid = NULL; |
@@ -833,7 +833,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
833 | WARN(1, "unexpected: %d", rma); | 833 | WARN(1, "unexpected: %d", rma); |
834 | } | 834 | } |
835 | 835 | ||
836 | mutex_unlock(&local->work_mtx); | 836 | mutex_unlock(&local->mtx); |
837 | 837 | ||
838 | if (rma != WORK_ACT_DONE) | 838 | if (rma != WORK_ACT_DONE) |
839 | goto out; | 839 | goto out; |
@@ -845,9 +845,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
845 | case WORK_DONE_REQUEUE: | 845 | case WORK_DONE_REQUEUE: |
846 | synchronize_rcu(); | 846 | synchronize_rcu(); |
847 | wk->started = false; /* restart */ | 847 | wk->started = false; /* restart */ |
848 | mutex_lock(&local->work_mtx); | 848 | mutex_lock(&local->mtx); |
849 | list_add_tail(&wk->list, &local->work_list); | 849 | list_add_tail(&wk->list, &local->work_list); |
850 | mutex_unlock(&local->work_mtx); | 850 | mutex_unlock(&local->mtx); |
851 | } | 851 | } |
852 | 852 | ||
853 | out: | 853 | out: |
@@ -888,9 +888,9 @@ static void ieee80211_work_work(struct work_struct *work) | |||
888 | while ((skb = skb_dequeue(&local->work_skb_queue))) | 888 | while ((skb = skb_dequeue(&local->work_skb_queue))) |
889 | ieee80211_work_rx_queued_mgmt(local, skb); | 889 | ieee80211_work_rx_queued_mgmt(local, skb); |
890 | 890 | ||
891 | ieee80211_recalc_idle(local); | 891 | mutex_lock(&local->mtx); |
892 | 892 | ||
893 | mutex_lock(&local->work_mtx); | 893 | ieee80211_recalc_idle(local); |
894 | 894 | ||
895 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | 895 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { |
896 | bool started = wk->started; | 896 | bool started = wk->started; |
@@ -995,20 +995,16 @@ static void ieee80211_work_work(struct work_struct *work) | |||
995 | run_again(local, jiffies + HZ/2); | 995 | run_again(local, jiffies + HZ/2); |
996 | } | 996 | } |
997 | 997 | ||
998 | mutex_lock(&local->scan_mtx); | ||
999 | |||
1000 | if (list_empty(&local->work_list) && local->scan_req && | 998 | if (list_empty(&local->work_list) && local->scan_req && |
1001 | !local->scanning) | 999 | !local->scanning) |
1002 | ieee80211_queue_delayed_work(&local->hw, | 1000 | ieee80211_queue_delayed_work(&local->hw, |
1003 | &local->scan_work, | 1001 | &local->scan_work, |
1004 | round_jiffies_relative(0)); | 1002 | round_jiffies_relative(0)); |
1005 | 1003 | ||
1006 | mutex_unlock(&local->scan_mtx); | ||
1007 | |||
1008 | mutex_unlock(&local->work_mtx); | ||
1009 | |||
1010 | ieee80211_recalc_idle(local); | 1004 | ieee80211_recalc_idle(local); |
1011 | 1005 | ||
1006 | mutex_unlock(&local->mtx); | ||
1007 | |||
1012 | list_for_each_entry_safe(wk, tmp, &free_work, list) { | 1008 | list_for_each_entry_safe(wk, tmp, &free_work, list) { |
1013 | wk->done(wk, NULL); | 1009 | wk->done(wk, NULL); |
1014 | list_del(&wk->list); | 1010 | list_del(&wk->list); |
@@ -1035,16 +1031,15 @@ void ieee80211_add_work(struct ieee80211_work *wk) | |||
1035 | wk->started = false; | 1031 | wk->started = false; |
1036 | 1032 | ||
1037 | local = wk->sdata->local; | 1033 | local = wk->sdata->local; |
1038 | mutex_lock(&local->work_mtx); | 1034 | mutex_lock(&local->mtx); |
1039 | list_add_tail(&wk->list, &local->work_list); | 1035 | list_add_tail(&wk->list, &local->work_list); |
1040 | mutex_unlock(&local->work_mtx); | 1036 | mutex_unlock(&local->mtx); |
1041 | 1037 | ||
1042 | ieee80211_queue_work(&local->hw, &local->work_work); | 1038 | ieee80211_queue_work(&local->hw, &local->work_work); |
1043 | } | 1039 | } |
1044 | 1040 | ||
1045 | void ieee80211_work_init(struct ieee80211_local *local) | 1041 | void ieee80211_work_init(struct ieee80211_local *local) |
1046 | { | 1042 | { |
1047 | mutex_init(&local->work_mtx); | ||
1048 | INIT_LIST_HEAD(&local->work_list); | 1043 | INIT_LIST_HEAD(&local->work_list); |
1049 | setup_timer(&local->work_timer, ieee80211_work_timer, | 1044 | setup_timer(&local->work_timer, ieee80211_work_timer, |
1050 | (unsigned long)local); | 1045 | (unsigned long)local); |
@@ -1057,7 +1052,7 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | |||
1057 | struct ieee80211_local *local = sdata->local; | 1052 | struct ieee80211_local *local = sdata->local; |
1058 | struct ieee80211_work *wk; | 1053 | struct ieee80211_work *wk; |
1059 | 1054 | ||
1060 | mutex_lock(&local->work_mtx); | 1055 | mutex_lock(&local->mtx); |
1061 | list_for_each_entry(wk, &local->work_list, list) { | 1056 | list_for_each_entry(wk, &local->work_list, list) { |
1062 | if (wk->sdata != sdata) | 1057 | if (wk->sdata != sdata) |
1063 | continue; | 1058 | continue; |
@@ -1065,19 +1060,19 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | |||
1065 | wk->started = true; | 1060 | wk->started = true; |
1066 | wk->timeout = jiffies; | 1061 | wk->timeout = jiffies; |
1067 | } | 1062 | } |
1068 | mutex_unlock(&local->work_mtx); | 1063 | mutex_unlock(&local->mtx); |
1069 | 1064 | ||
1070 | /* run cleanups etc. */ | 1065 | /* run cleanups etc. */ |
1071 | ieee80211_work_work(&local->work_work); | 1066 | ieee80211_work_work(&local->work_work); |
1072 | 1067 | ||
1073 | mutex_lock(&local->work_mtx); | 1068 | mutex_lock(&local->mtx); |
1074 | list_for_each_entry(wk, &local->work_list, list) { | 1069 | list_for_each_entry(wk, &local->work_list, list) { |
1075 | if (wk->sdata != sdata) | 1070 | if (wk->sdata != sdata) |
1076 | continue; | 1071 | continue; |
1077 | WARN_ON(1); | 1072 | WARN_ON(1); |
1078 | break; | 1073 | break; |
1079 | } | 1074 | } |
1080 | mutex_unlock(&local->work_mtx); | 1075 | mutex_unlock(&local->mtx); |
1081 | } | 1076 | } |
1082 | 1077 | ||
1083 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | 1078 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, |
@@ -1163,7 +1158,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | |||
1163 | struct ieee80211_work *wk, *tmp; | 1158 | struct ieee80211_work *wk, *tmp; |
1164 | bool found = false; | 1159 | bool found = false; |
1165 | 1160 | ||
1166 | mutex_lock(&local->work_mtx); | 1161 | mutex_lock(&local->mtx); |
1167 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | 1162 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { |
1168 | if ((unsigned long) wk == cookie) { | 1163 | if ((unsigned long) wk == cookie) { |
1169 | wk->timeout = jiffies; | 1164 | wk->timeout = jiffies; |
@@ -1171,7 +1166,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | |||
1171 | break; | 1166 | break; |
1172 | } | 1167 | } |
1173 | } | 1168 | } |
1174 | mutex_unlock(&local->work_mtx); | 1169 | mutex_unlock(&local->mtx); |
1175 | 1170 | ||
1176 | if (!found) | 1171 | if (!found) |
1177 | return -ENOENT; | 1172 | return -ENOENT; |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 8d59d27d887e..43882b36da55 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -36,8 +36,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
36 | int tail; | 36 | int tail; |
37 | 37 | ||
38 | hdr = (struct ieee80211_hdr *)skb->data; | 38 | hdr = (struct ieee80211_hdr *)skb->data; |
39 | if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 || | 39 | if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || |
40 | !ieee80211_is_data_present(hdr->frame_control)) | 40 | skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control)) |
41 | return TX_CONTINUE; | 41 | return TX_CONTINUE; |
42 | 42 | ||
43 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 43 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
@@ -94,7 +94,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
94 | if (status->flag & RX_FLAG_MMIC_STRIPPED) | 94 | if (status->flag & RX_FLAG_MMIC_STRIPPED) |
95 | return RX_CONTINUE; | 95 | return RX_CONTINUE; |
96 | 96 | ||
97 | if (!rx->key || rx->key->conf.alg != ALG_TKIP || | 97 | if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || |
98 | !ieee80211_has_protected(hdr->frame_control) || | 98 | !ieee80211_has_protected(hdr->frame_control) || |
99 | !ieee80211_is_data_present(hdr->frame_control)) | 99 | !ieee80211_is_data_present(hdr->frame_control)) |
100 | return RX_CONTINUE; | 100 | return RX_CONTINUE; |
@@ -221,19 +221,13 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
221 | if (!rx->sta || skb->len - hdrlen < 12) | 221 | if (!rx->sta || skb->len - hdrlen < 12) |
222 | return RX_DROP_UNUSABLE; | 222 | return RX_DROP_UNUSABLE; |
223 | 223 | ||
224 | if (status->flag & RX_FLAG_DECRYPTED) { | 224 | /* |
225 | if (status->flag & RX_FLAG_IV_STRIPPED) { | 225 | * Let TKIP code verify IV, but skip decryption. |
226 | /* | 226 | * In the case where hardware checks the IV as well, |
227 | * Hardware took care of all processing, including | 227 | * we don't even get here, see ieee80211_rx_h_decrypt() |
228 | * replay protection, and stripped the ICV/IV so | 228 | */ |
229 | * we cannot do any checks here. | 229 | if (status->flag & RX_FLAG_DECRYPTED) |
230 | */ | ||
231 | return RX_CONTINUE; | ||
232 | } | ||
233 | |||
234 | /* let TKIP code verify IV, but skip decryption */ | ||
235 | hwaccel = 1; | 230 | hwaccel = 1; |
236 | } | ||
237 | 231 | ||
238 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, | 232 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, |
239 | key, skb->data + hdrlen, | 233 | key, skb->data + hdrlen, |
@@ -447,10 +441,6 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
447 | if (!rx->sta || data_len < 0) | 441 | if (!rx->sta || data_len < 0) |
448 | return RX_DROP_UNUSABLE; | 442 | return RX_DROP_UNUSABLE; |
449 | 443 | ||
450 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
451 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
452 | return RX_CONTINUE; | ||
453 | |||
454 | ccmp_hdr2pn(pn, skb->data + hdrlen); | 444 | ccmp_hdr2pn(pn, skb->data + hdrlen); |
455 | 445 | ||
456 | queue = ieee80211_is_mgmt(hdr->frame_control) ? | 446 | queue = ieee80211_is_mgmt(hdr->frame_control) ? |
@@ -564,10 +554,6 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | |||
564 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 554 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
565 | return RX_CONTINUE; | 555 | return RX_CONTINUE; |
566 | 556 | ||
567 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
568 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
569 | return RX_CONTINUE; | ||
570 | |||
571 | if (skb->len < 24 + sizeof(*mmie)) | 557 | if (skb->len < 24 + sizeof(*mmie)) |
572 | return RX_DROP_UNUSABLE; | 558 | return RX_DROP_UNUSABLE; |
573 | 559 | ||