diff options
author | David S. Miller <davem@davemloft.net> | 2009-05-08 15:46:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-08 15:46:17 -0400 |
commit | a8679be2073392cf22a910bc25da0c7d36459845 (patch) | |
tree | 0d25750ea4ba3a85fe683f285261083d77080976 /net | |
parent | 22f6dacdfcfdc792d068e9c41234808860498d04 (diff) | |
parent | 9dfd6ba353b993d648dcda72480c7ce92cd27c7e (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/agg-rx.c | 19 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 13 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 49 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 20 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 184 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 102 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 14 | ||||
-rw-r--r-- | net/mac80211/iface.c | 100 | ||||
-rw-r--r-- | net/mac80211/key.c | 8 | ||||
-rw-r--r-- | net/mac80211/main.c | 165 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 6 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 74 | ||||
-rw-r--r-- | net/mac80211/pm.c | 9 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.c | 8 | ||||
-rw-r--r-- | net/mac80211/rc80211_pid_algo.c | 8 | ||||
-rw-r--r-- | net/mac80211/rx.c | 138 | ||||
-rw-r--r-- | net/mac80211/scan.c | 414 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 26 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/tkip.c | 6 | ||||
-rw-r--r-- | net/mac80211/tx.c | 9 | ||||
-rw-r--r-- | net/mac80211/util.c | 31 | ||||
-rw-r--r-- | net/mac80211/wext.c | 2 | ||||
-rw-r--r-- | net/rfkill/rfkill.c | 5 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 6 | ||||
-rw-r--r-- | net/wireless/reg.c | 8 | ||||
-rw-r--r-- | net/wireless/scan.c | 10 |
27 files changed, 876 insertions, 560 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 07656d830bc4..bc064d7933ff 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -16,12 +16,12 @@ | |||
16 | #include <linux/ieee80211.h> | 16 | #include <linux/ieee80211.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
19 | #include "driver-ops.h" | ||
19 | 20 | ||
20 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 21 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
21 | u16 initiator, u16 reason) | 22 | u16 initiator, u16 reason) |
22 | { | 23 | { |
23 | struct ieee80211_local *local = sta->local; | 24 | struct ieee80211_local *local = sta->local; |
24 | struct ieee80211_hw *hw = &local->hw; | ||
25 | int i; | 25 | int i; |
26 | 26 | ||
27 | /* check if TID is in operational state */ | 27 | /* check if TID is in operational state */ |
@@ -41,8 +41,8 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
41 | sta->sta.addr, tid); | 41 | sta->sta.addr, tid); |
42 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 42 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
43 | 43 | ||
44 | if (local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, | 44 | if (drv_ampdu_action(local, IEEE80211_AMPDU_RX_STOP, |
45 | &sta->sta, tid, NULL)) | 45 | &sta->sta, tid, NULL)) |
46 | printk(KERN_DEBUG "HW problem - can not stop rx " | 46 | printk(KERN_DEBUG "HW problem - can not stop rx " |
47 | "aggregation for tid %d\n", tid); | 47 | "aggregation for tid %d\n", tid); |
48 | 48 | ||
@@ -68,6 +68,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
68 | spin_lock_bh(&sta->lock); | 68 | spin_lock_bh(&sta->lock); |
69 | /* free resources */ | 69 | /* free resources */ |
70 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | 70 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); |
71 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time); | ||
71 | 72 | ||
72 | if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { | 73 | if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { |
73 | kfree(sta->ampdu_mlme.tid_rx[tid]); | 74 | kfree(sta->ampdu_mlme.tid_rx[tid]); |
@@ -268,19 +269,23 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
268 | /* prepare reordering buffer */ | 269 | /* prepare reordering buffer */ |
269 | tid_agg_rx->reorder_buf = | 270 | tid_agg_rx->reorder_buf = |
270 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); | 271 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); |
271 | if (!tid_agg_rx->reorder_buf) { | 272 | tid_agg_rx->reorder_time = |
273 | kcalloc(buf_size, sizeof(unsigned long), GFP_ATOMIC); | ||
274 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { | ||
272 | #ifdef CONFIG_MAC80211_HT_DEBUG | 275 | #ifdef CONFIG_MAC80211_HT_DEBUG |
273 | if (net_ratelimit()) | 276 | if (net_ratelimit()) |
274 | printk(KERN_ERR "can not allocate reordering buffer " | 277 | printk(KERN_ERR "can not allocate reordering buffer " |
275 | "to tid %d\n", tid); | 278 | "to tid %d\n", tid); |
276 | #endif | 279 | #endif |
280 | kfree(tid_agg_rx->reorder_buf); | ||
281 | kfree(tid_agg_rx->reorder_time); | ||
277 | kfree(sta->ampdu_mlme.tid_rx[tid]); | 282 | kfree(sta->ampdu_mlme.tid_rx[tid]); |
283 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
278 | goto end; | 284 | goto end; |
279 | } | 285 | } |
280 | 286 | ||
281 | if (local->ops->ampdu_action) | 287 | ret = drv_ampdu_action(local, IEEE80211_AMPDU_RX_START, |
282 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, | 288 | &sta->sta, tid, &start_seq_num); |
283 | &sta->sta, tid, &start_seq_num); | ||
284 | #ifdef CONFIG_MAC80211_HT_DEBUG | 289 | #ifdef CONFIG_MAC80211_HT_DEBUG |
285 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | 290 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); |
286 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 291 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 947aaaad35d2..43d00ffd3988 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/ieee80211.h> | 16 | #include <linux/ieee80211.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
19 | #include "driver-ops.h" | ||
19 | #include "wme.h" | 20 | #include "wme.h" |
20 | 21 | ||
21 | /** | 22 | /** |
@@ -134,8 +135,8 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
134 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | 135 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | |
135 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 136 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
136 | 137 | ||
137 | ret = local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_STOP, | 138 | ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_STOP, |
138 | &sta->sta, tid, NULL); | 139 | &sta->sta, tid, NULL); |
139 | 140 | ||
140 | /* HW shall not deny going back to legacy */ | 141 | /* HW shall not deny going back to legacy */ |
141 | if (WARN_ON(ret)) { | 142 | if (WARN_ON(ret)) { |
@@ -306,8 +307,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
306 | 307 | ||
307 | start_seq_num = sta->tid_seq[tid]; | 308 | start_seq_num = sta->tid_seq[tid]; |
308 | 309 | ||
309 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, | 310 | ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_START, |
310 | &sta->sta, tid, &start_seq_num); | 311 | &sta->sta, tid, &start_seq_num); |
311 | 312 | ||
312 | if (ret) { | 313 | if (ret) { |
313 | #ifdef CONFIG_MAC80211_HT_DEBUG | 314 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -418,8 +419,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
418 | ieee80211_agg_splice_finish(local, sta, tid); | 419 | ieee80211_agg_splice_finish(local, sta, tid); |
419 | spin_unlock(&local->ampdu_lock); | 420 | spin_unlock(&local->ampdu_lock); |
420 | 421 | ||
421 | local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_OPERATIONAL, | 422 | drv_ampdu_action(local, IEEE80211_AMPDU_TX_OPERATIONAL, |
422 | &sta->sta, tid, NULL); | 423 | &sta->sta, tid, NULL); |
423 | } | 424 | } |
424 | 425 | ||
425 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | 426 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5e1c230744b5..d0ca6da33ca9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/rcupdate.h> | 13 | #include <linux/rcupdate.h> |
14 | #include <net/cfg80211.h> | 14 | #include <net/cfg80211.h> |
15 | #include "ieee80211_i.h" | 15 | #include "ieee80211_i.h" |
16 | #include "driver-ops.h" | ||
16 | #include "cfg.h" | 17 | #include "cfg.h" |
17 | #include "rate.h" | 18 | #include "rate.h" |
18 | #include "mesh.h" | 19 | #include "mesh.h" |
@@ -245,12 +246,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
245 | iv32 = key->u.tkip.tx.iv32; | 246 | iv32 = key->u.tkip.tx.iv32; |
246 | iv16 = key->u.tkip.tx.iv16; | 247 | iv16 = key->u.tkip.tx.iv16; |
247 | 248 | ||
248 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && | 249 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
249 | sdata->local->ops->get_tkip_seq) | 250 | drv_get_tkip_seq(sdata->local, |
250 | sdata->local->ops->get_tkip_seq( | 251 | key->conf.hw_key_idx, |
251 | local_to_hw(sdata->local), | 252 | &iv32, &iv16); |
252 | key->conf.hw_key_idx, | ||
253 | &iv32, &iv16); | ||
254 | 253 | ||
255 | seq[0] = iv16 & 0xff; | 254 | seq[0] = iv16 & 0xff; |
256 | seq[1] = (iv16 >> 8) & 0xff; | 255 | seq[1] = (iv16 >> 8) & 0xff; |
@@ -451,18 +450,11 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
451 | * This is a kludge. beacon interval should really be part | 450 | * This is a kludge. beacon interval should really be part |
452 | * of the beacon information. | 451 | * of the beacon information. |
453 | */ | 452 | */ |
454 | if (params->interval && (sdata->local->hw.conf.beacon_int != | 453 | if (params->interval && |
455 | params->interval)) { | 454 | (sdata->vif.bss_conf.beacon_int != params->interval)) { |
456 | sdata->local->hw.conf.beacon_int = params->interval; | 455 | sdata->vif.bss_conf.beacon_int = params->interval; |
457 | err = ieee80211_hw_config(sdata->local, | 456 | ieee80211_bss_info_change_notify(sdata, |
458 | IEEE80211_CONF_CHANGE_BEACON_INTERVAL); | 457 | BSS_CHANGED_BEACON_INT); |
459 | if (err < 0) | ||
460 | return err; | ||
461 | /* | ||
462 | * We updated some parameter so if below bails out | ||
463 | * it's not an error. | ||
464 | */ | ||
465 | err = 0; | ||
466 | } | 458 | } |
467 | 459 | ||
468 | /* Need to have a beacon head if we don't have one yet */ | 460 | /* Need to have a beacon head if we don't have one yet */ |
@@ -528,8 +520,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
528 | 520 | ||
529 | kfree(old); | 521 | kfree(old); |
530 | 522 | ||
531 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | | 523 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | |
532 | IEEE80211_IFCC_BEACON_ENABLED); | 524 | BSS_CHANGED_BEACON); |
525 | return 0; | ||
533 | } | 526 | } |
534 | 527 | ||
535 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 528 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
@@ -580,7 +573,8 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
580 | synchronize_rcu(); | 573 | synchronize_rcu(); |
581 | kfree(old); | 574 | kfree(old); |
582 | 575 | ||
583 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); | 576 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
577 | return 0; | ||
584 | } | 578 | } |
585 | 579 | ||
586 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ | 580 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ |
@@ -1120,7 +1114,7 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1120 | p.cw_max = params->cwmax; | 1114 | p.cw_max = params->cwmax; |
1121 | p.cw_min = params->cwmin; | 1115 | p.cw_min = params->cwmin; |
1122 | p.txop = params->txop; | 1116 | p.txop = params->txop; |
1123 | if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) { | 1117 | if (drv_conf_tx(local, params->queue, &p)) { |
1124 | printk(KERN_DEBUG "%s: failed to set TX queue " | 1118 | printk(KERN_DEBUG "%s: failed to set TX queue " |
1125 | "parameters for queue %d\n", local->mdev->name, | 1119 | "parameters for queue %d\n", local->mdev->name, |
1126 | params->queue); | 1120 | params->queue); |
@@ -1301,16 +1295,13 @@ static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
1301 | static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | 1295 | static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) |
1302 | { | 1296 | { |
1303 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1297 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1298 | int err; | ||
1304 | 1299 | ||
1305 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | 1300 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { |
1306 | int err; | 1301 | err = drv_set_rts_threshold(local, wiphy->rts_threshold); |
1307 | 1302 | ||
1308 | if (local->ops->set_rts_threshold) { | 1303 | if (err) |
1309 | err = local->ops->set_rts_threshold( | 1304 | return err; |
1310 | local_to_hw(local), wiphy->rts_threshold); | ||
1311 | if (err) | ||
1312 | return err; | ||
1313 | } | ||
1314 | } | 1305 | } |
1315 | 1306 | ||
1316 | if (changed & WIPHY_PARAM_RETRY_SHORT) | 1307 | if (changed & WIPHY_PARAM_RETRY_SHORT) |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 5001328be46b..ac793201b701 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/debugfs.h> | 10 | #include <linux/debugfs.h> |
11 | #include <linux/rtnetlink.h> | 11 | #include <linux/rtnetlink.h> |
12 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
13 | #include "driver-ops.h" | ||
13 | #include "rate.h" | 14 | #include "rate.h" |
14 | #include "debugfs.h" | 15 | #include "debugfs.h" |
15 | 16 | ||
@@ -70,11 +71,10 @@ static ssize_t tsf_read(struct file *file, char __user *user_buf, | |||
70 | size_t count, loff_t *ppos) | 71 | size_t count, loff_t *ppos) |
71 | { | 72 | { |
72 | struct ieee80211_local *local = file->private_data; | 73 | struct ieee80211_local *local = file->private_data; |
73 | u64 tsf = 0; | 74 | u64 tsf; |
74 | char buf[100]; | 75 | char buf[100]; |
75 | 76 | ||
76 | if (local->ops->get_tsf) | 77 | tsf = drv_get_tsf(local); |
77 | tsf = local->ops->get_tsf(local_to_hw(local)); | ||
78 | 78 | ||
79 | snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf); | 79 | snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf); |
80 | 80 | ||
@@ -97,13 +97,13 @@ static ssize_t tsf_write(struct file *file, | |||
97 | 97 | ||
98 | if (strncmp(buf, "reset", 5) == 0) { | 98 | if (strncmp(buf, "reset", 5) == 0) { |
99 | if (local->ops->reset_tsf) { | 99 | if (local->ops->reset_tsf) { |
100 | local->ops->reset_tsf(local_to_hw(local)); | 100 | drv_reset_tsf(local); |
101 | printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy)); | 101 | printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy)); |
102 | } | 102 | } |
103 | } else { | 103 | } else { |
104 | tsf = simple_strtoul(buf, NULL, 0); | 104 | tsf = simple_strtoul(buf, NULL, 0); |
105 | if (local->ops->set_tsf) { | 105 | if (local->ops->set_tsf) { |
106 | local->ops->set_tsf(local_to_hw(local), tsf); | 106 | drv_set_tsf(local, tsf); |
107 | printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf); | 107 | printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf); |
108 | } | 108 | } |
109 | } | 109 | } |
@@ -150,14 +150,12 @@ static ssize_t format_devstat_counter(struct ieee80211_local *local, | |||
150 | char buf[20]; | 150 | char buf[20]; |
151 | int res; | 151 | int res; |
152 | 152 | ||
153 | if (!local->ops->get_stats) | ||
154 | return -EOPNOTSUPP; | ||
155 | |||
156 | rtnl_lock(); | 153 | rtnl_lock(); |
157 | res = local->ops->get_stats(local_to_hw(local), &stats); | 154 | res = drv_get_stats(local, &stats); |
158 | rtnl_unlock(); | 155 | rtnl_unlock(); |
159 | if (!res) | 156 | if (res) |
160 | res = printvalue(&stats, buf, sizeof(buf)); | 157 | return res; |
158 | res = printvalue(&stats, buf, sizeof(buf)); | ||
161 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 159 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
162 | } | 160 | } |
163 | 161 | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h new file mode 100644 index 000000000000..3912b5334b9c --- /dev/null +++ b/net/mac80211/driver-ops.h | |||
@@ -0,0 +1,184 @@ | |||
1 | #ifndef __MAC80211_DRIVER_OPS | ||
2 | #define __MAC80211_DRIVER_OPS | ||
3 | |||
4 | #include <net/mac80211.h> | ||
5 | #include "ieee80211_i.h" | ||
6 | |||
7 | static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb) | ||
8 | { | ||
9 | return local->ops->tx(&local->hw, skb); | ||
10 | } | ||
11 | |||
12 | static inline int drv_start(struct ieee80211_local *local) | ||
13 | { | ||
14 | return local->ops->start(&local->hw); | ||
15 | } | ||
16 | |||
17 | static inline void drv_stop(struct ieee80211_local *local) | ||
18 | { | ||
19 | local->ops->stop(&local->hw); | ||
20 | } | ||
21 | |||
22 | static inline int drv_add_interface(struct ieee80211_local *local, | ||
23 | struct ieee80211_if_init_conf *conf) | ||
24 | { | ||
25 | return local->ops->add_interface(&local->hw, conf); | ||
26 | } | ||
27 | |||
28 | static inline void drv_remove_interface(struct ieee80211_local *local, | ||
29 | struct ieee80211_if_init_conf *conf) | ||
30 | { | ||
31 | local->ops->remove_interface(&local->hw, conf); | ||
32 | } | ||
33 | |||
34 | static inline int drv_config(struct ieee80211_local *local, u32 changed) | ||
35 | { | ||
36 | return local->ops->config(&local->hw, changed); | ||
37 | } | ||
38 | |||
39 | static inline void drv_bss_info_changed(struct ieee80211_local *local, | ||
40 | struct ieee80211_vif *vif, | ||
41 | struct ieee80211_bss_conf *info, | ||
42 | u32 changed) | ||
43 | { | ||
44 | if (local->ops->bss_info_changed) | ||
45 | local->ops->bss_info_changed(&local->hw, vif, info, changed); | ||
46 | } | ||
47 | |||
48 | static inline void drv_configure_filter(struct ieee80211_local *local, | ||
49 | unsigned int changed_flags, | ||
50 | unsigned int *total_flags, | ||
51 | int mc_count, | ||
52 | struct dev_addr_list *mc_list) | ||
53 | { | ||
54 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, | ||
55 | mc_count, mc_list); | ||
56 | } | ||
57 | |||
58 | static inline int drv_set_tim(struct ieee80211_local *local, | ||
59 | struct ieee80211_sta *sta, bool set) | ||
60 | { | ||
61 | if (local->ops->set_tim) | ||
62 | return local->ops->set_tim(&local->hw, sta, set); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static inline int drv_set_key(struct ieee80211_local *local, | ||
67 | enum set_key_cmd cmd, struct ieee80211_vif *vif, | ||
68 | struct ieee80211_sta *sta, | ||
69 | struct ieee80211_key_conf *key) | ||
70 | { | ||
71 | return local->ops->set_key(&local->hw, cmd, vif, sta, key); | ||
72 | } | ||
73 | |||
74 | static inline void drv_update_tkip_key(struct ieee80211_local *local, | ||
75 | struct ieee80211_key_conf *conf, | ||
76 | const u8 *address, u32 iv32, | ||
77 | u16 *phase1key) | ||
78 | { | ||
79 | if (local->ops->update_tkip_key) | ||
80 | local->ops->update_tkip_key(&local->hw, conf, address, | ||
81 | iv32, phase1key); | ||
82 | } | ||
83 | |||
84 | static inline int drv_hw_scan(struct ieee80211_local *local, | ||
85 | struct cfg80211_scan_request *req) | ||
86 | { | ||
87 | return local->ops->hw_scan(&local->hw, req); | ||
88 | } | ||
89 | |||
90 | static inline void drv_sw_scan_start(struct ieee80211_local *local) | ||
91 | { | ||
92 | if (local->ops->sw_scan_start) | ||
93 | local->ops->sw_scan_start(&local->hw); | ||
94 | } | ||
95 | |||
96 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) | ||
97 | { | ||
98 | if (local->ops->sw_scan_complete) | ||
99 | local->ops->sw_scan_complete(&local->hw); | ||
100 | } | ||
101 | |||
102 | static inline int drv_get_stats(struct ieee80211_local *local, | ||
103 | struct ieee80211_low_level_stats *stats) | ||
104 | { | ||
105 | if (!local->ops->get_stats) | ||
106 | return -EOPNOTSUPP; | ||
107 | return local->ops->get_stats(&local->hw, stats); | ||
108 | } | ||
109 | |||
110 | static inline void drv_get_tkip_seq(struct ieee80211_local *local, | ||
111 | u8 hw_key_idx, u32 *iv32, u16 *iv16) | ||
112 | { | ||
113 | if (local->ops->get_tkip_seq) | ||
114 | local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16); | ||
115 | } | ||
116 | |||
117 | static inline int drv_set_rts_threshold(struct ieee80211_local *local, | ||
118 | u32 value) | ||
119 | { | ||
120 | if (local->ops->set_rts_threshold) | ||
121 | return local->ops->set_rts_threshold(&local->hw, value); | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static inline void drv_sta_notify(struct ieee80211_local *local, | ||
126 | struct ieee80211_vif *vif, | ||
127 | enum sta_notify_cmd cmd, | ||
128 | struct ieee80211_sta *sta) | ||
129 | { | ||
130 | if (local->ops->sta_notify) | ||
131 | local->ops->sta_notify(&local->hw, vif, cmd, sta); | ||
132 | } | ||
133 | |||
134 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | ||
135 | const struct ieee80211_tx_queue_params *params) | ||
136 | { | ||
137 | if (local->ops->conf_tx) | ||
138 | return local->ops->conf_tx(&local->hw, queue, params); | ||
139 | return -EOPNOTSUPP; | ||
140 | } | ||
141 | |||
142 | static inline int drv_get_tx_stats(struct ieee80211_local *local, | ||
143 | struct ieee80211_tx_queue_stats *stats) | ||
144 | { | ||
145 | return local->ops->get_tx_stats(&local->hw, stats); | ||
146 | } | ||
147 | |||
148 | static inline u64 drv_get_tsf(struct ieee80211_local *local) | ||
149 | { | ||
150 | if (local->ops->get_tsf) | ||
151 | return local->ops->get_tsf(&local->hw); | ||
152 | return -1ULL; | ||
153 | } | ||
154 | |||
155 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | ||
156 | { | ||
157 | if (local->ops->set_tsf) | ||
158 | local->ops->set_tsf(&local->hw, tsf); | ||
159 | } | ||
160 | |||
161 | static inline void drv_reset_tsf(struct ieee80211_local *local) | ||
162 | { | ||
163 | if (local->ops->reset_tsf) | ||
164 | local->ops->reset_tsf(&local->hw); | ||
165 | } | ||
166 | |||
167 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | ||
168 | { | ||
169 | if (local->ops->tx_last_beacon) | ||
170 | return local->ops->tx_last_beacon(&local->hw); | ||
171 | return 1; | ||
172 | } | ||
173 | |||
174 | static inline int drv_ampdu_action(struct ieee80211_local *local, | ||
175 | enum ieee80211_ampdu_mlme_action action, | ||
176 | struct ieee80211_sta *sta, u16 tid, | ||
177 | u16 *ssn) | ||
178 | { | ||
179 | if (local->ops->ampdu_action) | ||
180 | return local->ops->ampdu_action(&local->hw, action, | ||
181 | sta, tid, ssn); | ||
182 | return -EOPNOTSUPP; | ||
183 | } | ||
184 | #endif /* __MAC80211_DRIVER_OPS */ | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 6030e003180c..aa537681f87c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/unaligned.h> | 22 | #include <asm/unaligned.h> |
23 | 23 | ||
24 | #include "ieee80211_i.h" | 24 | #include "ieee80211_i.h" |
25 | #include "driver-ops.h" | ||
25 | #include "rate.h" | 26 | #include "rate.h" |
26 | 27 | ||
27 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) | 28 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) |
@@ -73,11 +74,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
73 | struct ieee80211_mgmt *mgmt; | 74 | struct ieee80211_mgmt *mgmt; |
74 | u8 *pos; | 75 | u8 *pos; |
75 | struct ieee80211_supported_band *sband; | 76 | struct ieee80211_supported_band *sband; |
77 | u32 bss_change; | ||
76 | 78 | ||
77 | if (local->ops->reset_tsf) { | 79 | |
78 | /* Reset own TSF to allow time synchronization work. */ | 80 | /* Reset own TSF to allow time synchronization work. */ |
79 | local->ops->reset_tsf(local_to_hw(local)); | 81 | drv_reset_tsf(local); |
80 | } | ||
81 | 82 | ||
82 | skb = ifibss->skb; | 83 | skb = ifibss->skb; |
83 | rcu_assign_pointer(ifibss->presp, NULL); | 84 | rcu_assign_pointer(ifibss->presp, NULL); |
@@ -92,15 +93,12 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
92 | 93 | ||
93 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | 94 | memcpy(ifibss->bssid, bssid, ETH_ALEN); |
94 | 95 | ||
95 | local->hw.conf.beacon_int = beacon_int >= 10 ? beacon_int : 10; | ||
96 | |||
97 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 96 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
98 | 97 | ||
99 | ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); | ||
100 | |||
101 | local->oper_channel = chan; | 98 | local->oper_channel = chan; |
102 | local->oper_channel_type = NL80211_CHAN_NO_HT; | 99 | local->oper_channel_type = NL80211_CHAN_NO_HT; |
103 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 100 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
101 | |||
104 | sband = local->hw.wiphy->bands[chan->band]; | 102 | sband = local->hw.wiphy->bands[chan->band]; |
105 | 103 | ||
106 | /* Build IBSS probe response */ | 104 | /* Build IBSS probe response */ |
@@ -111,7 +109,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
111 | memset(mgmt->da, 0xff, ETH_ALEN); | 109 | memset(mgmt->da, 0xff, ETH_ALEN); |
112 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 110 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
113 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); | 111 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); |
114 | mgmt->u.beacon.beacon_int = cpu_to_le16(local->hw.conf.beacon_int); | 112 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); |
115 | mgmt->u.beacon.timestamp = cpu_to_le64(tsf); | 113 | mgmt->u.beacon.timestamp = cpu_to_le64(tsf); |
116 | mgmt->u.beacon.capab_info = cpu_to_le16(capability); | 114 | mgmt->u.beacon.capab_info = cpu_to_le16(capability); |
117 | 115 | ||
@@ -156,8 +154,13 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
156 | 154 | ||
157 | rcu_assign_pointer(ifibss->presp, skb); | 155 | rcu_assign_pointer(ifibss->presp, skb); |
158 | 156 | ||
159 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | | 157 | sdata->vif.bss_conf.beacon_int = beacon_int; |
160 | IEEE80211_IFCC_BEACON_ENABLED); | 158 | bss_change = BSS_CHANGED_BEACON_INT; |
159 | bss_change |= ieee80211_reset_erp_info(sdata); | ||
160 | bss_change |= BSS_CHANGED_BSSID; | ||
161 | bss_change |= BSS_CHANGED_BEACON; | ||
162 | bss_change |= BSS_CHANGED_BEACON_ENABLED; | ||
163 | ieee80211_bss_info_change_notify(sdata, bss_change); | ||
161 | 164 | ||
162 | rates = 0; | 165 | rates = 0; |
163 | for (i = 0; i < supp_rates_len; i++) { | 166 | for (i = 0; i < supp_rates_len; i++) { |
@@ -181,8 +184,13 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
181 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 184 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
182 | struct ieee80211_bss *bss) | 185 | struct ieee80211_bss *bss) |
183 | { | 186 | { |
187 | u16 beacon_int = bss->cbss.beacon_interval; | ||
188 | |||
189 | if (beacon_int < 10) | ||
190 | beacon_int = 10; | ||
191 | |||
184 | __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, | 192 | __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, |
185 | bss->cbss.beacon_interval, | 193 | beacon_int, |
186 | bss->cbss.channel, | 194 | bss->cbss.channel, |
187 | bss->supp_rates_len, bss->supp_rates, | 195 | bss->supp_rates_len, bss->supp_rates, |
188 | bss->cbss.capability, | 196 | bss->cbss.capability, |
@@ -307,12 +315,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
307 | bitrates[rx_status->rate_idx].bitrate; | 315 | bitrates[rx_status->rate_idx].bitrate; |
308 | 316 | ||
309 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); | 317 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); |
310 | } else if (local && local->ops && local->ops->get_tsf) | 318 | } else { |
311 | /* second best option: get current TSF */ | 319 | /* |
312 | rx_timestamp = local->ops->get_tsf(local_to_hw(local)); | 320 | * second best option: get current TSF |
313 | else | 321 | * (will return -1 if not supported) |
314 | /* can't merge without knowing the TSF */ | 322 | */ |
315 | rx_timestamp = -1LLU; | 323 | rx_timestamp = drv_get_tsf(local); |
324 | } | ||
316 | 325 | ||
317 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 326 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
318 | printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" | 327 | printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" |
@@ -432,14 +441,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
432 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 441 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " |
433 | "IBSS networks with same SSID (merge)\n", sdata->dev->name); | 442 | "IBSS networks with same SSID (merge)\n", sdata->dev->name); |
434 | 443 | ||
435 | /* XXX maybe racy? */ | 444 | ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); |
436 | if (sdata->local->scan_req) | ||
437 | return; | ||
438 | |||
439 | memcpy(sdata->local->int_scan_req.ssids[0].ssid, | ||
440 | ifibss->ssid, IEEE80211_MAX_SSID_LEN); | ||
441 | sdata->local->int_scan_req.ssids[0].ssid_len = ifibss->ssid_len; | ||
442 | ieee80211_request_scan(sdata, &sdata->local->int_scan_req); | ||
443 | } | 445 | } |
444 | 446 | ||
445 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 447 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -471,9 +473,6 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
471 | 473 | ||
472 | sband = local->hw.wiphy->bands[ifibss->channel->band]; | 474 | sband = local->hw.wiphy->bands[ifibss->channel->band]; |
473 | 475 | ||
474 | if (local->hw.conf.beacon_int == 0) | ||
475 | local->hw.conf.beacon_int = 100; | ||
476 | |||
477 | capability = WLAN_CAPABILITY_IBSS; | 476 | capability = WLAN_CAPABILITY_IBSS; |
478 | 477 | ||
479 | if (sdata->default_key) | 478 | if (sdata->default_key) |
@@ -487,7 +486,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
487 | *pos++ = (u8) (rate / 5); | 486 | *pos++ = (u8) (rate / 5); |
488 | } | 487 | } |
489 | 488 | ||
490 | __ieee80211_sta_join_ibss(sdata, bssid, local->hw.conf.beacon_int, | 489 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, |
491 | ifibss->channel, sband->n_bitrates, | 490 | ifibss->channel, sband->n_bitrates, |
492 | supp_rates, capability, 0); | 491 | supp_rates, capability, 0); |
493 | } | 492 | } |
@@ -552,15 +551,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
552 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 551 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " |
553 | "join\n", sdata->dev->name); | 552 | "join\n", sdata->dev->name); |
554 | 553 | ||
555 | /* XXX maybe racy? */ | 554 | ieee80211_request_internal_scan(sdata, ifibss->ssid, |
556 | if (local->scan_req) | 555 | ifibss->ssid_len); |
557 | return; | ||
558 | |||
559 | memcpy(local->int_scan_req.ssids[0].ssid, | ||
560 | ifibss->ssid, IEEE80211_MAX_SSID_LEN); | ||
561 | local->int_scan_req.ssids[0].ssid_len = | ||
562 | ifibss->ssid_len; | ||
563 | ieee80211_request_scan(sdata, &local->int_scan_req); | ||
564 | } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { | 556 | } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { |
565 | int interval = IEEE80211_SCAN_INTERVAL; | 557 | int interval = IEEE80211_SCAN_INTERVAL; |
566 | 558 | ||
@@ -600,10 +592,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
600 | len < 24 + 2 || !ifibss->presp) | 592 | len < 24 + 2 || !ifibss->presp) |
601 | return; | 593 | return; |
602 | 594 | ||
603 | if (local->ops->tx_last_beacon) | 595 | tx_last_beacon = drv_tx_last_beacon(local); |
604 | tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local)); | ||
605 | else | ||
606 | tx_last_beacon = 1; | ||
607 | 596 | ||
608 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 597 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
609 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" | 598 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" |
@@ -786,8 +775,12 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) | |||
786 | 775 | ||
787 | mutex_lock(&local->iflist_mtx); | 776 | mutex_lock(&local->iflist_mtx); |
788 | list_for_each_entry(sdata, &local->interfaces, list) { | 777 | list_for_each_entry(sdata, &local->interfaces, list) { |
778 | if (!netif_running(sdata->dev)) | ||
779 | continue; | ||
789 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 780 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
790 | continue; | 781 | continue; |
782 | if (!sdata->u.ibss.ssid_len) | ||
783 | continue; | ||
791 | sdata->u.ibss.last_scan_completed = jiffies; | 784 | sdata->u.ibss.last_scan_completed = jiffies; |
792 | ieee80211_sta_find_ibss(sdata); | 785 | ieee80211_sta_find_ibss(sdata); |
793 | } | 786 | } |
@@ -827,15 +820,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
827 | { | 820 | { |
828 | struct sk_buff *skb; | 821 | struct sk_buff *skb; |
829 | 822 | ||
830 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | ||
831 | sdata->u.ibss.ssid_len = params->ssid_len; | ||
832 | |||
833 | if (params->bssid) { | 823 | if (params->bssid) { |
834 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); | 824 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); |
835 | sdata->u.ibss.fixed_bssid = true; | 825 | sdata->u.ibss.fixed_bssid = true; |
836 | } else | 826 | } else |
837 | sdata->u.ibss.fixed_bssid = false; | 827 | sdata->u.ibss.fixed_bssid = false; |
838 | 828 | ||
829 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | ||
830 | |||
839 | sdata->u.ibss.channel = params->channel; | 831 | sdata->u.ibss.channel = params->channel; |
840 | sdata->u.ibss.fixed_channel = params->channel_fixed; | 832 | sdata->u.ibss.fixed_channel = params->channel_fixed; |
841 | 833 | ||
@@ -859,6 +851,19 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
859 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; | 851 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; |
860 | sdata->u.ibss.ibss_join_req = jiffies; | 852 | sdata->u.ibss.ibss_join_req = jiffies; |
861 | 853 | ||
854 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | ||
855 | |||
856 | /* | ||
857 | * The ssid_len setting below is used to see whether | ||
858 | * we are active, and we need all other settings | ||
859 | * before that may get visible. | ||
860 | */ | ||
861 | mb(); | ||
862 | |||
863 | sdata->u.ibss.ssid_len = params->ssid_len; | ||
864 | |||
865 | ieee80211_recalc_idle(sdata->local); | ||
866 | |||
862 | set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); | 867 | set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); |
863 | queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); | 868 | queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); |
864 | 869 | ||
@@ -880,12 +885,15 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
880 | kfree(sdata->u.ibss.ie); | 885 | kfree(sdata->u.ibss.ie); |
881 | skb = sdata->u.ibss.presp; | 886 | skb = sdata->u.ibss.presp; |
882 | rcu_assign_pointer(sdata->u.ibss.presp, NULL); | 887 | rcu_assign_pointer(sdata->u.ibss.presp, NULL); |
883 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); | 888 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
884 | synchronize_rcu(); | 889 | synchronize_rcu(); |
885 | kfree_skb(skb); | 890 | kfree_skb(skb); |
886 | 891 | ||
887 | skb_queue_purge(&sdata->u.ibss.skb_queue); | 892 | skb_queue_purge(&sdata->u.ibss.skb_queue); |
888 | memset(sdata->u.ibss.bssid, 0, ETH_ALEN); | 893 | memset(sdata->u.ibss.bssid, 0, ETH_ALEN); |
894 | sdata->u.ibss.ssid_len = 0; | ||
895 | |||
896 | ieee80211_recalc_idle(sdata->local); | ||
889 | 897 | ||
890 | return 0; | 898 | return 0; |
891 | } | 899 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1579bc92c88d..03e0d22603c8 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -248,9 +248,8 @@ struct mesh_preq_queue { | |||
248 | #define IEEE80211_STA_EXT_SME BIT(17) | 248 | #define IEEE80211_STA_EXT_SME BIT(17) |
249 | /* flags for MLME request */ | 249 | /* flags for MLME request */ |
250 | #define IEEE80211_STA_REQ_SCAN 0 | 250 | #define IEEE80211_STA_REQ_SCAN 0 |
251 | #define IEEE80211_STA_REQ_DIRECT_PROBE 1 | 251 | #define IEEE80211_STA_REQ_AUTH 1 |
252 | #define IEEE80211_STA_REQ_AUTH 2 | 252 | #define IEEE80211_STA_REQ_RUN 2 |
253 | #define IEEE80211_STA_REQ_RUN 3 | ||
254 | 253 | ||
255 | /* bitfield of allowed auth algs */ | 254 | /* bitfield of allowed auth algs */ |
256 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) | 255 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) |
@@ -659,6 +658,7 @@ struct ieee80211_local { | |||
659 | 658 | ||
660 | 659 | ||
661 | /* Scanning and BSS list */ | 660 | /* Scanning and BSS list */ |
661 | struct mutex scan_mtx; | ||
662 | bool sw_scanning, hw_scanning; | 662 | bool sw_scanning, hw_scanning; |
663 | struct cfg80211_ssid scan_ssid; | 663 | struct cfg80211_ssid scan_ssid; |
664 | struct cfg80211_scan_request int_scan_req; | 664 | struct cfg80211_scan_request int_scan_req; |
@@ -905,7 +905,6 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | |||
905 | 905 | ||
906 | 906 | ||
907 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); | 907 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); |
908 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); | ||
909 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 908 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
910 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 909 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, |
911 | u32 changed); | 910 | u32 changed); |
@@ -947,6 +946,8 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | |||
947 | 946 | ||
948 | /* scan/BSS handling */ | 947 | /* scan/BSS handling */ |
949 | void ieee80211_scan_work(struct work_struct *work); | 948 | void ieee80211_scan_work(struct work_struct *work); |
949 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | ||
950 | const u8 *ssid, u8 ssid_len); | ||
950 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 951 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
951 | struct cfg80211_scan_request *req); | 952 | struct cfg80211_scan_request *req); |
952 | int ieee80211_scan_results(struct ieee80211_local *local, | 953 | int ieee80211_scan_results(struct ieee80211_local *local, |
@@ -960,9 +961,6 @@ int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, | |||
960 | const char *ie, size_t len); | 961 | const char *ie, size_t len); |
961 | 962 | ||
962 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); | 963 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); |
963 | void ieee80211_scan_failed(struct ieee80211_local *local); | ||
964 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | ||
965 | struct cfg80211_scan_request *req); | ||
966 | struct ieee80211_bss * | 964 | struct ieee80211_bss * |
967 | ieee80211_bss_info_update(struct ieee80211_local *local, | 965 | ieee80211_bss_info_update(struct ieee80211_local *local, |
968 | struct ieee80211_rx_status *rx_status, | 966 | struct ieee80211_rx_status *rx_status, |
@@ -987,6 +985,8 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
987 | enum nl80211_iftype type); | 985 | enum nl80211_iftype type); |
988 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); | 986 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); |
989 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 987 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
988 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); | ||
989 | void ieee80211_recalc_idle(struct ieee80211_local *local); | ||
990 | 990 | ||
991 | /* tx handling */ | 991 | /* tx handling */ |
992 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); | 992 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 52425975bbbe..8b6daf0219f4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "debugfs_netdev.h" | 20 | #include "debugfs_netdev.h" |
21 | #include "mesh.h" | 21 | #include "mesh.h" |
22 | #include "led.h" | 22 | #include "led.h" |
23 | #include "driver-ops.h" | ||
23 | 24 | ||
24 | /** | 25 | /** |
25 | * DOC: Interface list locking | 26 | * DOC: Interface list locking |
@@ -164,9 +165,7 @@ static int ieee80211_open(struct net_device *dev) | |||
164 | } | 165 | } |
165 | 166 | ||
166 | if (local->open_count == 0) { | 167 | if (local->open_count == 0) { |
167 | res = 0; | 168 | res = drv_start(local); |
168 | if (local->ops->start) | ||
169 | res = local->ops->start(local_to_hw(local)); | ||
170 | if (res) | 169 | if (res) |
171 | goto err_del_bss; | 170 | goto err_del_bss; |
172 | /* we're brought up, everything changes */ | 171 | /* we're brought up, everything changes */ |
@@ -199,8 +198,8 @@ static int ieee80211_open(struct net_device *dev) | |||
199 | * Validate the MAC address for this device. | 198 | * Validate the MAC address for this device. |
200 | */ | 199 | */ |
201 | if (!is_valid_ether_addr(dev->dev_addr)) { | 200 | if (!is_valid_ether_addr(dev->dev_addr)) { |
202 | if (!local->open_count && local->ops->stop) | 201 | if (!local->open_count) |
203 | local->ops->stop(local_to_hw(local)); | 202 | drv_stop(local); |
204 | return -EADDRNOTAVAIL; | 203 | return -EADDRNOTAVAIL; |
205 | } | 204 | } |
206 | 205 | ||
@@ -241,7 +240,7 @@ static int ieee80211_open(struct net_device *dev) | |||
241 | conf.vif = &sdata->vif; | 240 | conf.vif = &sdata->vif; |
242 | conf.type = sdata->vif.type; | 241 | conf.type = sdata->vif.type; |
243 | conf.mac_addr = dev->dev_addr; | 242 | conf.mac_addr = dev->dev_addr; |
244 | res = local->ops->add_interface(local_to_hw(local), &conf); | 243 | res = drv_add_interface(local, &conf); |
245 | if (res) | 244 | if (res) |
246 | goto err_stop; | 245 | goto err_stop; |
247 | 246 | ||
@@ -302,6 +301,8 @@ static int ieee80211_open(struct net_device *dev) | |||
302 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 301 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
303 | atomic_inc(&local->iff_promiscs); | 302 | atomic_inc(&local->iff_promiscs); |
304 | 303 | ||
304 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
305 | |||
305 | local->open_count++; | 306 | local->open_count++; |
306 | if (hw_reconf_flags) { | 307 | if (hw_reconf_flags) { |
307 | ieee80211_hw_config(local, hw_reconf_flags); | 308 | ieee80211_hw_config(local, hw_reconf_flags); |
@@ -328,10 +329,10 @@ static int ieee80211_open(struct net_device *dev) | |||
328 | 329 | ||
329 | return 0; | 330 | return 0; |
330 | err_del_interface: | 331 | err_del_interface: |
331 | local->ops->remove_interface(local_to_hw(local), &conf); | 332 | drv_remove_interface(local, &conf); |
332 | err_stop: | 333 | err_stop: |
333 | if (!local->open_count && local->ops->stop) | 334 | if (!local->open_count) |
334 | local->ops->stop(local_to_hw(local)); | 335 | drv_stop(local); |
335 | err_del_bss: | 336 | err_del_bss: |
336 | sdata->bss = NULL; | 337 | sdata->bss = NULL; |
337 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 338 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -544,17 +545,20 @@ static int ieee80211_stop(struct net_device *dev) | |||
544 | conf.mac_addr = dev->dev_addr; | 545 | conf.mac_addr = dev->dev_addr; |
545 | /* disable all keys for as long as this netdev is down */ | 546 | /* disable all keys for as long as this netdev is down */ |
546 | ieee80211_disable_keys(sdata); | 547 | ieee80211_disable_keys(sdata); |
547 | local->ops->remove_interface(local_to_hw(local), &conf); | 548 | drv_remove_interface(local, &conf); |
548 | } | 549 | } |
549 | 550 | ||
550 | sdata->bss = NULL; | 551 | sdata->bss = NULL; |
551 | 552 | ||
553 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
554 | |||
555 | ieee80211_recalc_ps(local, -1); | ||
556 | |||
552 | if (local->open_count == 0) { | 557 | if (local->open_count == 0) { |
553 | if (netif_running(local->mdev)) | 558 | if (netif_running(local->mdev)) |
554 | dev_close(local->mdev); | 559 | dev_close(local->mdev); |
555 | 560 | ||
556 | if (local->ops->stop) | 561 | drv_stop(local); |
557 | local->ops->stop(local_to_hw(local)); | ||
558 | 562 | ||
559 | ieee80211_led_radio(local, 0); | 563 | ieee80211_led_radio(local, 0); |
560 | 564 | ||
@@ -567,8 +571,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
567 | hw_reconf_flags = 0; | 571 | hw_reconf_flags = 0; |
568 | } | 572 | } |
569 | 573 | ||
570 | ieee80211_recalc_ps(local, -1); | ||
571 | |||
572 | /* do after stop to avoid reconfiguring when we stop anyway */ | 574 | /* do after stop to avoid reconfiguring when we stop anyway */ |
573 | if (hw_reconf_flags) | 575 | if (hw_reconf_flags) |
574 | ieee80211_hw_config(local, hw_reconf_flags); | 576 | ieee80211_hw_config(local, hw_reconf_flags); |
@@ -894,3 +896,73 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
894 | unregister_netdevice(sdata->dev); | 896 | unregister_netdevice(sdata->dev); |
895 | } | 897 | } |
896 | } | 898 | } |
899 | |||
900 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | ||
901 | const char *reason) | ||
902 | { | ||
903 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | ||
904 | return 0; | ||
905 | |||
906 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
907 | printk(KERN_DEBUG "%s: device no longer idle - %s\n", | ||
908 | wiphy_name(local->hw.wiphy), reason); | ||
909 | #endif | ||
910 | |||
911 | local->hw.conf.flags &= ~IEEE80211_CONF_IDLE; | ||
912 | return IEEE80211_CONF_CHANGE_IDLE; | ||
913 | } | ||
914 | |||
915 | static u32 ieee80211_idle_on(struct ieee80211_local *local) | ||
916 | { | ||
917 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) | ||
918 | return 0; | ||
919 | |||
920 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
921 | printk(KERN_DEBUG "%s: device now idle\n", | ||
922 | wiphy_name(local->hw.wiphy)); | ||
923 | #endif | ||
924 | |||
925 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | ||
926 | return IEEE80211_CONF_CHANGE_IDLE; | ||
927 | } | ||
928 | |||
929 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | ||
930 | { | ||
931 | struct ieee80211_sub_if_data *sdata; | ||
932 | int count = 0; | ||
933 | |||
934 | if (local->hw_scanning || local->sw_scanning) | ||
935 | return ieee80211_idle_off(local, "scanning"); | ||
936 | |||
937 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
938 | if (!netif_running(sdata->dev)) | ||
939 | continue; | ||
940 | /* do not count disabled managed interfaces */ | ||
941 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
942 | sdata->u.mgd.state == IEEE80211_STA_MLME_DISABLED) | ||
943 | continue; | ||
944 | /* do not count unused IBSS interfaces */ | ||
945 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
946 | !sdata->u.ibss.ssid_len) | ||
947 | continue; | ||
948 | /* count everything else */ | ||
949 | count++; | ||
950 | } | ||
951 | |||
952 | if (!count) | ||
953 | return ieee80211_idle_on(local); | ||
954 | else | ||
955 | return ieee80211_idle_off(local, "in use"); | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | void ieee80211_recalc_idle(struct ieee80211_local *local) | ||
961 | { | ||
962 | u32 chg; | ||
963 | |||
964 | mutex_lock(&local->iflist_mtx); | ||
965 | chg = __ieee80211_recalc_idle(local); | ||
966 | mutex_unlock(&local->iflist_mtx); | ||
967 | ieee80211_hw_config(local, chg); | ||
968 | } | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 687acf23054d..b7e1350273bb 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
19 | #include "driver-ops.h" | ||
19 | #include "debugfs_key.h" | 20 | #include "debugfs_key.h" |
20 | #include "aes_ccm.h" | 21 | #include "aes_ccm.h" |
21 | #include "aes_cmac.h" | 22 | #include "aes_cmac.h" |
@@ -136,8 +137,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
136 | struct ieee80211_sub_if_data, | 137 | struct ieee80211_sub_if_data, |
137 | u.ap); | 138 | u.ap); |
138 | 139 | ||
139 | ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, | 140 | ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); |
140 | &sdata->vif, sta, &key->conf); | ||
141 | 141 | ||
142 | if (!ret) { | 142 | if (!ret) { |
143 | spin_lock(&todo_lock); | 143 | spin_lock(&todo_lock); |
@@ -179,8 +179,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
179 | struct ieee80211_sub_if_data, | 179 | struct ieee80211_sub_if_data, |
180 | u.ap); | 180 | u.ap); |
181 | 181 | ||
182 | ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, | 182 | ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif, |
183 | &sdata->vif, sta, &key->conf); | 183 | sta, &key->conf); |
184 | 184 | ||
185 | if (ret) | 185 | if (ret) |
186 | printk(KERN_ERR "mac80211-%s: failed to remove key " | 186 | printk(KERN_ERR "mac80211-%s: failed to remove key " |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5ca62ea15079..b80bc80e46cf 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <net/cfg80211.h> | 26 | #include <net/cfg80211.h> |
27 | 27 | ||
28 | #include "ieee80211_i.h" | 28 | #include "ieee80211_i.h" |
29 | #include "driver-ops.h" | ||
29 | #include "rate.h" | 30 | #include "rate.h" |
30 | #include "mesh.h" | 31 | #include "mesh.h" |
31 | #include "wep.h" | 32 | #include "wep.h" |
@@ -81,10 +82,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
81 | /* be a bit nasty */ | 82 | /* be a bit nasty */ |
82 | new_flags |= (1<<31); | 83 | new_flags |= (1<<31); |
83 | 84 | ||
84 | local->ops->configure_filter(local_to_hw(local), | 85 | drv_configure_filter(local, changed_flags, &new_flags, |
85 | changed_flags, &new_flags, | 86 | local->mdev->mc_count, |
86 | local->mdev->mc_count, | 87 | local->mdev->mc_list); |
87 | local->mdev->mc_list); | ||
88 | 88 | ||
89 | WARN_ON(new_flags & (1<<31)); | 89 | WARN_ON(new_flags & (1<<31)); |
90 | 90 | ||
@@ -152,82 +152,6 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev) | |||
152 | ieee80211_configure_filter(local); | 152 | ieee80211_configure_filter(local); |
153 | } | 153 | } |
154 | 154 | ||
155 | /* everything else */ | ||
156 | |||
157 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | ||
158 | { | ||
159 | struct ieee80211_local *local = sdata->local; | ||
160 | struct ieee80211_if_conf conf; | ||
161 | |||
162 | if (WARN_ON(!netif_running(sdata->dev))) | ||
163 | return 0; | ||
164 | |||
165 | memset(&conf, 0, sizeof(conf)); | ||
166 | |||
167 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
168 | conf.bssid = sdata->u.mgd.bssid; | ||
169 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
170 | conf.bssid = sdata->u.ibss.bssid; | ||
171 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
172 | conf.bssid = sdata->dev->dev_addr; | ||
173 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
174 | static const u8 zero[ETH_ALEN] = { 0 }; | ||
175 | conf.bssid = zero; | ||
176 | } else { | ||
177 | WARN_ON(1); | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | if (!local->ops->config_interface) | ||
182 | return 0; | ||
183 | |||
184 | switch (sdata->vif.type) { | ||
185 | case NL80211_IFTYPE_AP: | ||
186 | case NL80211_IFTYPE_ADHOC: | ||
187 | case NL80211_IFTYPE_MESH_POINT: | ||
188 | break; | ||
189 | default: | ||
190 | /* do not warn to simplify caller in scan.c */ | ||
191 | changed &= ~IEEE80211_IFCC_BEACON_ENABLED; | ||
192 | if (WARN_ON(changed & IEEE80211_IFCC_BEACON)) | ||
193 | return -EINVAL; | ||
194 | changed &= ~IEEE80211_IFCC_BEACON; | ||
195 | break; | ||
196 | } | ||
197 | |||
198 | if (changed & IEEE80211_IFCC_BEACON_ENABLED) { | ||
199 | if (local->sw_scanning) { | ||
200 | conf.enable_beacon = false; | ||
201 | } else { | ||
202 | /* | ||
203 | * Beacon should be enabled, but AP mode must | ||
204 | * check whether there is a beacon configured. | ||
205 | */ | ||
206 | switch (sdata->vif.type) { | ||
207 | case NL80211_IFTYPE_AP: | ||
208 | conf.enable_beacon = | ||
209 | !!rcu_dereference(sdata->u.ap.beacon); | ||
210 | break; | ||
211 | case NL80211_IFTYPE_ADHOC: | ||
212 | conf.enable_beacon = !!sdata->u.ibss.presp; | ||
213 | break; | ||
214 | case NL80211_IFTYPE_MESH_POINT: | ||
215 | conf.enable_beacon = true; | ||
216 | break; | ||
217 | default: | ||
218 | /* not reached */ | ||
219 | WARN_ON(1); | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | |||
225 | conf.changed = changed; | ||
226 | |||
227 | return local->ops->config_interface(local_to_hw(local), | ||
228 | &sdata->vif, &conf); | ||
229 | } | ||
230 | |||
231 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 155 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
232 | { | 156 | { |
233 | struct ieee80211_channel *chan; | 157 | struct ieee80211_channel *chan; |
@@ -268,7 +192,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
268 | } | 192 | } |
269 | 193 | ||
270 | if (changed && local->open_count) { | 194 | if (changed && local->open_count) { |
271 | ret = local->ops->config(local_to_hw(local), changed); | 195 | ret = drv_config(local, changed); |
272 | /* | 196 | /* |
273 | * Goal: | 197 | * Goal: |
274 | * HW reconfiguration should never fail, the driver has told | 198 | * HW reconfiguration should never fail, the driver has told |
@@ -294,17 +218,77 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
294 | { | 218 | { |
295 | struct ieee80211_local *local = sdata->local; | 219 | struct ieee80211_local *local = sdata->local; |
296 | 220 | ||
297 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) | 221 | if (!changed) |
298 | return; | 222 | return; |
299 | 223 | ||
300 | if (!changed) | 224 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
225 | sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; | ||
226 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
227 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; | ||
228 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
229 | sdata->vif.bss_conf.bssid = sdata->dev->dev_addr; | ||
230 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
231 | static const u8 zero[ETH_ALEN] = { 0 }; | ||
232 | sdata->vif.bss_conf.bssid = zero; | ||
233 | } else { | ||
234 | WARN_ON(1); | ||
301 | return; | 235 | return; |
236 | } | ||
237 | |||
238 | switch (sdata->vif.type) { | ||
239 | case NL80211_IFTYPE_AP: | ||
240 | case NL80211_IFTYPE_ADHOC: | ||
241 | case NL80211_IFTYPE_MESH_POINT: | ||
242 | break; | ||
243 | default: | ||
244 | /* do not warn to simplify caller in scan.c */ | ||
245 | changed &= ~BSS_CHANGED_BEACON_ENABLED; | ||
246 | if (WARN_ON(changed & BSS_CHANGED_BEACON)) | ||
247 | return; | ||
248 | break; | ||
249 | } | ||
250 | |||
251 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | ||
252 | if (local->sw_scanning) { | ||
253 | sdata->vif.bss_conf.enable_beacon = false; | ||
254 | } else { | ||
255 | /* | ||
256 | * Beacon should be enabled, but AP mode must | ||
257 | * check whether there is a beacon configured. | ||
258 | */ | ||
259 | switch (sdata->vif.type) { | ||
260 | case NL80211_IFTYPE_AP: | ||
261 | sdata->vif.bss_conf.enable_beacon = | ||
262 | !!rcu_dereference(sdata->u.ap.beacon); | ||
263 | break; | ||
264 | case NL80211_IFTYPE_ADHOC: | ||
265 | sdata->vif.bss_conf.enable_beacon = | ||
266 | !!rcu_dereference(sdata->u.ibss.presp); | ||
267 | break; | ||
268 | case NL80211_IFTYPE_MESH_POINT: | ||
269 | sdata->vif.bss_conf.enable_beacon = true; | ||
270 | break; | ||
271 | default: | ||
272 | /* not reached */ | ||
273 | WARN_ON(1); | ||
274 | break; | ||
275 | } | ||
276 | } | ||
277 | } | ||
302 | 278 | ||
303 | if (local->ops->bss_info_changed) | 279 | drv_bss_info_changed(local, &sdata->vif, |
304 | local->ops->bss_info_changed(local_to_hw(local), | 280 | &sdata->vif.bss_conf, changed); |
305 | &sdata->vif, | 281 | |
306 | &sdata->vif.bss_conf, | 282 | /* |
307 | changed); | 283 | * DEPRECATED |
284 | * | ||
285 | * ~changed is just there to not do this at resume time | ||
286 | */ | ||
287 | if (changed & BSS_CHANGED_BEACON_INT && ~changed) { | ||
288 | local->hw.conf.beacon_int = sdata->vif.bss_conf.beacon_int; | ||
289 | ieee80211_hw_config(local, | ||
290 | _IEEE80211_CONF_CHANGE_BEACON_INTERVAL); | ||
291 | } | ||
308 | } | 292 | } |
309 | 293 | ||
310 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | 294 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) |
@@ -783,6 +767,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
783 | 767 | ||
784 | INIT_LIST_HEAD(&local->interfaces); | 768 | INIT_LIST_HEAD(&local->interfaces); |
785 | mutex_init(&local->iflist_mtx); | 769 | mutex_init(&local->iflist_mtx); |
770 | mutex_init(&local->scan_mtx); | ||
786 | 771 | ||
787 | spin_lock_init(&local->key_lock); | 772 | spin_lock_init(&local->key_lock); |
788 | 773 | ||
@@ -970,9 +955,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
970 | 955 | ||
971 | debugfs_hw_add(local); | 956 | debugfs_hw_add(local); |
972 | 957 | ||
973 | if (local->hw.conf.beacon_int < 10) | ||
974 | local->hw.conf.beacon_int = 100; | ||
975 | |||
976 | if (local->hw.max_listen_interval == 0) | 958 | if (local->hw.max_listen_interval == 0) |
977 | local->hw.max_listen_interval = 1; | 959 | local->hw.max_listen_interval = 1; |
978 | 960 | ||
@@ -1126,6 +1108,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
1126 | struct ieee80211_local *local = hw_to_local(hw); | 1108 | struct ieee80211_local *local = hw_to_local(hw); |
1127 | 1109 | ||
1128 | mutex_destroy(&local->iflist_mtx); | 1110 | mutex_destroy(&local->iflist_mtx); |
1111 | mutex_destroy(&local->scan_mtx); | ||
1129 | 1112 | ||
1130 | wiphy_free(local->hw.wiphy); | 1113 | wiphy_free(local->hw.wiphy); |
1131 | } | 1114 | } |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 9a3e5de0410a..9000b01a1671 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -417,7 +417,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
417 | 417 | ||
418 | free_plinks = mesh_plink_availables(sdata); | 418 | free_plinks = mesh_plink_availables(sdata); |
419 | if (free_plinks != sdata->u.mesh.accepting_plinks) | 419 | if (free_plinks != sdata->u.mesh.accepting_plinks) |
420 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 420 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); |
421 | 421 | ||
422 | ifmsh->housekeeping = false; | 422 | ifmsh->housekeeping = false; |
423 | mod_timer(&ifmsh->housekeeping_timer, | 423 | mod_timer(&ifmsh->housekeeping_timer, |
@@ -432,8 +432,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
432 | 432 | ||
433 | ifmsh->housekeeping = true; | 433 | ifmsh->housekeeping = true; |
434 | queue_work(local->hw.workqueue, &ifmsh->work); | 434 | queue_work(local->hw.workqueue, &ifmsh->work); |
435 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | | 435 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
436 | IEEE80211_IFCC_BEACON_ENABLED); | 436 | BSS_CHANGED_BEACON_ENABLED); |
437 | } | 437 | } |
438 | 438 | ||
439 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 439 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 3610c11286bc..75c487229f2e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/unaligned.h> | 23 | #include <asm/unaligned.h> |
24 | 24 | ||
25 | #include "ieee80211_i.h" | 25 | #include "ieee80211_i.h" |
26 | #include "driver-ops.h" | ||
26 | #include "rate.h" | 27 | #include "rate.h" |
27 | #include "led.h" | 28 | #include "led.h" |
28 | 29 | ||
@@ -487,6 +488,13 @@ static void ieee80211_enable_ps(struct ieee80211_local *local, | |||
487 | { | 488 | { |
488 | struct ieee80211_conf *conf = &local->hw.conf; | 489 | struct ieee80211_conf *conf = &local->hw.conf; |
489 | 490 | ||
491 | /* | ||
492 | * If we are scanning right now then the parameters will | ||
493 | * take effect when scan finishes. | ||
494 | */ | ||
495 | if (local->hw_scanning || local->sw_scanning) | ||
496 | return; | ||
497 | |||
490 | if (conf->dynamic_ps_timeout > 0 && | 498 | if (conf->dynamic_ps_timeout > 0 && |
491 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { | 499 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) { |
492 | mod_timer(&local->dynamic_ps_timer, jiffies + | 500 | mod_timer(&local->dynamic_ps_timer, jiffies + |
@@ -555,7 +563,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
555 | maxslp = min_t(int, dtimper, | 563 | maxslp = min_t(int, dtimper, |
556 | latency / beaconint_us); | 564 | latency / beaconint_us); |
557 | 565 | ||
558 | local->hw.conf.max_sleep_interval = maxslp; | 566 | local->hw.conf.max_sleep_period = maxslp; |
559 | local->ps_sdata = found; | 567 | local->ps_sdata = found; |
560 | } | 568 | } |
561 | } else { | 569 | } else { |
@@ -676,11 +684,10 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
676 | local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, | 684 | local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, |
677 | params.cw_max, params.txop); | 685 | params.cw_max, params.txop); |
678 | #endif | 686 | #endif |
679 | if (local->ops->conf_tx && | 687 | if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx) |
680 | local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { | ||
681 | printk(KERN_DEBUG "%s: failed to set TX queue " | 688 | printk(KERN_DEBUG "%s: failed to set TX queue " |
682 | "parameters for queue %d\n", local->mdev->name, queue); | 689 | "parameters for queue %d\n", local->mdev->name, |
683 | } | 690 | queue); |
684 | } | 691 | } |
685 | } | 692 | } |
686 | 693 | ||
@@ -835,6 +842,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
835 | sdata->vif.bss_conf.timestamp = bss->cbss.tsf; | 842 | sdata->vif.bss_conf.timestamp = bss->cbss.tsf; |
836 | sdata->vif.bss_conf.dtim_period = bss->dtim_period; | 843 | sdata->vif.bss_conf.dtim_period = bss->dtim_period; |
837 | 844 | ||
845 | bss_info_changed |= BSS_CHANGED_BEACON_INT; | ||
838 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 846 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
839 | bss->cbss.capability, bss->has_erp_value, bss->erp_value); | 847 | bss->cbss.capability, bss->has_erp_value, bss->erp_value); |
840 | 848 | ||
@@ -882,7 +890,8 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) | |||
882 | printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", | 890 | printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", |
883 | sdata->dev->name, ifmgd->bssid); | 891 | sdata->dev->name, ifmgd->bssid); |
884 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; | 892 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; |
885 | ieee80211_sta_send_apinfo(sdata); | 893 | ieee80211_recalc_idle(local); |
894 | cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); | ||
886 | 895 | ||
887 | /* | 896 | /* |
888 | * Most likely AP is not in the range so remove the | 897 | * Most likely AP is not in the range so remove the |
@@ -907,8 +916,6 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) | |||
907 | 916 | ||
908 | ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; | 917 | ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; |
909 | 918 | ||
910 | set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifmgd->request); | ||
911 | |||
912 | /* Direct probe is sent to broadcast address as some APs | 919 | /* Direct probe is sent to broadcast address as some APs |
913 | * will not answer to direct packet in unassociated state. | 920 | * will not answer to direct packet in unassociated state. |
914 | */ | 921 | */ |
@@ -932,6 +939,7 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata) | |||
932 | " timed out\n", | 939 | " timed out\n", |
933 | sdata->dev->name, ifmgd->bssid); | 940 | sdata->dev->name, ifmgd->bssid); |
934 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; | 941 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; |
942 | ieee80211_recalc_idle(local); | ||
935 | cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); | 943 | cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid); |
936 | ieee80211_rx_bss_remove(sdata, ifmgd->bssid, | 944 | ieee80211_rx_bss_remove(sdata, ifmgd->bssid, |
937 | sdata->local->hw.conf.channel->center_freq, | 945 | sdata->local->hw.conf.channel->center_freq, |
@@ -1035,6 +1043,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1035 | 1043 | ||
1036 | rcu_read_unlock(); | 1044 | rcu_read_unlock(); |
1037 | 1045 | ||
1046 | ieee80211_recalc_idle(local); | ||
1047 | |||
1038 | /* channel(_type) changes are handled by ieee80211_hw_config */ | 1048 | /* channel(_type) changes are handled by ieee80211_hw_config */ |
1039 | local->oper_channel_type = NL80211_CHAN_NO_HT; | 1049 | local->oper_channel_type = NL80211_CHAN_NO_HT; |
1040 | 1050 | ||
@@ -1115,6 +1125,7 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) | |||
1115 | " timed out\n", | 1125 | " timed out\n", |
1116 | sdata->dev->name, ifmgd->bssid); | 1126 | sdata->dev->name, ifmgd->bssid); |
1117 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; | 1127 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; |
1128 | ieee80211_recalc_idle(local); | ||
1118 | cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid); | 1129 | cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid); |
1119 | ieee80211_rx_bss_remove(sdata, ifmgd->bssid, | 1130 | ieee80211_rx_bss_remove(sdata, ifmgd->bssid, |
1120 | sdata->local->hw.conf.channel->center_freq, | 1131 | sdata->local->hw.conf.channel->center_freq, |
@@ -1135,6 +1146,7 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata) | |||
1135 | printk(KERN_DEBUG "%s: mismatch in privacy configuration and " | 1146 | printk(KERN_DEBUG "%s: mismatch in privacy configuration and " |
1136 | "mixed-cell disabled - abort association\n", sdata->dev->name); | 1147 | "mixed-cell disabled - abort association\n", sdata->dev->name); |
1137 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; | 1148 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; |
1149 | ieee80211_recalc_idle(local); | ||
1138 | return; | 1150 | return; |
1139 | } | 1151 | } |
1140 | 1152 | ||
@@ -1273,6 +1285,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata) | |||
1273 | if (ifmgd->flags & IEEE80211_STA_EXT_SME) { | 1285 | if (ifmgd->flags & IEEE80211_STA_EXT_SME) { |
1274 | /* Wait for SME to request association */ | 1286 | /* Wait for SME to request association */ |
1275 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; | 1287 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; |
1288 | ieee80211_recalc_idle(sdata->local); | ||
1276 | } else | 1289 | } else |
1277 | ieee80211_associate(sdata); | 1290 | ieee80211_associate(sdata); |
1278 | } | 1291 | } |
@@ -1509,6 +1522,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1509 | if (ifmgd->flags & IEEE80211_STA_EXT_SME) { | 1522 | if (ifmgd->flags & IEEE80211_STA_EXT_SME) { |
1510 | /* Wait for SME to decide what to do next */ | 1523 | /* Wait for SME to decide what to do next */ |
1511 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; | 1524 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; |
1525 | ieee80211_recalc_idle(local); | ||
1512 | } | 1526 | } |
1513 | return; | 1527 | return; |
1514 | } | 1528 | } |
@@ -1730,8 +1744,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1730 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); | 1744 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); |
1731 | 1745 | ||
1732 | /* direct probe may be part of the association flow */ | 1746 | /* direct probe may be part of the association flow */ |
1733 | if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, | 1747 | if (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE) { |
1734 | &ifmgd->request)) { | ||
1735 | printk(KERN_DEBUG "%s direct probe responded\n", | 1748 | printk(KERN_DEBUG "%s direct probe responded\n", |
1736 | sdata->dev->name); | 1749 | sdata->dev->name); |
1737 | ieee80211_authenticate(sdata); | 1750 | ieee80211_authenticate(sdata); |
@@ -1974,10 +1987,8 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata) | |||
1974 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1987 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1975 | struct ieee80211_local *local = sdata->local; | 1988 | struct ieee80211_local *local = sdata->local; |
1976 | 1989 | ||
1977 | if (local->ops->reset_tsf) { | 1990 | /* Reset own TSF to allow time synchronization work. */ |
1978 | /* Reset own TSF to allow time synchronization work. */ | 1991 | drv_reset_tsf(local); |
1979 | local->ops->reset_tsf(local_to_hw(local)); | ||
1980 | } | ||
1981 | 1992 | ||
1982 | ifmgd->wmm_last_param_set = -1; /* allow any WMM update */ | 1993 | ifmgd->wmm_last_param_set = -1; /* allow any WMM update */ |
1983 | 1994 | ||
@@ -2065,25 +2076,18 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) | |||
2065 | return 0; | 2076 | return 0; |
2066 | } else { | 2077 | } else { |
2067 | if (ifmgd->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { | 2078 | if (ifmgd->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { |
2079 | |||
2068 | ifmgd->assoc_scan_tries++; | 2080 | ifmgd->assoc_scan_tries++; |
2069 | /* XXX maybe racy? */ | ||
2070 | if (local->scan_req) | ||
2071 | return -1; | ||
2072 | memcpy(local->int_scan_req.ssids[0].ssid, | ||
2073 | ifmgd->ssid, IEEE80211_MAX_SSID_LEN); | ||
2074 | if (ifmgd->flags & IEEE80211_STA_AUTO_SSID_SEL) | ||
2075 | local->int_scan_req.ssids[0].ssid_len = 0; | ||
2076 | else | ||
2077 | local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len; | ||
2078 | 2081 | ||
2079 | if (ieee80211_start_scan(sdata, &local->int_scan_req)) | 2082 | ieee80211_request_internal_scan(sdata, ifmgd->ssid, |
2080 | ieee80211_scan_failed(local); | 2083 | ssid_len); |
2081 | 2084 | ||
2082 | ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; | 2085 | ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; |
2083 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); | 2086 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); |
2084 | } else { | 2087 | } else { |
2085 | ifmgd->assoc_scan_tries = 0; | 2088 | ifmgd->assoc_scan_tries = 0; |
2086 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; | 2089 | ifmgd->state = IEEE80211_STA_MLME_DISABLED; |
2090 | ieee80211_recalc_idle(local); | ||
2087 | } | 2091 | } |
2088 | } | 2092 | } |
2089 | return -1; | 2093 | return -1; |
@@ -2115,14 +2119,8 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2115 | ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && | 2119 | ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && |
2116 | ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && | 2120 | ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && |
2117 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { | 2121 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { |
2118 | /* | 2122 | queue_delayed_work(local->hw.workqueue, &local->scan_work, |
2119 | * The call to ieee80211_start_scan can fail but ieee80211_request_scan | 2123 | round_jiffies_relative(0)); |
2120 | * (which queued ieee80211_sta_work) did not return an error. Thus, call | ||
2121 | * ieee80211_scan_failed here if ieee80211_start_scan fails in order to | ||
2122 | * notify the scan requester. | ||
2123 | */ | ||
2124 | if (ieee80211_start_scan(sdata, local->scan_req)) | ||
2125 | ieee80211_scan_failed(local); | ||
2126 | return; | 2124 | return; |
2127 | } | 2125 | } |
2128 | 2126 | ||
@@ -2133,6 +2131,8 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2133 | } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request)) | 2131 | } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request)) |
2134 | return; | 2132 | return; |
2135 | 2133 | ||
2134 | ieee80211_recalc_idle(local); | ||
2135 | |||
2136 | switch (ifmgd->state) { | 2136 | switch (ifmgd->state) { |
2137 | case IEEE80211_STA_MLME_DISABLED: | 2137 | case IEEE80211_STA_MLME_DISABLED: |
2138 | break; | 2138 | break; |
@@ -2291,12 +2291,8 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) | |||
2291 | ifmgd->flags &= ~IEEE80211_STA_BSSID_SET; | 2291 | ifmgd->flags &= ~IEEE80211_STA_BSSID_SET; |
2292 | } | 2292 | } |
2293 | 2293 | ||
2294 | if (netif_running(sdata->dev)) { | 2294 | if (netif_running(sdata->dev)) |
2295 | if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) { | 2295 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
2296 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " | ||
2297 | "the low-level driver\n", sdata->dev->name); | ||
2298 | } | ||
2299 | } | ||
2300 | 2296 | ||
2301 | return ieee80211_sta_commit(sdata); | 2297 | return ieee80211_sta_commit(sdata); |
2302 | } | 2298 | } |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index b38986c9deef..9d3d89abbb57 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <net/rtnetlink.h> | 2 | #include <net/rtnetlink.h> |
3 | 3 | ||
4 | #include "ieee80211_i.h" | 4 | #include "ieee80211_i.h" |
5 | #include "driver-ops.h" | ||
5 | #include "led.h" | 6 | #include "led.h" |
6 | 7 | ||
7 | int __ieee80211_suspend(struct ieee80211_hw *hw) | 8 | int __ieee80211_suspend(struct ieee80211_hw *hw) |
@@ -43,8 +44,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
43 | struct ieee80211_sub_if_data, | 44 | struct ieee80211_sub_if_data, |
44 | u.ap); | 45 | u.ap); |
45 | 46 | ||
46 | local->ops->sta_notify(hw, &sdata->vif, | 47 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, |
47 | STA_NOTIFY_REMOVE, &sta->sta); | 48 | &sta->sta); |
48 | } | 49 | } |
49 | spin_unlock_irqrestore(&local->sta_lock, flags); | 50 | spin_unlock_irqrestore(&local->sta_lock, flags); |
50 | } | 51 | } |
@@ -57,7 +58,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
57 | conf.vif = &sdata->vif; | 58 | conf.vif = &sdata->vif; |
58 | conf.type = sdata->vif.type; | 59 | conf.type = sdata->vif.type; |
59 | conf.mac_addr = sdata->dev->dev_addr; | 60 | conf.mac_addr = sdata->dev->dev_addr; |
60 | local->ops->remove_interface(hw, &conf); | 61 | drv_remove_interface(local, &conf); |
61 | } | 62 | } |
62 | } | 63 | } |
63 | 64 | ||
@@ -67,7 +68,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
67 | /* stop hardware */ | 68 | /* stop hardware */ |
68 | if (local->open_count) { | 69 | if (local->open_count) { |
69 | ieee80211_led_radio(local, false); | 70 | ieee80211_led_radio(local, false); |
70 | local->ops->stop(hw); | 71 | drv_stop(local); |
71 | } | 72 | } |
72 | return 0; | 73 | return 0; |
73 | } | 74 | } |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 70df3dcc3cf6..efaf38349731 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -80,8 +80,7 @@ use_low_rate(struct sk_buff *skb) | |||
80 | fc = le16_to_cpu(hdr->frame_control); | 80 | fc = le16_to_cpu(hdr->frame_control); |
81 | 81 | ||
82 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || | 82 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || |
83 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 83 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA); |
84 | is_multicast_ether_addr(hdr->addr1)); | ||
85 | } | 84 | } |
86 | 85 | ||
87 | 86 | ||
@@ -245,7 +244,10 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
245 | 244 | ||
246 | if (!sta || !mi || use_low_rate(skb)) { | 245 | if (!sta || !mi || use_low_rate(skb)) { |
247 | ar[0].idx = rate_lowest_index(sband, sta); | 246 | ar[0].idx = rate_lowest_index(sband, sta); |
248 | ar[0].count = mp->max_retry; | 247 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) |
248 | ar[0].count = 1; | ||
249 | else | ||
250 | ar[0].count = mp->max_retry; | ||
249 | return; | 251 | return; |
250 | } | 252 | } |
251 | 253 | ||
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 01d59a8e334c..6704fb55c6b2 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -289,13 +289,15 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, | |||
289 | info->control.rates[0].count = | 289 | info->control.rates[0].count = |
290 | txrc->hw->conf.short_frame_max_tx_count; | 290 | txrc->hw->conf.short_frame_max_tx_count; |
291 | 291 | ||
292 | /* Send management frames and broadcast/multicast data using lowest | 292 | /* Send management frames and NO_ACK data using lowest rate. */ |
293 | * rate. */ | ||
294 | fc = le16_to_cpu(hdr->frame_control); | 293 | fc = le16_to_cpu(hdr->frame_control); |
295 | if (!sta || !spinfo || | 294 | if (!sta || !spinfo || |
296 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 295 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
297 | is_multicast_ether_addr(hdr->addr1)) { | 296 | info->flags & IEEE80211_TX_CTL_NO_ACK) { |
298 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | 297 | info->control.rates[0].idx = rate_lowest_index(sband, sta); |
298 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
299 | info->control.rates[0].count = 1; | ||
300 | |||
299 | return; | 301 | return; |
300 | } | 302 | } |
301 | 303 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a5afb79dab6e..d052f4004829 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <net/ieee80211_radiotap.h> | 19 | #include <net/ieee80211_radiotap.h> |
20 | 20 | ||
21 | #include "ieee80211_i.h" | 21 | #include "ieee80211_i.h" |
22 | #include "driver-ops.h" | ||
22 | #include "led.h" | 23 | #include "led.h" |
23 | #include "mesh.h" | 24 | #include "mesh.h" |
24 | #include "wep.h" | 25 | #include "wep.h" |
@@ -773,9 +774,7 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
773 | 774 | ||
774 | atomic_inc(&sdata->bss->num_sta_ps); | 775 | atomic_inc(&sdata->bss->num_sta_ps); |
775 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 776 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
776 | if (local->ops->sta_notify) | 777 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); |
777 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | ||
778 | STA_NOTIFY_SLEEP, &sta->sta); | ||
779 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 778 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
780 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 779 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", |
781 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 780 | sdata->dev->name, sta->sta.addr, sta->sta.aid); |
@@ -792,9 +791,7 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
792 | atomic_dec(&sdata->bss->num_sta_ps); | 791 | atomic_dec(&sdata->bss->num_sta_ps); |
793 | 792 | ||
794 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 793 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
795 | if (local->ops->sta_notify) | 794 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); |
796 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | ||
797 | STA_NOTIFY_AWAKE, &sta->sta); | ||
798 | 795 | ||
799 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 796 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
800 | sta_info_clear_tim_bit(sta); | 797 | sta_info_clear_tim_bit(sta); |
@@ -2287,6 +2284,43 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) | |||
2287 | } | 2284 | } |
2288 | 2285 | ||
2289 | 2286 | ||
2287 | static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | ||
2288 | struct tid_ampdu_rx *tid_agg_rx, | ||
2289 | int index) | ||
2290 | { | ||
2291 | struct ieee80211_supported_band *sband; | ||
2292 | struct ieee80211_rate *rate; | ||
2293 | struct ieee80211_rx_status status; | ||
2294 | |||
2295 | if (!tid_agg_rx->reorder_buf[index]) | ||
2296 | goto no_frame; | ||
2297 | |||
2298 | /* release the reordered frames to stack */ | ||
2299 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, sizeof(status)); | ||
2300 | sband = hw->wiphy->bands[status.band]; | ||
2301 | if (status.flag & RX_FLAG_HT) | ||
2302 | rate = sband->bitrates; /* TODO: HT rates */ | ||
2303 | else | ||
2304 | rate = &sband->bitrates[status.rate_idx]; | ||
2305 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | ||
2306 | &status, rate); | ||
2307 | tid_agg_rx->stored_mpdu_num--; | ||
2308 | tid_agg_rx->reorder_buf[index] = NULL; | ||
2309 | |||
2310 | no_frame: | ||
2311 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | ||
2312 | } | ||
2313 | |||
2314 | |||
2315 | /* | ||
2316 | * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If | ||
2317 | * the skb was added to the buffer longer than this time ago, the earlier | ||
2318 | * frames that have not yet been received are assumed to be lost and the skb | ||
2319 | * can be released for processing. This may also release other skb's from the | ||
2320 | * reorder buffer if there are no additional gaps between the frames. | ||
2321 | */ | ||
2322 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | ||
2323 | |||
2290 | /* | 2324 | /* |
2291 | * As it function blongs to Rx path it must be called with | 2325 | * As it function blongs to Rx path it must be called with |
2292 | * the proper rcu_read_lock protection for its flow. | 2326 | * the proper rcu_read_lock protection for its flow. |
@@ -2298,12 +2332,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2298 | u16 mpdu_seq_num, | 2332 | u16 mpdu_seq_num, |
2299 | int bar_req) | 2333 | int bar_req) |
2300 | { | 2334 | { |
2301 | struct ieee80211_local *local = hw_to_local(hw); | ||
2302 | struct ieee80211_rx_status status; | ||
2303 | u16 head_seq_num, buf_size; | 2335 | u16 head_seq_num, buf_size; |
2304 | int index; | 2336 | int index; |
2305 | struct ieee80211_supported_band *sband; | ||
2306 | struct ieee80211_rate *rate; | ||
2307 | 2337 | ||
2308 | buf_size = tid_agg_rx->buf_size; | 2338 | buf_size = tid_agg_rx->buf_size; |
2309 | head_seq_num = tid_agg_rx->head_seq_num; | 2339 | head_seq_num = tid_agg_rx->head_seq_num; |
@@ -2328,28 +2358,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2328 | index = seq_sub(tid_agg_rx->head_seq_num, | 2358 | index = seq_sub(tid_agg_rx->head_seq_num, |
2329 | tid_agg_rx->ssn) | 2359 | tid_agg_rx->ssn) |
2330 | % tid_agg_rx->buf_size; | 2360 | % tid_agg_rx->buf_size; |
2331 | 2361 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | |
2332 | if (tid_agg_rx->reorder_buf[index]) { | 2362 | index); |
2333 | /* release the reordered frames to stack */ | ||
2334 | memcpy(&status, | ||
2335 | tid_agg_rx->reorder_buf[index]->cb, | ||
2336 | sizeof(status)); | ||
2337 | sband = local->hw.wiphy->bands[status.band]; | ||
2338 | if (status.flag & RX_FLAG_HT) { | ||
2339 | /* TODO: HT rates */ | ||
2340 | rate = sband->bitrates; | ||
2341 | } else { | ||
2342 | rate = &sband->bitrates | ||
2343 | [status.rate_idx]; | ||
2344 | } | ||
2345 | __ieee80211_rx_handle_packet(hw, | ||
2346 | tid_agg_rx->reorder_buf[index], | ||
2347 | &status, rate); | ||
2348 | tid_agg_rx->stored_mpdu_num--; | ||
2349 | tid_agg_rx->reorder_buf[index] = NULL; | ||
2350 | } | ||
2351 | tid_agg_rx->head_seq_num = | ||
2352 | seq_inc(tid_agg_rx->head_seq_num); | ||
2353 | } | 2363 | } |
2354 | if (bar_req) | 2364 | if (bar_req) |
2355 | return 1; | 2365 | return 1; |
@@ -2376,26 +2386,50 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2376 | 2386 | ||
2377 | /* put the frame in the reordering buffer */ | 2387 | /* put the frame in the reordering buffer */ |
2378 | tid_agg_rx->reorder_buf[index] = skb; | 2388 | tid_agg_rx->reorder_buf[index] = skb; |
2389 | tid_agg_rx->reorder_time[index] = jiffies; | ||
2379 | memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, | 2390 | memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, |
2380 | sizeof(*rxstatus)); | 2391 | sizeof(*rxstatus)); |
2381 | tid_agg_rx->stored_mpdu_num++; | 2392 | tid_agg_rx->stored_mpdu_num++; |
2382 | /* release the buffer until next missing frame */ | 2393 | /* release the buffer until next missing frame */ |
2383 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) | 2394 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) |
2384 | % tid_agg_rx->buf_size; | 2395 | % tid_agg_rx->buf_size; |
2385 | while (tid_agg_rx->reorder_buf[index]) { | 2396 | if (!tid_agg_rx->reorder_buf[index] && |
2386 | /* release the reordered frame back to stack */ | 2397 | tid_agg_rx->stored_mpdu_num > 1) { |
2387 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, | 2398 | /* |
2388 | sizeof(status)); | 2399 | * No buffers ready to be released, but check whether any |
2389 | sband = local->hw.wiphy->bands[status.band]; | 2400 | * frames in the reorder buffer have timed out. |
2390 | if (status.flag & RX_FLAG_HT) | 2401 | */ |
2391 | rate = sband->bitrates; /* TODO: HT rates */ | 2402 | int j; |
2392 | else | 2403 | int skipped = 1; |
2393 | rate = &sband->bitrates[status.rate_idx]; | 2404 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; |
2394 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | 2405 | j = (j + 1) % tid_agg_rx->buf_size) { |
2395 | &status, rate); | 2406 | if (tid_agg_rx->reorder_buf[j] == NULL) { |
2396 | tid_agg_rx->stored_mpdu_num--; | 2407 | skipped++; |
2397 | tid_agg_rx->reorder_buf[index] = NULL; | 2408 | continue; |
2398 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 2409 | } |
2410 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
2411 | HZ / 10)) | ||
2412 | break; | ||
2413 | |||
2414 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
2415 | if (net_ratelimit()) | ||
2416 | printk(KERN_DEBUG "%s: release an RX reorder " | ||
2417 | "frame due to timeout on earlier " | ||
2418 | "frames\n", | ||
2419 | wiphy_name(hw->wiphy)); | ||
2420 | #endif | ||
2421 | ieee80211_release_reorder_frame(hw, tid_agg_rx, j); | ||
2422 | |||
2423 | /* | ||
2424 | * Increment the head seq# also for the skipped slots. | ||
2425 | */ | ||
2426 | tid_agg_rx->head_seq_num = | ||
2427 | (tid_agg_rx->head_seq_num + skipped) & | ||
2428 | SEQ_MASK; | ||
2429 | skipped = 0; | ||
2430 | } | ||
2431 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
2432 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); | ||
2399 | index = seq_sub(tid_agg_rx->head_seq_num, | 2433 | index = seq_sub(tid_agg_rx->head_seq_num, |
2400 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 2434 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; |
2401 | } | 2435 | } |
@@ -2517,6 +2551,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2517 | return; | 2551 | return; |
2518 | } | 2552 | } |
2519 | 2553 | ||
2554 | /* | ||
2555 | * In theory, the block ack reordering should happen after duplicate | ||
2556 | * removal (ieee80211_rx_h_check(), which is an RX handler). As such, | ||
2557 | * the call to ieee80211_rx_reorder_ampdu() should really be moved to | ||
2558 | * happen as a new RX handler between ieee80211_rx_h_check and | ||
2559 | * ieee80211_rx_h_decrypt. This cleanup may eventually happen, but for | ||
2560 | * the time being, the call can be here since RX reorder buf processing | ||
2561 | * will implicitly skip duplicates. We could, in theory at least, | ||
2562 | * process frames that ieee80211_rx_h_passive_scan would drop (e.g., | ||
2563 | * frames from other than operational channel), but that should not | ||
2564 | * happen in normal networks. | ||
2565 | */ | ||
2520 | if (!ieee80211_rx_reorder_ampdu(local, skb, status)) | 2566 | if (!ieee80211_rx_reorder_ampdu(local, skb, status)) |
2521 | __ieee80211_rx_handle_packet(hw, skb, status, rate); | 2567 | __ieee80211_rx_handle_packet(hw, skb, status, rate); |
2522 | 2568 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f25b07feabf9..c99ef8d04d3d 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <net/iw_handler.h> | 21 | #include <net/iw_handler.h> |
22 | 22 | ||
23 | #include "ieee80211_i.h" | 23 | #include "ieee80211_i.h" |
24 | #include "driver-ops.h" | ||
24 | #include "mesh.h" | 25 | #include "mesh.h" |
25 | 26 | ||
26 | #define IEEE80211_PROBE_DELAY (HZ / 33) | 27 | #define IEEE80211_PROBE_DELAY (HZ / 33) |
@@ -202,18 +203,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
202 | return RX_QUEUED; | 203 | return RX_QUEUED; |
203 | } | 204 | } |
204 | 205 | ||
205 | void ieee80211_scan_failed(struct ieee80211_local *local) | ||
206 | { | ||
207 | if (WARN_ON(!local->scan_req)) | ||
208 | return; | ||
209 | |||
210 | /* notify cfg80211 about the failed scan */ | ||
211 | if (local->scan_req != &local->int_scan_req) | ||
212 | cfg80211_scan_done(local->scan_req, true); | ||
213 | |||
214 | local->scan_req = NULL; | ||
215 | } | ||
216 | |||
217 | /* | 206 | /* |
218 | * inform AP that we will go to sleep so that it will buffer the frames | 207 | * inform AP that we will go to sleep so that it will buffer the frames |
219 | * while we scan | 208 | * while we scan |
@@ -274,55 +263,61 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
274 | } | 263 | } |
275 | } | 264 | } |
276 | 265 | ||
266 | static void ieee80211_restore_scan_ies(struct ieee80211_local *local) | ||
267 | { | ||
268 | kfree(local->scan_req->ie); | ||
269 | local->scan_req->ie = local->orig_ies; | ||
270 | local->scan_req->ie_len = local->orig_ies_len; | ||
271 | } | ||
272 | |||
277 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 273 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
278 | { | 274 | { |
279 | struct ieee80211_local *local = hw_to_local(hw); | 275 | struct ieee80211_local *local = hw_to_local(hw); |
280 | struct ieee80211_sub_if_data *sdata; | 276 | struct ieee80211_sub_if_data *sdata; |
277 | bool was_hw_scan; | ||
281 | 278 | ||
282 | if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) | 279 | mutex_lock(&local->scan_mtx); |
283 | return; | ||
284 | 280 | ||
285 | if (WARN_ON(!local->scan_req)) | 281 | if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) { |
282 | mutex_unlock(&local->scan_mtx); | ||
286 | return; | 283 | return; |
284 | } | ||
287 | 285 | ||
288 | if (local->hw_scanning) { | 286 | if (WARN_ON(!local->scan_req)) { |
289 | kfree(local->scan_req->ie); | 287 | mutex_unlock(&local->scan_mtx); |
290 | local->scan_req->ie = local->orig_ies; | 288 | return; |
291 | local->scan_req->ie_len = local->orig_ies_len; | ||
292 | } | 289 | } |
293 | 290 | ||
291 | if (local->hw_scanning) | ||
292 | ieee80211_restore_scan_ies(local); | ||
293 | |||
294 | if (local->scan_req != &local->int_scan_req) | 294 | if (local->scan_req != &local->int_scan_req) |
295 | cfg80211_scan_done(local->scan_req, aborted); | 295 | cfg80211_scan_done(local->scan_req, aborted); |
296 | local->scan_req = NULL; | 296 | local->scan_req = NULL; |
297 | 297 | ||
298 | if (local->hw_scanning) { | 298 | was_hw_scan = local->hw_scanning; |
299 | local->hw_scanning = false; | 299 | local->hw_scanning = false; |
300 | /* | ||
301 | * Somebody might have requested channel change during scan | ||
302 | * that we won't have acted upon, try now. ieee80211_hw_config | ||
303 | * will set the flag based on actual changes. | ||
304 | */ | ||
305 | ieee80211_hw_config(local, 0); | ||
306 | goto done; | ||
307 | } | ||
308 | |||
309 | local->sw_scanning = false; | 300 | local->sw_scanning = false; |
301 | |||
302 | /* we only have to protect scan_req and hw/sw scan */ | ||
303 | mutex_unlock(&local->scan_mtx); | ||
304 | |||
310 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 305 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
306 | if (was_hw_scan) | ||
307 | goto done; | ||
311 | 308 | ||
312 | netif_tx_lock_bh(local->mdev); | 309 | netif_tx_lock_bh(local->mdev); |
313 | netif_addr_lock(local->mdev); | 310 | netif_addr_lock(local->mdev); |
314 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; | 311 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; |
315 | local->ops->configure_filter(local_to_hw(local), | 312 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, |
316 | FIF_BCN_PRBRESP_PROMISC, | 313 | &local->filter_flags, |
317 | &local->filter_flags, | 314 | local->mdev->mc_count, |
318 | local->mdev->mc_count, | 315 | local->mdev->mc_list); |
319 | local->mdev->mc_list); | ||
320 | 316 | ||
321 | netif_addr_unlock(local->mdev); | 317 | netif_addr_unlock(local->mdev); |
322 | netif_tx_unlock_bh(local->mdev); | 318 | netif_tx_unlock_bh(local->mdev); |
323 | 319 | ||
324 | if (local->ops->sw_scan_complete) | 320 | drv_sw_scan_complete(local); |
325 | local->ops->sw_scan_complete(local_to_hw(local)); | ||
326 | 321 | ||
327 | mutex_lock(&local->iflist_mtx); | 322 | mutex_lock(&local->iflist_mtx); |
328 | list_for_each_entry(sdata, &local->interfaces, list) { | 323 | list_for_each_entry(sdata, &local->interfaces, list) { |
@@ -342,18 +337,160 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
342 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 337 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
343 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | 338 | sdata->vif.type == NL80211_IFTYPE_ADHOC || |
344 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | 339 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
345 | ieee80211_if_config(sdata, | 340 | ieee80211_bss_info_change_notify( |
346 | IEEE80211_IFCC_BEACON_ENABLED); | 341 | sdata, BSS_CHANGED_BEACON_ENABLED); |
347 | } | 342 | } |
348 | mutex_unlock(&local->iflist_mtx); | 343 | mutex_unlock(&local->iflist_mtx); |
349 | 344 | ||
350 | done: | 345 | done: |
346 | ieee80211_recalc_idle(local); | ||
351 | ieee80211_mlme_notify_scan_completed(local); | 347 | ieee80211_mlme_notify_scan_completed(local); |
352 | ieee80211_ibss_notify_scan_completed(local); | 348 | ieee80211_ibss_notify_scan_completed(local); |
353 | ieee80211_mesh_notify_scan_completed(local); | 349 | ieee80211_mesh_notify_scan_completed(local); |
354 | } | 350 | } |
355 | EXPORT_SYMBOL(ieee80211_scan_completed); | 351 | EXPORT_SYMBOL(ieee80211_scan_completed); |
356 | 352 | ||
353 | static int ieee80211_start_sw_scan(struct ieee80211_local *local) | ||
354 | { | ||
355 | struct ieee80211_sub_if_data *sdata; | ||
356 | |||
357 | /* | ||
358 | * Hardware/driver doesn't support hw_scan, so use software | ||
359 | * scanning instead. First send a nullfunc frame with power save | ||
360 | * bit on so that AP will buffer the frames for us while we are not | ||
361 | * listening, then send probe requests to each channel and wait for | ||
362 | * the responses. After all channels are scanned, tune back to the | ||
363 | * original channel and send a nullfunc frame with power save bit | ||
364 | * off to trigger the AP to send us all the buffered frames. | ||
365 | * | ||
366 | * Note that while local->sw_scanning is true everything else but | ||
367 | * nullfunc frames and probe requests will be dropped in | ||
368 | * ieee80211_tx_h_check_assoc(). | ||
369 | */ | ||
370 | drv_sw_scan_start(local); | ||
371 | |||
372 | mutex_lock(&local->iflist_mtx); | ||
373 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
374 | if (!netif_running(sdata->dev)) | ||
375 | continue; | ||
376 | |||
377 | /* disable beaconing */ | ||
378 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
379 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
380 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
381 | ieee80211_bss_info_change_notify( | ||
382 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
383 | |||
384 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
385 | if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { | ||
386 | netif_tx_stop_all_queues(sdata->dev); | ||
387 | ieee80211_scan_ps_enable(sdata); | ||
388 | } | ||
389 | } else | ||
390 | netif_tx_stop_all_queues(sdata->dev); | ||
391 | } | ||
392 | mutex_unlock(&local->iflist_mtx); | ||
393 | |||
394 | local->scan_state = SCAN_SET_CHANNEL; | ||
395 | local->scan_channel_idx = 0; | ||
396 | |||
397 | netif_addr_lock_bh(local->mdev); | ||
398 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | ||
399 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, | ||
400 | &local->filter_flags, | ||
401 | local->mdev->mc_count, | ||
402 | local->mdev->mc_list); | ||
403 | netif_addr_unlock_bh(local->mdev); | ||
404 | |||
405 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | ||
406 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
407 | IEEE80211_CHANNEL_TIME); | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | |||
413 | static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | ||
414 | struct cfg80211_scan_request *req) | ||
415 | { | ||
416 | struct ieee80211_local *local = sdata->local; | ||
417 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
418 | int rc; | ||
419 | |||
420 | if (local->scan_req) | ||
421 | return -EBUSY; | ||
422 | |||
423 | if (local->ops->hw_scan) { | ||
424 | u8 *ies; | ||
425 | int ielen; | ||
426 | |||
427 | ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN + | ||
428 | local->scan_ies_len + req->ie_len, GFP_KERNEL); | ||
429 | if (!ies) | ||
430 | return -ENOMEM; | ||
431 | |||
432 | ielen = ieee80211_build_preq_ies(local, ies, | ||
433 | req->ie, req->ie_len); | ||
434 | local->orig_ies = req->ie; | ||
435 | local->orig_ies_len = req->ie_len; | ||
436 | req->ie = ies; | ||
437 | req->ie_len = ielen; | ||
438 | } | ||
439 | |||
440 | local->scan_req = req; | ||
441 | local->scan_sdata = sdata; | ||
442 | |||
443 | if (req != &local->int_scan_req && | ||
444 | sdata->vif.type == NL80211_IFTYPE_STATION && | ||
445 | (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE || | ||
446 | ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE || | ||
447 | ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE)) { | ||
448 | /* actually wait for the assoc to finish/time out */ | ||
449 | set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | if (local->ops->hw_scan) | ||
454 | local->hw_scanning = true; | ||
455 | else | ||
456 | local->sw_scanning = true; | ||
457 | /* | ||
458 | * Kicking off the scan need not be protected, | ||
459 | * only the scan variable stuff, since now | ||
460 | * local->scan_req is assigned and other callers | ||
461 | * will abort their scan attempts. | ||
462 | * | ||
463 | * This avoids getting a scan_mtx -> iflist_mtx | ||
464 | * dependency, so that the scan completed calls | ||
465 | * have more locking freedom. | ||
466 | */ | ||
467 | |||
468 | ieee80211_recalc_idle(local); | ||
469 | mutex_unlock(&local->scan_mtx); | ||
470 | |||
471 | if (local->ops->hw_scan) | ||
472 | rc = drv_hw_scan(local, local->scan_req); | ||
473 | else | ||
474 | rc = ieee80211_start_sw_scan(local); | ||
475 | |||
476 | mutex_lock(&local->scan_mtx); | ||
477 | |||
478 | if (rc) { | ||
479 | if (local->ops->hw_scan) { | ||
480 | local->hw_scanning = false; | ||
481 | ieee80211_restore_scan_ies(local); | ||
482 | } else | ||
483 | local->sw_scanning = false; | ||
484 | |||
485 | ieee80211_recalc_idle(local); | ||
486 | |||
487 | local->scan_req = NULL; | ||
488 | local->scan_sdata = NULL; | ||
489 | } | ||
490 | |||
491 | return rc; | ||
492 | } | ||
493 | |||
357 | void ieee80211_scan_work(struct work_struct *work) | 494 | void ieee80211_scan_work(struct work_struct *work) |
358 | { | 495 | { |
359 | struct ieee80211_local *local = | 496 | struct ieee80211_local *local = |
@@ -363,17 +500,41 @@ void ieee80211_scan_work(struct work_struct *work) | |||
363 | int skip, i; | 500 | int skip, i; |
364 | unsigned long next_delay = 0; | 501 | unsigned long next_delay = 0; |
365 | 502 | ||
503 | mutex_lock(&local->scan_mtx); | ||
504 | if (!sdata || !local->scan_req) { | ||
505 | mutex_unlock(&local->scan_mtx); | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | if (local->scan_req && !(local->sw_scanning || local->hw_scanning)) { | ||
510 | struct cfg80211_scan_request *req = local->scan_req; | ||
511 | int rc; | ||
512 | |||
513 | local->scan_req = NULL; | ||
514 | |||
515 | rc = __ieee80211_start_scan(sdata, req); | ||
516 | mutex_unlock(&local->scan_mtx); | ||
517 | |||
518 | if (rc) | ||
519 | ieee80211_scan_completed(&local->hw, true); | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | mutex_unlock(&local->scan_mtx); | ||
524 | |||
366 | /* | 525 | /* |
367 | * Avoid re-scheduling when the sdata is going away. | 526 | * Avoid re-scheduling when the sdata is going away. |
368 | */ | 527 | */ |
369 | if (!netif_running(sdata->dev)) | 528 | if (!netif_running(sdata->dev)) { |
529 | ieee80211_scan_completed(&local->hw, true); | ||
370 | return; | 530 | return; |
531 | } | ||
371 | 532 | ||
372 | switch (local->scan_state) { | 533 | switch (local->scan_state) { |
373 | case SCAN_SET_CHANNEL: | 534 | case SCAN_SET_CHANNEL: |
374 | /* if no more bands/channels left, complete scan */ | 535 | /* if no more bands/channels left, complete scan */ |
375 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | 536 | if (local->scan_channel_idx >= local->scan_req->n_channels) { |
376 | ieee80211_scan_completed(local_to_hw(local), false); | 537 | ieee80211_scan_completed(&local->hw, false); |
377 | return; | 538 | return; |
378 | } | 539 | } |
379 | skip = 0; | 540 | skip = 0; |
@@ -422,166 +583,35 @@ void ieee80211_scan_work(struct work_struct *work) | |||
422 | next_delay); | 583 | next_delay); |
423 | } | 584 | } |
424 | 585 | ||
425 | 586 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |
426 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | 587 | struct cfg80211_scan_request *req) |
427 | struct cfg80211_scan_request *req) | ||
428 | { | 588 | { |
429 | struct ieee80211_local *local = scan_sdata->local; | 589 | int res; |
430 | struct ieee80211_sub_if_data *sdata; | ||
431 | |||
432 | if (!req) | ||
433 | return -EINVAL; | ||
434 | |||
435 | if (local->scan_req && local->scan_req != req) | ||
436 | return -EBUSY; | ||
437 | |||
438 | local->scan_req = req; | ||
439 | 590 | ||
440 | /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) | 591 | mutex_lock(&sdata->local->scan_mtx); |
441 | * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS | 592 | res = __ieee80211_start_scan(sdata, req); |
442 | * BSSID: MACAddress | 593 | mutex_unlock(&sdata->local->scan_mtx); |
443 | * SSID | ||
444 | * ScanType: ACTIVE, PASSIVE | ||
445 | * ProbeDelay: delay (in microseconds) to be used prior to transmitting | ||
446 | * a Probe frame during active scanning | ||
447 | * ChannelList | ||
448 | * MinChannelTime (>= ProbeDelay), in TU | ||
449 | * MaxChannelTime: (>= MinChannelTime), in TU | ||
450 | */ | ||
451 | 594 | ||
452 | /* MLME-SCAN.confirm | 595 | return res; |
453 | * BSSDescriptionSet | ||
454 | * ResultCode: SUCCESS, INVALID_PARAMETERS | ||
455 | */ | ||
456 | |||
457 | if (local->sw_scanning || local->hw_scanning) { | ||
458 | if (local->scan_sdata == scan_sdata) | ||
459 | return 0; | ||
460 | return -EBUSY; | ||
461 | } | ||
462 | |||
463 | if (local->ops->hw_scan) { | ||
464 | u8 *ies; | ||
465 | int rc, ielen; | ||
466 | |||
467 | ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN + | ||
468 | local->scan_ies_len + req->ie_len, GFP_KERNEL); | ||
469 | if (!ies) | ||
470 | return -ENOMEM; | ||
471 | |||
472 | ielen = ieee80211_build_preq_ies(local, ies, | ||
473 | req->ie, req->ie_len); | ||
474 | local->orig_ies = req->ie; | ||
475 | local->orig_ies_len = req->ie_len; | ||
476 | req->ie = ies; | ||
477 | req->ie_len = ielen; | ||
478 | |||
479 | local->hw_scanning = true; | ||
480 | rc = local->ops->hw_scan(local_to_hw(local), req); | ||
481 | if (rc) { | ||
482 | local->hw_scanning = false; | ||
483 | kfree(ies); | ||
484 | req->ie_len = local->orig_ies_len; | ||
485 | req->ie = local->orig_ies; | ||
486 | return rc; | ||
487 | } | ||
488 | local->scan_sdata = scan_sdata; | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | /* | ||
493 | * Hardware/driver doesn't support hw_scan, so use software | ||
494 | * scanning instead. First send a nullfunc frame with power save | ||
495 | * bit on so that AP will buffer the frames for us while we are not | ||
496 | * listening, then send probe requests to each channel and wait for | ||
497 | * the responses. After all channels are scanned, tune back to the | ||
498 | * original channel and send a nullfunc frame with power save bit | ||
499 | * off to trigger the AP to send us all the buffered frames. | ||
500 | * | ||
501 | * Note that while local->sw_scanning is true everything else but | ||
502 | * nullfunc frames and probe requests will be dropped in | ||
503 | * ieee80211_tx_h_check_assoc(). | ||
504 | */ | ||
505 | local->sw_scanning = true; | ||
506 | if (local->ops->sw_scan_start) | ||
507 | local->ops->sw_scan_start(local_to_hw(local)); | ||
508 | |||
509 | mutex_lock(&local->iflist_mtx); | ||
510 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
511 | if (!netif_running(sdata->dev)) | ||
512 | continue; | ||
513 | |||
514 | /* disable beaconing */ | ||
515 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
516 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
517 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
518 | ieee80211_if_config(sdata, | ||
519 | IEEE80211_IFCC_BEACON_ENABLED); | ||
520 | |||
521 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
522 | if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { | ||
523 | netif_tx_stop_all_queues(sdata->dev); | ||
524 | ieee80211_scan_ps_enable(sdata); | ||
525 | } | ||
526 | } else | ||
527 | netif_tx_stop_all_queues(sdata->dev); | ||
528 | } | ||
529 | mutex_unlock(&local->iflist_mtx); | ||
530 | |||
531 | local->scan_state = SCAN_SET_CHANNEL; | ||
532 | local->scan_channel_idx = 0; | ||
533 | local->scan_sdata = scan_sdata; | ||
534 | local->scan_req = req; | ||
535 | |||
536 | netif_addr_lock_bh(local->mdev); | ||
537 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | ||
538 | local->ops->configure_filter(local_to_hw(local), | ||
539 | FIF_BCN_PRBRESP_PROMISC, | ||
540 | &local->filter_flags, | ||
541 | local->mdev->mc_count, | ||
542 | local->mdev->mc_list); | ||
543 | netif_addr_unlock_bh(local->mdev); | ||
544 | |||
545 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | ||
546 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
547 | IEEE80211_CHANNEL_TIME); | ||
548 | |||
549 | return 0; | ||
550 | } | 596 | } |
551 | 597 | ||
552 | 598 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |
553 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 599 | const u8 *ssid, u8 ssid_len) |
554 | struct cfg80211_scan_request *req) | ||
555 | { | 600 | { |
556 | struct ieee80211_local *local = sdata->local; | 601 | struct ieee80211_local *local = sdata->local; |
557 | struct ieee80211_if_managed *ifmgd; | 602 | int ret = -EBUSY; |
558 | |||
559 | if (!req) | ||
560 | return -EINVAL; | ||
561 | |||
562 | if (local->scan_req && local->scan_req != req) | ||
563 | return -EBUSY; | ||
564 | |||
565 | local->scan_req = req; | ||
566 | 603 | ||
567 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 604 | mutex_lock(&local->scan_mtx); |
568 | return ieee80211_start_scan(sdata, req); | ||
569 | 605 | ||
570 | /* | 606 | /* busy scanning */ |
571 | * STA has a state machine that might need to defer scanning | 607 | if (local->scan_req) |
572 | * while it's trying to associate/authenticate, therefore we | 608 | goto unlock; |
573 | * queue it up to the state machine in that case. | ||
574 | */ | ||
575 | 609 | ||
576 | if (local->sw_scanning || local->hw_scanning) { | 610 | memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); |
577 | if (local->scan_sdata == sdata) | 611 | local->int_scan_req.ssids[0].ssid_len = ssid_len; |
578 | return 0; | ||
579 | return -EBUSY; | ||
580 | } | ||
581 | |||
582 | ifmgd = &sdata->u.mgd; | ||
583 | set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); | ||
584 | queue_work(local->hw.workqueue, &ifmgd->work); | ||
585 | 612 | ||
586 | return 0; | 613 | ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req); |
614 | unlock: | ||
615 | mutex_unlock(&local->scan_mtx); | ||
616 | return ret; | ||
587 | } | 617 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 654a8e963ccb..a98ea273a155 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
21 | #include "ieee80211_i.h" | 21 | #include "ieee80211_i.h" |
22 | #include "driver-ops.h" | ||
22 | #include "rate.h" | 23 | #include "rate.h" |
23 | #include "sta_info.h" | 24 | #include "sta_info.h" |
24 | #include "debugfs_sta.h" | 25 | #include "debugfs_sta.h" |
@@ -346,8 +347,7 @@ int sta_info_insert(struct sta_info *sta) | |||
346 | struct ieee80211_sub_if_data, | 347 | struct ieee80211_sub_if_data, |
347 | u.ap); | 348 | u.ap); |
348 | 349 | ||
349 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 350 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); |
350 | STA_NOTIFY_ADD, &sta->sta); | ||
351 | } | 351 | } |
352 | 352 | ||
353 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 353 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -405,8 +405,7 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | |||
405 | 405 | ||
406 | if (sta->local->ops->set_tim) { | 406 | if (sta->local->ops->set_tim) { |
407 | sta->local->tim_in_locked_section = true; | 407 | sta->local->tim_in_locked_section = true; |
408 | sta->local->ops->set_tim(local_to_hw(sta->local), | 408 | drv_set_tim(sta->local, &sta->sta, true); |
409 | &sta->sta, true); | ||
410 | sta->local->tim_in_locked_section = false; | 409 | sta->local->tim_in_locked_section = false; |
411 | } | 410 | } |
412 | } | 411 | } |
@@ -431,8 +430,7 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | |||
431 | 430 | ||
432 | if (sta->local->ops->set_tim) { | 431 | if (sta->local->ops->set_tim) { |
433 | sta->local->tim_in_locked_section = true; | 432 | sta->local->tim_in_locked_section = true; |
434 | sta->local->ops->set_tim(local_to_hw(sta->local), | 433 | drv_set_tim(sta->local, &sta->sta, false); |
435 | &sta->sta, false); | ||
436 | sta->local->tim_in_locked_section = false; | 434 | sta->local->tim_in_locked_section = false; |
437 | } | 435 | } |
438 | } | 436 | } |
@@ -482,8 +480,8 @@ static void __sta_info_unlink(struct sta_info **sta) | |||
482 | struct ieee80211_sub_if_data, | 480 | struct ieee80211_sub_if_data, |
483 | u.ap); | 481 | u.ap); |
484 | 482 | ||
485 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 483 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, |
486 | STA_NOTIFY_REMOVE, &(*sta)->sta); | 484 | &(*sta)->sta); |
487 | } | 485 | } |
488 | 486 | ||
489 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 487 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
@@ -543,9 +541,8 @@ void sta_info_unlink(struct sta_info **sta) | |||
543 | spin_unlock_irqrestore(&local->sta_lock, flags); | 541 | spin_unlock_irqrestore(&local->sta_lock, flags); |
544 | } | 542 | } |
545 | 543 | ||
546 | static inline int sta_info_buffer_expired(struct ieee80211_local *local, | 544 | static int sta_info_buffer_expired(struct sta_info *sta, |
547 | struct sta_info *sta, | 545 | struct sk_buff *skb) |
548 | struct sk_buff *skb) | ||
549 | { | 546 | { |
550 | struct ieee80211_tx_info *info; | 547 | struct ieee80211_tx_info *info; |
551 | int timeout; | 548 | int timeout; |
@@ -556,8 +553,9 @@ static inline int sta_info_buffer_expired(struct ieee80211_local *local, | |||
556 | info = IEEE80211_SKB_CB(skb); | 553 | info = IEEE80211_SKB_CB(skb); |
557 | 554 | ||
558 | /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */ | 555 | /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */ |
559 | timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 / | 556 | timeout = (sta->listen_interval * |
560 | 15625) * HZ; | 557 | sta->sdata->vif.bss_conf.beacon_int * |
558 | 32 / 15625) * HZ; | ||
561 | if (timeout < STA_TX_BUFFER_EXPIRE) | 559 | if (timeout < STA_TX_BUFFER_EXPIRE) |
562 | timeout = STA_TX_BUFFER_EXPIRE; | 560 | timeout = STA_TX_BUFFER_EXPIRE; |
563 | return time_after(jiffies, info->control.jiffies + timeout); | 561 | return time_after(jiffies, info->control.jiffies + timeout); |
@@ -577,7 +575,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
577 | for (;;) { | 575 | for (;;) { |
578 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); | 576 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); |
579 | skb = skb_peek(&sta->ps_tx_buf); | 577 | skb = skb_peek(&sta->ps_tx_buf); |
580 | if (sta_info_buffer_expired(local, sta, skb)) | 578 | if (sta_info_buffer_expired(sta, skb)) |
581 | skb = __skb_dequeue(&sta->ps_tx_buf); | 579 | skb = __skb_dequeue(&sta->ps_tx_buf); |
582 | else | 580 | else |
583 | skb = NULL; | 581 | skb = NULL; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 31a8990ce401..164b16cbe0a5 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -88,6 +88,7 @@ struct tid_ampdu_tx { | |||
88 | * struct tid_ampdu_rx - TID aggregation information (Rx). | 88 | * struct tid_ampdu_rx - TID aggregation information (Rx). |
89 | * | 89 | * |
90 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs | 90 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs |
91 | * @reorder_time: jiffies when skb was added | ||
91 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) | 92 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) |
92 | * @head_seq_num: head sequence number in reordering buffer. | 93 | * @head_seq_num: head sequence number in reordering buffer. |
93 | * @stored_mpdu_num: number of MPDUs in reordering buffer | 94 | * @stored_mpdu_num: number of MPDUs in reordering buffer |
@@ -99,6 +100,7 @@ struct tid_ampdu_tx { | |||
99 | */ | 100 | */ |
100 | struct tid_ampdu_rx { | 101 | struct tid_ampdu_rx { |
101 | struct sk_buff **reorder_buf; | 102 | struct sk_buff **reorder_buf; |
103 | unsigned long *reorder_time; | ||
102 | struct timer_list session_timer; | 104 | struct timer_list session_timer; |
103 | u16 head_seq_num; | 105 | u16 head_seq_num; |
104 | u16 stored_mpdu_num; | 106 | u16 stored_mpdu_num; |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 38fa111d2dc6..964b7faa7f17 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/unaligned.h> | 13 | #include <asm/unaligned.h> |
14 | 14 | ||
15 | #include <net/mac80211.h> | 15 | #include <net/mac80211.h> |
16 | #include "driver-ops.h" | ||
16 | #include "key.h" | 17 | #include "key.h" |
17 | #include "tkip.h" | 18 | #include "tkip.h" |
18 | #include "wep.h" | 19 | #include "wep.h" |
@@ -307,9 +308,8 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
307 | if (is_multicast_ether_addr(ra)) | 308 | if (is_multicast_ether_addr(ra)) |
308 | sta_addr = bcast; | 309 | sta_addr = bcast; |
309 | 310 | ||
310 | key->local->ops->update_tkip_key( | 311 | drv_update_tkip_key(key->local, &key->conf, sta_addr, |
311 | local_to_hw(key->local), &key->conf, | 312 | iv32, key->u.tkip.rx[queue].p1k); |
312 | sta_addr, iv32, key->u.tkip.rx[queue].p1k); | ||
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e5b148fe24bb..5f9a8d7af83d 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/unaligned.h> | 25 | #include <asm/unaligned.h> |
26 | 26 | ||
27 | #include "ieee80211_i.h" | 27 | #include "ieee80211_i.h" |
28 | #include "driver-ops.h" | ||
28 | #include "led.h" | 29 | #include "led.h" |
29 | #include "mesh.h" | 30 | #include "mesh.h" |
30 | #include "wep.h" | 31 | #include "wep.h" |
@@ -557,6 +558,10 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
557 | if (unlikely(!info->control.rates[0].count)) | 558 | if (unlikely(!info->control.rates[0].count)) |
558 | info->control.rates[0].count = 1; | 559 | info->control.rates[0].count = 1; |
559 | 560 | ||
561 | if (WARN_ON_ONCE((info->control.rates[0].count > 1) && | ||
562 | (info->flags & IEEE80211_TX_CTL_NO_ACK))) | ||
563 | info->control.rates[0].count = 1; | ||
564 | |||
560 | if (is_multicast_ether_addr(hdr->addr1)) { | 565 | if (is_multicast_ether_addr(hdr->addr1)) { |
561 | /* | 566 | /* |
562 | * XXX: verify the rate is in the basic rateset | 567 | * XXX: verify the rate is in the basic rateset |
@@ -1162,7 +1167,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1162 | 1167 | ||
1163 | next = skb->next; | 1168 | next = skb->next; |
1164 | len = skb->len; | 1169 | len = skb->len; |
1165 | ret = local->ops->tx(local_to_hw(local), skb); | 1170 | ret = drv_tx(local, skb); |
1166 | if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { | 1171 | if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { |
1167 | dev_kfree_skb(skb); | 1172 | dev_kfree_skb(skb); |
1168 | ret = NETDEV_TX_OK; | 1173 | ret = NETDEV_TX_OK; |
@@ -2132,7 +2137,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
2132 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 2137 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
2133 | /* BSSID is left zeroed, wildcard value */ | 2138 | /* BSSID is left zeroed, wildcard value */ |
2134 | mgmt->u.beacon.beacon_int = | 2139 | mgmt->u.beacon.beacon_int = |
2135 | cpu_to_le16(local->hw.conf.beacon_int); | 2140 | cpu_to_le16(sdata->vif.bss_conf.beacon_int); |
2136 | mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ | 2141 | mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ |
2137 | 2142 | ||
2138 | pos = skb_put(skb, 2); | 2143 | pos = skb_put(skb, 2); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 61876eb50b49..97b613affe08 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <net/rtnetlink.h> | 26 | #include <net/rtnetlink.h> |
27 | 27 | ||
28 | #include "ieee80211_i.h" | 28 | #include "ieee80211_i.h" |
29 | #include "driver-ops.h" | ||
29 | #include "rate.h" | 30 | #include "rate.h" |
30 | #include "mesh.h" | 31 | #include "mesh.h" |
31 | #include "wme.h" | 32 | #include "wme.h" |
@@ -726,7 +727,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
726 | qparam.txop = 0; | 727 | qparam.txop = 0; |
727 | 728 | ||
728 | for (i = 0; i < local_to_hw(local)->queues; i++) | 729 | for (i = 0; i < local_to_hw(local)->queues; i++) |
729 | local->ops->conf_tx(local_to_hw(local), i, &qparam); | 730 | drv_conf_tx(local, i, &qparam); |
730 | } | 731 | } |
731 | 732 | ||
732 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 733 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
@@ -1000,7 +1001,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1000 | 1001 | ||
1001 | /* restart hardware */ | 1002 | /* restart hardware */ |
1002 | if (local->open_count) { | 1003 | if (local->open_count) { |
1003 | res = local->ops->start(hw); | 1004 | res = drv_start(local); |
1004 | 1005 | ||
1005 | ieee80211_led_radio(local, hw->conf.radio_enabled); | 1006 | ieee80211_led_radio(local, hw->conf.radio_enabled); |
1006 | } | 1007 | } |
@@ -1013,7 +1014,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1013 | conf.vif = &sdata->vif; | 1014 | conf.vif = &sdata->vif; |
1014 | conf.type = sdata->vif.type; | 1015 | conf.type = sdata->vif.type; |
1015 | conf.mac_addr = sdata->dev->dev_addr; | 1016 | conf.mac_addr = sdata->dev->dev_addr; |
1016 | res = local->ops->add_interface(hw, &conf); | 1017 | res = drv_add_interface(local, &conf); |
1017 | } | 1018 | } |
1018 | } | 1019 | } |
1019 | 1020 | ||
@@ -1026,8 +1027,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1026 | struct ieee80211_sub_if_data, | 1027 | struct ieee80211_sub_if_data, |
1027 | u.ap); | 1028 | u.ap); |
1028 | 1029 | ||
1029 | local->ops->sta_notify(hw, &sdata->vif, | 1030 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, |
1030 | STA_NOTIFY_ADD, &sta->sta); | 1031 | &sta->sta); |
1031 | } | 1032 | } |
1032 | spin_unlock_irqrestore(&local->sta_lock, flags); | 1033 | spin_unlock_irqrestore(&local->sta_lock, flags); |
1033 | } | 1034 | } |
@@ -1045,8 +1046,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1045 | rcu_read_unlock(); | 1046 | rcu_read_unlock(); |
1046 | 1047 | ||
1047 | /* setup RTS threshold */ | 1048 | /* setup RTS threshold */ |
1048 | if (local->ops->set_rts_threshold) | 1049 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); |
1049 | local->ops->set_rts_threshold(hw, hw->wiphy->rts_threshold); | ||
1050 | 1050 | ||
1051 | /* reconfigure hardware */ | 1051 | /* reconfigure hardware */ |
1052 | ieee80211_hw_config(local, ~0); | 1052 | ieee80211_hw_config(local, ~0); |
@@ -1063,24 +1063,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1063 | switch (sdata->vif.type) { | 1063 | switch (sdata->vif.type) { |
1064 | case NL80211_IFTYPE_STATION: | 1064 | case NL80211_IFTYPE_STATION: |
1065 | /* disable beacon change bits */ | 1065 | /* disable beacon change bits */ |
1066 | changed &= ~IEEE80211_IFCC_BEACON; | 1066 | changed &= ~(BSS_CHANGED_BEACON | |
1067 | BSS_CHANGED_BEACON_ENABLED); | ||
1067 | /* fall through */ | 1068 | /* fall through */ |
1068 | case NL80211_IFTYPE_ADHOC: | 1069 | case NL80211_IFTYPE_ADHOC: |
1069 | case NL80211_IFTYPE_AP: | 1070 | case NL80211_IFTYPE_AP: |
1070 | case NL80211_IFTYPE_MESH_POINT: | 1071 | case NL80211_IFTYPE_MESH_POINT: |
1071 | /* | 1072 | ieee80211_bss_info_change_notify(sdata, changed); |
1072 | * Driver's config_interface can fail if rfkill is | ||
1073 | * enabled. Accommodate this return code. | ||
1074 | * FIXME: When mac80211 has knowledge of rfkill | ||
1075 | * state the code below can change back to: | ||
1076 | * WARN(ieee80211_if_config(sdata, changed)); | ||
1077 | * ieee80211_bss_info_change_notify(sdata, ~0); | ||
1078 | */ | ||
1079 | if (ieee80211_if_config(sdata, changed)) | ||
1080 | printk(KERN_DEBUG "%s: failed to configure interface during resume\n", | ||
1081 | sdata->dev->name); | ||
1082 | else | ||
1083 | ieee80211_bss_info_change_notify(sdata, ~0); | ||
1084 | break; | 1073 | break; |
1085 | case NL80211_IFTYPE_WDS: | 1074 | case NL80211_IFTYPE_WDS: |
1086 | break; | 1075 | break; |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 1a649da42c41..6b4eb8d43a4e 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -185,7 +185,7 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev, | |||
185 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 185 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
186 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | 186 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); |
187 | 187 | ||
188 | freq->m = local->hw.conf.channel->center_freq; | 188 | freq->m = local->oper_channel->center_freq; |
189 | freq->e = 6; | 189 | freq->e = 6; |
190 | 190 | ||
191 | return 0; | 191 | return 0; |
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index e2d4510623f2..4f5a83183c95 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
@@ -75,6 +75,11 @@ static void rfkill_led_trigger_activate(struct led_classdev *led) | |||
75 | 75 | ||
76 | rfkill_led_trigger(rfkill, rfkill->state); | 76 | rfkill_led_trigger(rfkill, rfkill->state); |
77 | } | 77 | } |
78 | #else | ||
79 | static inline void rfkill_led_trigger(struct rfkill *rfkill, | ||
80 | enum rfkill_state state) | ||
81 | { | ||
82 | } | ||
78 | #endif /* CONFIG_RFKILL_LEDS */ | 83 | #endif /* CONFIG_RFKILL_LEDS */ |
79 | 84 | ||
80 | static void rfkill_uevent(struct rfkill *rfkill) | 85 | static void rfkill_uevent(struct rfkill *rfkill) |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b1fc98225fd1..3c53c5cbc3a9 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3696,9 +3696,9 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, | |||
3696 | NL80211_CMD_DISASSOCIATE); | 3696 | NL80211_CMD_DISASSOCIATE); |
3697 | } | 3697 | } |
3698 | 3698 | ||
3699 | void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, | 3699 | static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, |
3700 | struct net_device *netdev, int cmd, | 3700 | struct net_device *netdev, int cmd, |
3701 | const u8 *addr) | 3701 | const u8 *addr) |
3702 | { | 3702 | { |
3703 | struct sk_buff *msg; | 3703 | struct sk_buff *msg; |
3704 | void *hdr; | 3704 | void *hdr; |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 139d13fdc94f..537af62ec42b 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -2113,14 +2113,14 @@ void reg_device_remove(struct wiphy *wiphy) | |||
2113 | 2113 | ||
2114 | assert_cfg80211_lock(); | 2114 | assert_cfg80211_lock(); |
2115 | 2115 | ||
2116 | kfree(wiphy->regd); | ||
2117 | |||
2116 | if (last_request) | 2118 | if (last_request) |
2117 | request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | 2119 | request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); |
2118 | 2120 | ||
2119 | kfree(wiphy->regd); | 2121 | if (!request_wiphy || request_wiphy != wiphy) |
2120 | if (!last_request || !request_wiphy) | ||
2121 | return; | ||
2122 | if (request_wiphy != wiphy) | ||
2123 | return; | 2122 | return; |
2123 | |||
2124 | last_request->wiphy_idx = WIPHY_IDX_STALE; | 2124 | last_request->wiphy_idx = WIPHY_IDX_STALE; |
2125 | last_request->country_ie_env = ENVIRON_ANY; | 2125 | last_request->country_ie_env = ENVIRON_ANY; |
2126 | } | 2126 | } |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index dfb53d19fd77..df59440290e5 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -377,18 +377,16 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
377 | size_t used = dev->wiphy.bss_priv_size + sizeof(*res); | 377 | size_t used = dev->wiphy.bss_priv_size + sizeof(*res); |
378 | size_t ielen = res->pub.len_information_elements; | 378 | size_t ielen = res->pub.len_information_elements; |
379 | 379 | ||
380 | if (ksize(found) >= used + ielen) { | 380 | if (!found->ies_allocated && ksize(found) >= used + ielen) { |
381 | memcpy(found->pub.information_elements, | 381 | memcpy(found->pub.information_elements, |
382 | res->pub.information_elements, ielen); | 382 | res->pub.information_elements, ielen); |
383 | found->pub.len_information_elements = ielen; | 383 | found->pub.len_information_elements = ielen; |
384 | } else { | 384 | } else { |
385 | u8 *ies = found->pub.information_elements; | 385 | u8 *ies = found->pub.information_elements; |
386 | 386 | ||
387 | if (found->ies_allocated) { | 387 | if (found->ies_allocated) |
388 | if (ksize(ies) < ielen) | 388 | ies = krealloc(ies, ielen, GFP_ATOMIC); |
389 | ies = krealloc(ies, ielen, | 389 | else |
390 | GFP_ATOMIC); | ||
391 | } else | ||
392 | ies = kmalloc(ielen, GFP_ATOMIC); | 390 | ies = kmalloc(ielen, GFP_ATOMIC); |
393 | 391 | ||
394 | if (ies) { | 392 | if (ies) { |