diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-rx.c | 8 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 16 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 79 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 3 | ||||
-rw-r--r-- | net/mac80211/ht.c | 17 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 65 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 20 | ||||
-rw-r--r-- | net/mac80211/iface.c | 50 | ||||
-rw-r--r-- | net/mac80211/key.c | 95 | ||||
-rw-r--r-- | net/mac80211/key.h | 3 | ||||
-rw-r--r-- | net/mac80211/main.c | 27 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 33 | ||||
-rw-r--r-- | net/mac80211/pm.c | 5 | ||||
-rw-r--r-- | net/mac80211/rx.c | 42 | ||||
-rw-r--r-- | net/mac80211/scan.c | 154 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 12 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 8 | ||||
-rw-r--r-- | net/mac80211/status.c | 6 | ||||
-rw-r--r-- | net/mac80211/tx.c | 5 | ||||
-rw-r--r-- | net/mac80211/util.c | 22 |
20 files changed, 410 insertions, 260 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 58eab9e8e4ee..720b7a84af59 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -56,7 +56,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) | |||
56 | } | 56 | } |
57 | 57 | ||
58 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 58 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
59 | u16 initiator, u16 reason) | 59 | u16 initiator, u16 reason, bool tx) |
60 | { | 60 | { |
61 | struct ieee80211_local *local = sta->local; | 61 | struct ieee80211_local *local = sta->local; |
62 | struct tid_ampdu_rx *tid_rx; | 62 | struct tid_ampdu_rx *tid_rx; |
@@ -81,7 +81,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
81 | "aggregation for tid %d\n", tid); | 81 | "aggregation for tid %d\n", tid); |
82 | 82 | ||
83 | /* check if this is a self generated aggregation halt */ | 83 | /* check if this is a self generated aggregation halt */ |
84 | if (initiator == WLAN_BACK_RECIPIENT) | 84 | if (initiator == WLAN_BACK_RECIPIENT && tx) |
85 | ieee80211_send_delba(sta->sdata, sta->sta.addr, | 85 | ieee80211_send_delba(sta->sdata, sta->sta.addr, |
86 | tid, 0, reason); | 86 | tid, 0, reason); |
87 | 87 | ||
@@ -92,10 +92,10 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
92 | } | 92 | } |
93 | 93 | ||
94 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 94 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
95 | u16 initiator, u16 reason) | 95 | u16 initiator, u16 reason, bool tx) |
96 | { | 96 | { |
97 | mutex_lock(&sta->ampdu_mlme.mtx); | 97 | mutex_lock(&sta->ampdu_mlme.mtx); |
98 | ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); | 98 | ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx); |
99 | mutex_unlock(&sta->ampdu_mlme.mtx); | 99 | mutex_unlock(&sta->ampdu_mlme.mtx); |
100 | } | 100 | } |
101 | 101 | ||
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index c893f236acea..d4679b265ba8 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -145,7 +145,8 @@ static void kfree_tid_tx(struct rcu_head *rcu_head) | |||
145 | } | 145 | } |
146 | 146 | ||
147 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 147 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
148 | enum ieee80211_back_parties initiator) | 148 | enum ieee80211_back_parties initiator, |
149 | bool tx) | ||
149 | { | 150 | { |
150 | struct ieee80211_local *local = sta->local; | 151 | struct ieee80211_local *local = sta->local; |
151 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 152 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; |
@@ -175,6 +176,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
175 | 176 | ||
176 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); | 177 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); |
177 | 178 | ||
179 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
180 | |||
178 | /* | 181 | /* |
179 | * After this packets are no longer handed right through | 182 | * After this packets are no longer handed right through |
180 | * to the driver but are put onto tid_tx->pending instead, | 183 | * to the driver but are put onto tid_tx->pending instead, |
@@ -183,6 +186,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
183 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); | 186 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); |
184 | 187 | ||
185 | tid_tx->stop_initiator = initiator; | 188 | tid_tx->stop_initiator = initiator; |
189 | tid_tx->tx_stop = tx; | ||
186 | 190 | ||
187 | ret = drv_ampdu_action(local, sta->sdata, | 191 | ret = drv_ampdu_action(local, sta->sdata, |
188 | IEEE80211_AMPDU_TX_STOP, | 192 | IEEE80211_AMPDU_TX_STOP, |
@@ -575,13 +579,14 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
575 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | 579 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); |
576 | 580 | ||
577 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 581 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
578 | enum ieee80211_back_parties initiator) | 582 | enum ieee80211_back_parties initiator, |
583 | bool tx) | ||
579 | { | 584 | { |
580 | int ret; | 585 | int ret; |
581 | 586 | ||
582 | mutex_lock(&sta->ampdu_mlme.mtx); | 587 | mutex_lock(&sta->ampdu_mlme.mtx); |
583 | 588 | ||
584 | ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator); | 589 | ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator, tx); |
585 | 590 | ||
586 | mutex_unlock(&sta->ampdu_mlme.mtx); | 591 | mutex_unlock(&sta->ampdu_mlme.mtx); |
587 | 592 | ||
@@ -670,7 +675,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
670 | goto unlock_sta; | 675 | goto unlock_sta; |
671 | } | 676 | } |
672 | 677 | ||
673 | if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR) | 678 | if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR && tid_tx->tx_stop) |
674 | ieee80211_send_delba(sta->sdata, ra, tid, | 679 | ieee80211_send_delba(sta->sdata, ra, tid, |
675 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | 680 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); |
676 | 681 | ||
@@ -770,7 +775,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
770 | 775 | ||
771 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 776 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
772 | } else { | 777 | } else { |
773 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); | 778 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, |
779 | true); | ||
774 | } | 780 | } |
775 | 781 | ||
776 | out: | 782 | out: |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c981604b71e6..ecf9b7166ed1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -68,14 +68,42 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
68 | params && params->use_4addr >= 0) | 68 | params && params->use_4addr >= 0) |
69 | sdata->u.mgd.use_4addr = params->use_4addr; | 69 | sdata->u.mgd.use_4addr = params->use_4addr; |
70 | 70 | ||
71 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) | 71 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) { |
72 | sdata->u.mntr_flags = *flags; | 72 | struct ieee80211_local *local = sdata->local; |
73 | |||
74 | if (ieee80211_sdata_running(sdata)) { | ||
75 | /* | ||
76 | * Prohibit MONITOR_FLAG_COOK_FRAMES to be | ||
77 | * changed while the interface is up. | ||
78 | * Else we would need to add a lot of cruft | ||
79 | * to update everything: | ||
80 | * cooked_mntrs, monitor and all fif_* counters | ||
81 | * reconfigure hardware | ||
82 | */ | ||
83 | if ((*flags & MONITOR_FLAG_COOK_FRAMES) != | ||
84 | (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) | ||
85 | return -EBUSY; | ||
86 | |||
87 | ieee80211_adjust_monitor_flags(sdata, -1); | ||
88 | sdata->u.mntr_flags = *flags; | ||
89 | ieee80211_adjust_monitor_flags(sdata, 1); | ||
90 | |||
91 | ieee80211_configure_filter(local); | ||
92 | } else { | ||
93 | /* | ||
94 | * Because the interface is down, ieee80211_do_stop | ||
95 | * and ieee80211_do_open take care of "everything" | ||
96 | * mentioned in the comment above. | ||
97 | */ | ||
98 | sdata->u.mntr_flags = *flags; | ||
99 | } | ||
100 | } | ||
73 | 101 | ||
74 | return 0; | 102 | return 0; |
75 | } | 103 | } |
76 | 104 | ||
77 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | 105 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, |
78 | u8 key_idx, const u8 *mac_addr, | 106 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
79 | struct key_params *params) | 107 | struct key_params *params) |
80 | { | 108 | { |
81 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 109 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -103,6 +131,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
103 | if (IS_ERR(key)) | 131 | if (IS_ERR(key)) |
104 | return PTR_ERR(key); | 132 | return PTR_ERR(key); |
105 | 133 | ||
134 | if (pairwise) | ||
135 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | ||
136 | |||
106 | mutex_lock(&sdata->local->sta_mtx); | 137 | mutex_lock(&sdata->local->sta_mtx); |
107 | 138 | ||
108 | if (mac_addr) { | 139 | if (mac_addr) { |
@@ -125,7 +156,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
125 | } | 156 | } |
126 | 157 | ||
127 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 158 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
128 | u8 key_idx, const u8 *mac_addr) | 159 | u8 key_idx, bool pairwise, const u8 *mac_addr) |
129 | { | 160 | { |
130 | struct ieee80211_sub_if_data *sdata; | 161 | struct ieee80211_sub_if_data *sdata; |
131 | struct sta_info *sta; | 162 | struct sta_info *sta; |
@@ -142,10 +173,17 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
142 | if (!sta) | 173 | if (!sta) |
143 | goto out_unlock; | 174 | goto out_unlock; |
144 | 175 | ||
145 | if (sta->key) { | 176 | if (pairwise) { |
146 | ieee80211_key_free(sdata->local, sta->key); | 177 | if (sta->ptk) { |
147 | WARN_ON(sta->key); | 178 | ieee80211_key_free(sdata->local, sta->ptk); |
148 | ret = 0; | 179 | ret = 0; |
180 | } | ||
181 | } else { | ||
182 | if (sta->gtk[key_idx]) { | ||
183 | ieee80211_key_free(sdata->local, | ||
184 | sta->gtk[key_idx]); | ||
185 | ret = 0; | ||
186 | } | ||
149 | } | 187 | } |
150 | 188 | ||
151 | goto out_unlock; | 189 | goto out_unlock; |
@@ -167,7 +205,8 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
167 | } | 205 | } |
168 | 206 | ||
169 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | 207 | static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, |
170 | u8 key_idx, const u8 *mac_addr, void *cookie, | 208 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
209 | void *cookie, | ||
171 | void (*callback)(void *cookie, | 210 | void (*callback)(void *cookie, |
172 | struct key_params *params)) | 211 | struct key_params *params)) |
173 | { | 212 | { |
@@ -175,7 +214,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
175 | struct sta_info *sta = NULL; | 214 | struct sta_info *sta = NULL; |
176 | u8 seq[6] = {0}; | 215 | u8 seq[6] = {0}; |
177 | struct key_params params; | 216 | struct key_params params; |
178 | struct ieee80211_key *key; | 217 | struct ieee80211_key *key = NULL; |
179 | u32 iv32; | 218 | u32 iv32; |
180 | u16 iv16; | 219 | u16 iv16; |
181 | int err = -ENOENT; | 220 | int err = -ENOENT; |
@@ -189,7 +228,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
189 | if (!sta) | 228 | if (!sta) |
190 | goto out; | 229 | goto out; |
191 | 230 | ||
192 | key = sta->key; | 231 | if (pairwise) |
232 | key = sta->ptk; | ||
233 | else if (key_idx < NUM_DEFAULT_KEYS) | ||
234 | key = sta->gtk[key_idx]; | ||
193 | } else | 235 | } else |
194 | key = sdata->keys[key_idx]; | 236 | key = sdata->keys[key_idx]; |
195 | 237 | ||
@@ -285,6 +327,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
285 | STATION_INFO_TX_BYTES | | 327 | STATION_INFO_TX_BYTES | |
286 | STATION_INFO_RX_PACKETS | | 328 | STATION_INFO_RX_PACKETS | |
287 | STATION_INFO_TX_PACKETS | | 329 | STATION_INFO_TX_PACKETS | |
330 | STATION_INFO_TX_RETRIES | | ||
331 | STATION_INFO_TX_FAILED | | ||
288 | STATION_INFO_TX_BITRATE; | 332 | STATION_INFO_TX_BITRATE; |
289 | 333 | ||
290 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 334 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
@@ -292,6 +336,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
292 | sinfo->tx_bytes = sta->tx_bytes; | 336 | sinfo->tx_bytes = sta->tx_bytes; |
293 | sinfo->rx_packets = sta->rx_packets; | 337 | sinfo->rx_packets = sta->rx_packets; |
294 | sinfo->tx_packets = sta->tx_packets; | 338 | sinfo->tx_packets = sta->tx_packets; |
339 | sinfo->tx_retries = sta->tx_retry_count; | ||
340 | sinfo->tx_failed = sta->tx_retry_failed; | ||
295 | 341 | ||
296 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | 342 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || |
297 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | 343 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { |
@@ -1317,7 +1363,7 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm) | |||
1317 | } | 1363 | } |
1318 | 1364 | ||
1319 | static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, | 1365 | static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, |
1320 | u8 *addr) | 1366 | const u8 *addr) |
1321 | { | 1367 | { |
1322 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1368 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1323 | 1369 | ||
@@ -1366,7 +1412,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
1366 | if (!sdata->u.mgd.associated || | 1412 | if (!sdata->u.mgd.associated || |
1367 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { | 1413 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { |
1368 | mutex_lock(&sdata->local->iflist_mtx); | 1414 | mutex_lock(&sdata->local->iflist_mtx); |
1369 | ieee80211_recalc_smps(sdata->local, sdata); | 1415 | ieee80211_recalc_smps(sdata->local); |
1370 | mutex_unlock(&sdata->local->iflist_mtx); | 1416 | mutex_unlock(&sdata->local->iflist_mtx); |
1371 | return 0; | 1417 | return 0; |
1372 | } | 1418 | } |
@@ -1521,7 +1567,11 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1521 | 1567 | ||
1522 | switch (sdata->vif.type) { | 1568 | switch (sdata->vif.type) { |
1523 | case NL80211_IFTYPE_ADHOC: | 1569 | case NL80211_IFTYPE_ADHOC: |
1524 | if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | 1570 | case NL80211_IFTYPE_AP: |
1571 | case NL80211_IFTYPE_AP_VLAN: | ||
1572 | case NL80211_IFTYPE_P2P_GO: | ||
1573 | if (!ieee80211_is_action(mgmt->frame_control) || | ||
1574 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | ||
1525 | break; | 1575 | break; |
1526 | rcu_read_lock(); | 1576 | rcu_read_lock(); |
1527 | sta = sta_info_get(sdata, mgmt->da); | 1577 | sta = sta_info_get(sdata, mgmt->da); |
@@ -1530,6 +1580,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1530 | return -ENOLINK; | 1580 | return -ENOLINK; |
1531 | break; | 1581 | break; |
1532 | case NL80211_IFTYPE_STATION: | 1582 | case NL80211_IFTYPE_STATION: |
1583 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1533 | break; | 1584 | break; |
1534 | default: | 1585 | default: |
1535 | return -EOPNOTSUPP; | 1586 | return -EOPNOTSUPP; |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 6b7ff9fb4604..50c40ea3cb4d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -196,7 +196,8 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu | |||
196 | else | 196 | else |
197 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); | 197 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); |
198 | } else { | 198 | } else { |
199 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3); | 199 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
200 | 3, true); | ||
200 | ret = 0; | 201 | ret = 0; |
201 | } | 202 | } |
202 | 203 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 11f74f5f7b2f..4214bb6e12fc 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -101,16 +101,16 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | |||
101 | ht_cap->mcs.rx_mask[32/8] |= 1; | 101 | ht_cap->mcs.rx_mask[32/8] |= 1; |
102 | } | 102 | } |
103 | 103 | ||
104 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta) | 104 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx) |
105 | { | 105 | { |
106 | int i; | 106 | int i; |
107 | 107 | ||
108 | cancel_work_sync(&sta->ampdu_mlme.work); | 108 | cancel_work_sync(&sta->ampdu_mlme.work); |
109 | 109 | ||
110 | for (i = 0; i < STA_TID_NUM; i++) { | 110 | for (i = 0; i < STA_TID_NUM; i++) { |
111 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR); | 111 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx); |
112 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, | 112 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, |
113 | WLAN_REASON_QSTA_LEAVE_QBSS); | 113 | WLAN_REASON_QSTA_LEAVE_QBSS, tx); |
114 | } | 114 | } |
115 | } | 115 | } |
116 | 116 | ||
@@ -135,7 +135,7 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
135 | if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) | 135 | if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) |
136 | ___ieee80211_stop_rx_ba_session( | 136 | ___ieee80211_stop_rx_ba_session( |
137 | sta, tid, WLAN_BACK_RECIPIENT, | 137 | sta, tid, WLAN_BACK_RECIPIENT, |
138 | WLAN_REASON_QSTA_TIMEOUT); | 138 | WLAN_REASON_QSTA_TIMEOUT, true); |
139 | 139 | ||
140 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 140 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; |
141 | if (!tid_tx) | 141 | if (!tid_tx) |
@@ -146,7 +146,8 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
146 | else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, | 146 | else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, |
147 | &tid_tx->state)) | 147 | &tid_tx->state)) |
148 | ___ieee80211_stop_tx_ba_session(sta, tid, | 148 | ___ieee80211_stop_tx_ba_session(sta, tid, |
149 | WLAN_BACK_INITIATOR); | 149 | WLAN_BACK_INITIATOR, |
150 | true); | ||
150 | } | 151 | } |
151 | mutex_unlock(&sta->ampdu_mlme.mtx); | 152 | mutex_unlock(&sta->ampdu_mlme.mtx); |
152 | } | 153 | } |
@@ -214,9 +215,11 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
214 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 215 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
215 | 216 | ||
216 | if (initiator == WLAN_BACK_INITIATOR) | 217 | if (initiator == WLAN_BACK_INITIATOR) |
217 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0); | 218 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0, |
219 | true); | ||
218 | else | 220 | else |
219 | __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT); | 221 | __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
222 | true); | ||
220 | } | 223 | } |
221 | 224 | ||
222 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | 225 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 1a3aae54f0cf..ff60c022f51d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -173,6 +173,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
173 | memcpy(skb_put(skb, ifibss->ie_len), | 173 | memcpy(skb_put(skb, ifibss->ie_len), |
174 | ifibss->ie, ifibss->ie_len); | 174 | ifibss->ie, ifibss->ie_len); |
175 | 175 | ||
176 | if (local->hw.queues >= 4) { | ||
177 | pos = skb_put(skb, 9); | ||
178 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
179 | *pos++ = 7; /* len */ | ||
180 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
181 | *pos++ = 0x50; | ||
182 | *pos++ = 0xf2; | ||
183 | *pos++ = 2; /* WME */ | ||
184 | *pos++ = 0; /* WME info */ | ||
185 | *pos++ = 1; /* WME ver */ | ||
186 | *pos++ = 0; /* U-APSD no in use */ | ||
187 | } | ||
188 | |||
176 | rcu_assign_pointer(ifibss->presp, skb); | 189 | rcu_assign_pointer(ifibss->presp, skb); |
177 | 190 | ||
178 | sdata->vif.bss_conf.beacon_int = beacon_int; | 191 | sdata->vif.bss_conf.beacon_int = beacon_int; |
@@ -266,37 +279,45 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
266 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 279 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
267 | return; | 280 | return; |
268 | 281 | ||
269 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && elems->supp_rates && | 282 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
270 | memcmp(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) { | 283 | memcmp(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) { |
271 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | ||
272 | 284 | ||
273 | rcu_read_lock(); | 285 | rcu_read_lock(); |
274 | |||
275 | sta = sta_info_get(sdata, mgmt->sa); | 286 | sta = sta_info_get(sdata, mgmt->sa); |
276 | if (sta) { | ||
277 | u32 prev_rates; | ||
278 | 287 | ||
279 | prev_rates = sta->sta.supp_rates[band]; | 288 | if (elems->supp_rates) { |
280 | /* make sure mandatory rates are always added */ | 289 | supp_rates = ieee80211_sta_get_rates(local, elems, |
281 | sta->sta.supp_rates[band] = supp_rates | | 290 | band); |
282 | ieee80211_mandatory_rates(local, band); | 291 | if (sta) { |
292 | u32 prev_rates; | ||
283 | 293 | ||
284 | if (sta->sta.supp_rates[band] != prev_rates) { | 294 | prev_rates = sta->sta.supp_rates[band]; |
295 | /* make sure mandatory rates are always added */ | ||
296 | sta->sta.supp_rates[band] = supp_rates | | ||
297 | ieee80211_mandatory_rates(local, band); | ||
298 | |||
299 | if (sta->sta.supp_rates[band] != prev_rates) { | ||
285 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 300 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
286 | printk(KERN_DEBUG "%s: updated supp_rates set " | 301 | printk(KERN_DEBUG |
287 | "for %pM based on beacon/probe_response " | 302 | "%s: updated supp_rates set " |
288 | "(0x%x -> 0x%x)\n", | 303 | "for %pM based on beacon" |
289 | sdata->name, sta->sta.addr, | 304 | "/probe_resp (0x%x -> 0x%x)\n", |
290 | prev_rates, sta->sta.supp_rates[band]); | 305 | sdata->name, sta->sta.addr, |
306 | prev_rates, | ||
307 | sta->sta.supp_rates[band]); | ||
291 | #endif | 308 | #endif |
292 | rate_control_rate_init(sta); | 309 | rate_control_rate_init(sta); |
293 | } | 310 | } |
294 | rcu_read_unlock(); | 311 | } else |
295 | } else { | 312 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, |
296 | rcu_read_unlock(); | 313 | mgmt->sa, supp_rates, |
297 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 314 | GFP_ATOMIC); |
298 | supp_rates, GFP_KERNEL); | ||
299 | } | 315 | } |
316 | |||
317 | if (sta && elems->wmm_info) | ||
318 | set_sta_flags(sta, WLAN_STA_WME); | ||
319 | |||
320 | rcu_read_unlock(); | ||
300 | } | 321 | } |
301 | 322 | ||
302 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 323 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 945fbf29719d..f0610fa4fbe0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -369,6 +369,7 @@ struct ieee80211_if_managed { | |||
369 | 369 | ||
370 | unsigned int flags; | 370 | unsigned int flags; |
371 | 371 | ||
372 | bool beacon_crc_valid; | ||
372 | u32 beacon_crc; | 373 | u32 beacon_crc; |
373 | 374 | ||
374 | enum { | 375 | enum { |
@@ -548,8 +549,6 @@ struct ieee80211_sub_if_data { | |||
548 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 549 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
549 | unsigned int fragment_next; | 550 | unsigned int fragment_next; |
550 | 551 | ||
551 | #define NUM_DEFAULT_KEYS 4 | ||
552 | #define NUM_DEFAULT_MGMT_KEYS 2 | ||
553 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 552 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
554 | struct ieee80211_key *default_key; | 553 | struct ieee80211_key *default_key; |
555 | struct ieee80211_key *default_mgmt_key; | 554 | struct ieee80211_key *default_mgmt_key; |
@@ -1132,6 +1131,8 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); | |||
1132 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 1131 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
1133 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); | 1132 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); |
1134 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1133 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
1134 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | ||
1135 | const int offset); | ||
1135 | 1136 | ||
1136 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | 1137 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) |
1137 | { | 1138 | { |
@@ -1172,10 +1173,10 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
1172 | void ieee80211_request_smps_work(struct work_struct *work); | 1173 | void ieee80211_request_smps_work(struct work_struct *work); |
1173 | 1174 | ||
1174 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1175 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1175 | u16 initiator, u16 reason); | 1176 | u16 initiator, u16 reason, bool stop); |
1176 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1177 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1177 | u16 initiator, u16 reason); | 1178 | u16 initiator, u16 reason, bool stop); |
1178 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); | 1179 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx); |
1179 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 1180 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
1180 | struct sta_info *sta, | 1181 | struct sta_info *sta, |
1181 | struct ieee80211_mgmt *mgmt, size_t len); | 1182 | struct ieee80211_mgmt *mgmt, size_t len); |
@@ -1189,9 +1190,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
1189 | size_t len); | 1190 | size_t len); |
1190 | 1191 | ||
1191 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 1192 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
1192 | enum ieee80211_back_parties initiator); | 1193 | enum ieee80211_back_parties initiator, |
1194 | bool tx); | ||
1193 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 1195 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
1194 | enum ieee80211_back_parties initiator); | 1196 | enum ieee80211_back_parties initiator, |
1197 | bool tx); | ||
1195 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); | 1198 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); |
1196 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); | 1199 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); |
1197 | void ieee80211_ba_session_work(struct work_struct *work); | 1200 | void ieee80211_ba_session_work(struct work_struct *work); |
@@ -1294,8 +1297,7 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
1294 | enum ieee80211_band band); | 1297 | enum ieee80211_band band); |
1295 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | 1298 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, |
1296 | enum ieee80211_smps_mode smps_mode); | 1299 | enum ieee80211_smps_mode smps_mode); |
1297 | void ieee80211_recalc_smps(struct ieee80211_local *local, | 1300 | void ieee80211_recalc_smps(struct ieee80211_local *local); |
1298 | struct ieee80211_sub_if_data *forsdata); | ||
1299 | 1301 | ||
1300 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | 1302 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, |
1301 | const u8 *ids, int n_ids, size_t offset); | 1303 | const u8 *ids, int n_ids, size_t offset); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 66785739dad3..e99d1b60557c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "led.h" | 24 | #include "led.h" |
25 | #include "driver-ops.h" | 25 | #include "driver-ops.h" |
26 | #include "wme.h" | 26 | #include "wme.h" |
27 | #include "rate.h" | ||
27 | 28 | ||
28 | /** | 29 | /** |
29 | * DOC: Interface list locking | 30 | * DOC: Interface list locking |
@@ -148,6 +149,26 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, | |||
148 | return 0; | 149 | return 0; |
149 | } | 150 | } |
150 | 151 | ||
152 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | ||
153 | const int offset) | ||
154 | { | ||
155 | struct ieee80211_local *local = sdata->local; | ||
156 | u32 flags = sdata->u.mntr_flags; | ||
157 | |||
158 | #define ADJUST(_f, _s) do { \ | ||
159 | if (flags & MONITOR_FLAG_##_f) \ | ||
160 | local->fif_##_s += offset; \ | ||
161 | } while (0) | ||
162 | |||
163 | ADJUST(FCSFAIL, fcsfail); | ||
164 | ADJUST(PLCPFAIL, plcpfail); | ||
165 | ADJUST(CONTROL, control); | ||
166 | ADJUST(CONTROL, pspoll); | ||
167 | ADJUST(OTHER_BSS, other_bss); | ||
168 | |||
169 | #undef ADJUST | ||
170 | } | ||
171 | |||
151 | /* | 172 | /* |
152 | * NOTE: Be very careful when changing this function, it must NOT return | 173 | * NOTE: Be very careful when changing this function, it must NOT return |
153 | * an error on interface type changes that have been pre-checked, so most | 174 | * an error on interface type changes that have been pre-checked, so most |
@@ -240,17 +261,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
240 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 261 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
241 | } | 262 | } |
242 | 263 | ||
243 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | 264 | ieee80211_adjust_monitor_flags(sdata, 1); |
244 | local->fif_fcsfail++; | ||
245 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
246 | local->fif_plcpfail++; | ||
247 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) { | ||
248 | local->fif_control++; | ||
249 | local->fif_pspoll++; | ||
250 | } | ||
251 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
252 | local->fif_other_bss++; | ||
253 | |||
254 | ieee80211_configure_filter(local); | 265 | ieee80211_configure_filter(local); |
255 | 266 | ||
256 | netif_carrier_on(dev); | 267 | netif_carrier_on(dev); |
@@ -301,6 +312,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
301 | /* STA has been freed */ | 312 | /* STA has been freed */ |
302 | goto err_del_interface; | 313 | goto err_del_interface; |
303 | } | 314 | } |
315 | |||
316 | rate_control_rate_init(sta); | ||
304 | } | 317 | } |
305 | 318 | ||
306 | /* | 319 | /* |
@@ -477,17 +490,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
477 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 490 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
478 | } | 491 | } |
479 | 492 | ||
480 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | 493 | ieee80211_adjust_monitor_flags(sdata, -1); |
481 | local->fif_fcsfail--; | ||
482 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
483 | local->fif_plcpfail--; | ||
484 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) { | ||
485 | local->fif_pspoll--; | ||
486 | local->fif_control--; | ||
487 | } | ||
488 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
489 | local->fif_other_bss--; | ||
490 | |||
491 | ieee80211_configure_filter(local); | 494 | ieee80211_configure_filter(local); |
492 | break; | 495 | break; |
493 | case NL80211_IFTYPE_MESH_POINT: | 496 | case NL80211_IFTYPE_MESH_POINT: |
@@ -793,7 +796,8 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
793 | 796 | ||
794 | __ieee80211_stop_rx_ba_session( | 797 | __ieee80211_stop_rx_ba_session( |
795 | sta, tid, WLAN_BACK_RECIPIENT, | 798 | sta, tid, WLAN_BACK_RECIPIENT, |
796 | WLAN_REASON_QSTA_REQUIRE_SETUP); | 799 | WLAN_REASON_QSTA_REQUIRE_SETUP, |
800 | true); | ||
797 | } | 801 | } |
798 | mutex_unlock(&local->sta_mtx); | 802 | mutex_unlock(&local->sta_mtx); |
799 | } else switch (sdata->vif.type) { | 803 | } else switch (sdata->vif.type) { |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 6a63d1abd14d..ccd676b2f599 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -68,15 +68,21 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
68 | 68 | ||
69 | might_sleep(); | 69 | might_sleep(); |
70 | 70 | ||
71 | if (!key->local->ops->set_key) { | 71 | if (!key->local->ops->set_key) |
72 | ret = -EOPNOTSUPP; | ||
73 | goto out_unsupported; | 72 | goto out_unsupported; |
74 | } | ||
75 | 73 | ||
76 | assert_key_lock(key->local); | 74 | assert_key_lock(key->local); |
77 | 75 | ||
78 | sta = get_sta_for_key(key); | 76 | sta = get_sta_for_key(key); |
79 | 77 | ||
78 | /* | ||
79 | * If this is a per-STA GTK, check if it | ||
80 | * is supported; if not, return. | ||
81 | */ | ||
82 | if (sta && !(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) && | ||
83 | !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)) | ||
84 | goto out_unsupported; | ||
85 | |||
80 | sdata = key->sdata; | 86 | sdata = key->sdata; |
81 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 87 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
82 | sdata = container_of(sdata->bss, | 88 | sdata = container_of(sdata->bss, |
@@ -85,31 +91,28 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
85 | 91 | ||
86 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); | 92 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); |
87 | 93 | ||
88 | if (!ret) | 94 | if (!ret) { |
89 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 95 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
96 | return 0; | ||
97 | } | ||
90 | 98 | ||
91 | if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) | 99 | if (ret != -ENOSPC && ret != -EOPNOTSUPP) |
92 | wiphy_err(key->local->hw.wiphy, | 100 | wiphy_err(key->local->hw.wiphy, |
93 | "failed to set key (%d, %pM) to hardware (%d)\n", | 101 | "failed to set key (%d, %pM) to hardware (%d)\n", |
94 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); | 102 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
95 | 103 | ||
96 | out_unsupported: | 104 | out_unsupported: |
97 | if (ret) { | 105 | switch (key->conf.cipher) { |
98 | switch (key->conf.cipher) { | 106 | case WLAN_CIPHER_SUITE_WEP40: |
99 | case WLAN_CIPHER_SUITE_WEP40: | 107 | case WLAN_CIPHER_SUITE_WEP104: |
100 | case WLAN_CIPHER_SUITE_WEP104: | 108 | case WLAN_CIPHER_SUITE_TKIP: |
101 | case WLAN_CIPHER_SUITE_TKIP: | 109 | case WLAN_CIPHER_SUITE_CCMP: |
102 | case WLAN_CIPHER_SUITE_CCMP: | 110 | case WLAN_CIPHER_SUITE_AES_CMAC: |
103 | case WLAN_CIPHER_SUITE_AES_CMAC: | 111 | /* all of these we can do in software */ |
104 | /* all of these we can do in software */ | 112 | return 0; |
105 | ret = 0; | 113 | default: |
106 | break; | 114 | return -EINVAL; |
107 | default: | ||
108 | ret = -EINVAL; | ||
109 | } | ||
110 | } | 115 | } |
111 | |||
112 | return ret; | ||
113 | } | 116 | } |
114 | 117 | ||
115 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | 118 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) |
@@ -147,6 +150,26 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
147 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 150 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
148 | } | 151 | } |
149 | 152 | ||
153 | void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) | ||
154 | { | ||
155 | struct ieee80211_key *key; | ||
156 | |||
157 | key = container_of(key_conf, struct ieee80211_key, conf); | ||
158 | |||
159 | might_sleep(); | ||
160 | assert_key_lock(key->local); | ||
161 | |||
162 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | ||
163 | |||
164 | /* | ||
165 | * Flush TX path to avoid attempts to use this key | ||
166 | * after this function returns. Until then, drivers | ||
167 | * must be prepared to handle the key. | ||
168 | */ | ||
169 | synchronize_rcu(); | ||
170 | } | ||
171 | EXPORT_SYMBOL_GPL(ieee80211_key_removed); | ||
172 | |||
150 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | 173 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
151 | int idx) | 174 | int idx) |
152 | { | 175 | { |
@@ -202,6 +225,7 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | |||
202 | 225 | ||
203 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | 226 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, |
204 | struct sta_info *sta, | 227 | struct sta_info *sta, |
228 | bool pairwise, | ||
205 | struct ieee80211_key *old, | 229 | struct ieee80211_key *old, |
206 | struct ieee80211_key *new) | 230 | struct ieee80211_key *new) |
207 | { | 231 | { |
@@ -210,8 +234,14 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
210 | if (new) | 234 | if (new) |
211 | list_add(&new->list, &sdata->key_list); | 235 | list_add(&new->list, &sdata->key_list); |
212 | 236 | ||
213 | if (sta) { | 237 | if (sta && pairwise) { |
214 | rcu_assign_pointer(sta->key, new); | 238 | rcu_assign_pointer(sta->ptk, new); |
239 | } else if (sta) { | ||
240 | if (old) | ||
241 | idx = old->conf.keyidx; | ||
242 | else | ||
243 | idx = new->conf.keyidx; | ||
244 | rcu_assign_pointer(sta->gtk[idx], new); | ||
215 | } else { | 245 | } else { |
216 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); | 246 | WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx); |
217 | 247 | ||
@@ -355,6 +385,7 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
355 | { | 385 | { |
356 | struct ieee80211_key *old_key; | 386 | struct ieee80211_key *old_key; |
357 | int idx, ret; | 387 | int idx, ret; |
388 | bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; | ||
358 | 389 | ||
359 | BUG_ON(!sdata); | 390 | BUG_ON(!sdata); |
360 | BUG_ON(!key); | 391 | BUG_ON(!key); |
@@ -371,13 +402,6 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
371 | */ | 402 | */ |
372 | if (test_sta_flags(sta, WLAN_STA_WME)) | 403 | if (test_sta_flags(sta, WLAN_STA_WME)) |
373 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; | 404 | key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; |
374 | |||
375 | /* | ||
376 | * This key is for a specific sta interface, | ||
377 | * inform the driver that it should try to store | ||
378 | * this key as pairwise key. | ||
379 | */ | ||
380 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | ||
381 | } else { | 405 | } else { |
382 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 406 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
383 | struct sta_info *ap; | 407 | struct sta_info *ap; |
@@ -399,12 +423,14 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
399 | 423 | ||
400 | mutex_lock(&sdata->local->key_mtx); | 424 | mutex_lock(&sdata->local->key_mtx); |
401 | 425 | ||
402 | if (sta) | 426 | if (sta && pairwise) |
403 | old_key = sta->key; | 427 | old_key = sta->ptk; |
428 | else if (sta) | ||
429 | old_key = sta->gtk[idx]; | ||
404 | else | 430 | else |
405 | old_key = sdata->keys[idx]; | 431 | old_key = sdata->keys[idx]; |
406 | 432 | ||
407 | __ieee80211_key_replace(sdata, sta, old_key, key); | 433 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); |
408 | __ieee80211_key_destroy(old_key); | 434 | __ieee80211_key_destroy(old_key); |
409 | 435 | ||
410 | ieee80211_debugfs_key_add(key); | 436 | ieee80211_debugfs_key_add(key); |
@@ -423,7 +449,8 @@ static void __ieee80211_key_free(struct ieee80211_key *key) | |||
423 | */ | 449 | */ |
424 | if (key->sdata) | 450 | if (key->sdata) |
425 | __ieee80211_key_replace(key->sdata, key->sta, | 451 | __ieee80211_key_replace(key->sdata, key->sta, |
426 | key, NULL); | 452 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
453 | key, NULL); | ||
427 | __ieee80211_key_destroy(key); | 454 | __ieee80211_key_destroy(key); |
428 | } | 455 | } |
429 | 456 | ||
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index cb9a4a65cc68..0db1c0f5f697 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -16,6 +16,9 @@ | |||
16 | #include <linux/rcupdate.h> | 16 | #include <linux/rcupdate.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | 18 | ||
19 | #define NUM_DEFAULT_KEYS 4 | ||
20 | #define NUM_DEFAULT_MGMT_KEYS 2 | ||
21 | |||
19 | #define WEP_IV_LEN 4 | 22 | #define WEP_IV_LEN 4 |
20 | #define WEP_ICV_LEN 4 | 23 | #define WEP_ICV_LEN 4 |
21 | #define ALG_TKIP_KEY_LEN 32 | 24 | #define ALG_TKIP_KEY_LEN 32 |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index db341a99c7c7..eb0f59977676 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -201,6 +201,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
201 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; | 201 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; |
202 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | 202 | else if (sdata->vif.type == NL80211_IFTYPE_AP) |
203 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | 203 | sdata->vif.bss_conf.bssid = sdata->vif.addr; |
204 | else if (sdata->vif.type == NL80211_IFTYPE_WDS) | ||
205 | sdata->vif.bss_conf.bssid = NULL; | ||
204 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 206 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
205 | sdata->vif.bss_conf.bssid = zero; | 207 | sdata->vif.bss_conf.bssid = zero; |
206 | } else { | 208 | } else { |
@@ -211,6 +213,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
211 | switch (sdata->vif.type) { | 213 | switch (sdata->vif.type) { |
212 | case NL80211_IFTYPE_AP: | 214 | case NL80211_IFTYPE_AP: |
213 | case NL80211_IFTYPE_ADHOC: | 215 | case NL80211_IFTYPE_ADHOC: |
216 | case NL80211_IFTYPE_WDS: | ||
214 | case NL80211_IFTYPE_MESH_POINT: | 217 | case NL80211_IFTYPE_MESH_POINT: |
215 | break; | 218 | break; |
216 | default: | 219 | default: |
@@ -295,7 +298,16 @@ static void ieee80211_restart_work(struct work_struct *work) | |||
295 | struct ieee80211_local *local = | 298 | struct ieee80211_local *local = |
296 | container_of(work, struct ieee80211_local, restart_work); | 299 | container_of(work, struct ieee80211_local, restart_work); |
297 | 300 | ||
301 | /* wait for scan work complete */ | ||
302 | flush_workqueue(local->workqueue); | ||
303 | |||
304 | mutex_lock(&local->mtx); | ||
305 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | ||
306 | "%s called with hardware scan in progress\n", __func__); | ||
307 | mutex_unlock(&local->mtx); | ||
308 | |||
298 | rtnl_lock(); | 309 | rtnl_lock(); |
310 | ieee80211_scan_cancel(local); | ||
299 | ieee80211_reconfig(local); | 311 | ieee80211_reconfig(local); |
300 | rtnl_unlock(); | 312 | rtnl_unlock(); |
301 | } | 313 | } |
@@ -306,15 +318,6 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
306 | 318 | ||
307 | trace_api_restart_hw(local); | 319 | trace_api_restart_hw(local); |
308 | 320 | ||
309 | /* wait for scan work complete */ | ||
310 | flush_workqueue(local->workqueue); | ||
311 | |||
312 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | ||
313 | "%s called with hardware scan in progress\n", __func__); | ||
314 | |||
315 | if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) | ||
316 | ieee80211_scan_cancel(local); | ||
317 | |||
318 | /* use this reason, ieee80211_reconfig will unblock it */ | 321 | /* use this reason, ieee80211_reconfig will unblock it */ |
319 | ieee80211_stop_queues_by_reason(hw, | 322 | ieee80211_stop_queues_by_reason(hw, |
320 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 323 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
@@ -329,7 +332,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work) | |||
329 | container_of(work, struct ieee80211_local, recalc_smps); | 332 | container_of(work, struct ieee80211_local, recalc_smps); |
330 | 333 | ||
331 | mutex_lock(&local->iflist_mtx); | 334 | mutex_lock(&local->iflist_mtx); |
332 | ieee80211_recalc_smps(local, NULL); | 335 | ieee80211_recalc_smps(local); |
333 | mutex_unlock(&local->iflist_mtx); | 336 | mutex_unlock(&local->iflist_mtx); |
334 | } | 337 | } |
335 | 338 | ||
@@ -533,6 +536,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
533 | /* set up some defaults */ | 536 | /* set up some defaults */ |
534 | local->hw.queues = 1; | 537 | local->hw.queues = 1; |
535 | local->hw.max_rates = 1; | 538 | local->hw.max_rates = 1; |
539 | local->hw.max_report_rates = 0; | ||
536 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 540 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
537 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 541 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
538 | local->user_power_level = -1; | 542 | local->user_power_level = -1; |
@@ -608,6 +612,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
608 | WLAN_CIPHER_SUITE_AES_CMAC | 612 | WLAN_CIPHER_SUITE_AES_CMAC |
609 | }; | 613 | }; |
610 | 614 | ||
615 | if (hw->max_report_rates == 0) | ||
616 | hw->max_report_rates = hw->max_rates; | ||
617 | |||
611 | /* | 618 | /* |
612 | * generic code guarantees at least one band, | 619 | * generic code guarantees at least one band, |
613 | * set this very early because much code assumes | 620 | * set this very early because much code assumes |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 77913a15f537..5695c94c49aa 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -913,7 +913,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
913 | 913 | ||
914 | mutex_lock(&local->iflist_mtx); | 914 | mutex_lock(&local->iflist_mtx); |
915 | ieee80211_recalc_ps(local, -1); | 915 | ieee80211_recalc_ps(local, -1); |
916 | ieee80211_recalc_smps(local, sdata); | 916 | ieee80211_recalc_smps(local); |
917 | mutex_unlock(&local->iflist_mtx); | 917 | mutex_unlock(&local->iflist_mtx); |
918 | 918 | ||
919 | netif_tx_start_all_queues(sdata->dev); | 919 | netif_tx_start_all_queues(sdata->dev); |
@@ -921,7 +921,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
921 | } | 921 | } |
922 | 922 | ||
923 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | 923 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
924 | bool remove_sta) | 924 | bool remove_sta, bool tx) |
925 | { | 925 | { |
926 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 926 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
927 | struct ieee80211_local *local = sdata->local; | 927 | struct ieee80211_local *local = sdata->local; |
@@ -960,7 +960,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
960 | sta = sta_info_get(sdata, bssid); | 960 | sta = sta_info_get(sdata, bssid); |
961 | if (sta) { | 961 | if (sta) { |
962 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 962 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
963 | ieee80211_sta_tear_down_BA_sessions(sta); | 963 | ieee80211_sta_tear_down_BA_sessions(sta, tx); |
964 | } | 964 | } |
965 | mutex_unlock(&local->sta_mtx); | 965 | mutex_unlock(&local->sta_mtx); |
966 | 966 | ||
@@ -1124,7 +1124,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1124 | 1124 | ||
1125 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | 1125 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); |
1126 | 1126 | ||
1127 | ieee80211_set_disassoc(sdata, true); | 1127 | ieee80211_set_disassoc(sdata, true, true); |
1128 | mutex_unlock(&ifmgd->mtx); | 1128 | mutex_unlock(&ifmgd->mtx); |
1129 | 1129 | ||
1130 | mutex_lock(&local->mtx); | 1130 | mutex_lock(&local->mtx); |
@@ -1197,7 +1197,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1197 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1197 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
1198 | sdata->name, bssid, reason_code); | 1198 | sdata->name, bssid, reason_code); |
1199 | 1199 | ||
1200 | ieee80211_set_disassoc(sdata, true); | 1200 | ieee80211_set_disassoc(sdata, true, false); |
1201 | mutex_lock(&sdata->local->mtx); | 1201 | mutex_lock(&sdata->local->mtx); |
1202 | ieee80211_recalc_idle(sdata->local); | 1202 | ieee80211_recalc_idle(sdata->local); |
1203 | mutex_unlock(&sdata->local->mtx); | 1203 | mutex_unlock(&sdata->local->mtx); |
@@ -1229,7 +1229,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1229 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1229 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
1230 | sdata->name, mgmt->sa, reason_code); | 1230 | sdata->name, mgmt->sa, reason_code); |
1231 | 1231 | ||
1232 | ieee80211_set_disassoc(sdata, true); | 1232 | ieee80211_set_disassoc(sdata, true, false); |
1233 | mutex_lock(&sdata->local->mtx); | 1233 | mutex_lock(&sdata->local->mtx); |
1234 | ieee80211_recalc_idle(sdata->local); | 1234 | ieee80211_recalc_idle(sdata->local); |
1235 | mutex_unlock(&sdata->local->mtx); | 1235 | mutex_unlock(&sdata->local->mtx); |
@@ -1291,7 +1291,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1291 | 1291 | ||
1292 | rates = 0; | 1292 | rates = 0; |
1293 | basic_rates = 0; | 1293 | basic_rates = 0; |
1294 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1294 | sband = local->hw.wiphy->bands[wk->chan->band]; |
1295 | 1295 | ||
1296 | for (i = 0; i < elems.supp_rates_len; i++) { | 1296 | for (i = 0; i < elems.supp_rates_len; i++) { |
1297 | int rate = (elems.supp_rates[i] & 0x7f) * 5; | 1297 | int rate = (elems.supp_rates[i] & 0x7f) * 5; |
@@ -1327,11 +1327,11 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1327 | } | 1327 | } |
1328 | } | 1328 | } |
1329 | 1329 | ||
1330 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 1330 | sta->sta.supp_rates[wk->chan->band] = rates; |
1331 | sdata->vif.bss_conf.basic_rates = basic_rates; | 1331 | sdata->vif.bss_conf.basic_rates = basic_rates; |
1332 | 1332 | ||
1333 | /* cf. IEEE 802.11 9.2.12 */ | 1333 | /* cf. IEEE 802.11 9.2.12 */ |
1334 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 1334 | if (wk->chan->band == IEEE80211_BAND_2GHZ && |
1335 | have_higher_than_11mbit) | 1335 | have_higher_than_11mbit) |
1336 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 1336 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
1337 | else | 1337 | else |
@@ -1639,7 +1639,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1639 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, | 1639 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, |
1640 | ifmgd->aid); | 1640 | ifmgd->aid); |
1641 | 1641 | ||
1642 | if (ncrc != ifmgd->beacon_crc) { | 1642 | if (ncrc != ifmgd->beacon_crc || !ifmgd->beacon_crc_valid) { |
1643 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, | 1643 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, |
1644 | true); | 1644 | true); |
1645 | 1645 | ||
@@ -1670,9 +1670,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1670 | } | 1670 | } |
1671 | } | 1671 | } |
1672 | 1672 | ||
1673 | if (ncrc == ifmgd->beacon_crc) | 1673 | if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) |
1674 | return; | 1674 | return; |
1675 | ifmgd->beacon_crc = ncrc; | 1675 | ifmgd->beacon_crc = ncrc; |
1676 | ifmgd->beacon_crc_valid = true; | ||
1676 | 1677 | ||
1677 | if (elems.erp_info && elems.erp_info_len >= 1) { | 1678 | if (elems.erp_info && elems.erp_info_len >= 1) { |
1678 | erp_valid = true; | 1679 | erp_valid = true; |
@@ -1879,7 +1880,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1879 | printk(KERN_DEBUG "No probe response from AP %pM" | 1880 | printk(KERN_DEBUG "No probe response from AP %pM" |
1880 | " after %dms, disconnecting.\n", | 1881 | " after %dms, disconnecting.\n", |
1881 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1882 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1882 | ieee80211_set_disassoc(sdata, true); | 1883 | ieee80211_set_disassoc(sdata, true, true); |
1883 | mutex_unlock(&ifmgd->mtx); | 1884 | mutex_unlock(&ifmgd->mtx); |
1884 | mutex_lock(&local->mtx); | 1885 | mutex_lock(&local->mtx); |
1885 | ieee80211_recalc_idle(local); | 1886 | ieee80211_recalc_idle(local); |
@@ -2203,7 +2204,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2203 | } | 2204 | } |
2204 | 2205 | ||
2205 | /* Trying to reassociate - clear previous association state */ | 2206 | /* Trying to reassociate - clear previous association state */ |
2206 | ieee80211_set_disassoc(sdata, true); | 2207 | ieee80211_set_disassoc(sdata, true, false); |
2207 | } | 2208 | } |
2208 | mutex_unlock(&ifmgd->mtx); | 2209 | mutex_unlock(&ifmgd->mtx); |
2209 | 2210 | ||
@@ -2214,6 +2215,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2214 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; | 2215 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; |
2215 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 2216 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; |
2216 | 2217 | ||
2218 | ifmgd->beacon_crc_valid = false; | ||
2219 | |||
2217 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) | 2220 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) |
2218 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 2221 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
2219 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 2222 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
@@ -2315,7 +2318,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2315 | 2318 | ||
2316 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | 2319 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
2317 | if (ifmgd->associated == req->bss) { | 2320 | if (ifmgd->associated == req->bss) { |
2318 | ieee80211_set_disassoc(sdata, false); | 2321 | ieee80211_set_disassoc(sdata, false, true); |
2319 | mutex_unlock(&ifmgd->mtx); | 2322 | mutex_unlock(&ifmgd->mtx); |
2320 | assoc_bss = true; | 2323 | assoc_bss = true; |
2321 | } else { | 2324 | } else { |
@@ -2398,7 +2401,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2398 | sdata->name, req->bss->bssid, req->reason_code); | 2401 | sdata->name, req->bss->bssid, req->reason_code); |
2399 | 2402 | ||
2400 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | 2403 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
2401 | ieee80211_set_disassoc(sdata, false); | 2404 | ieee80211_set_disassoc(sdata, false, true); |
2402 | 2405 | ||
2403 | mutex_unlock(&ifmgd->mtx); | 2406 | mutex_unlock(&ifmgd->mtx); |
2404 | 2407 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index ce671dfd238c..e37355193ed1 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -12,8 +12,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
13 | struct sta_info *sta; | 13 | struct sta_info *sta; |
14 | 14 | ||
15 | if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) | 15 | ieee80211_scan_cancel(local); |
16 | ieee80211_scan_cancel(local); | ||
17 | 16 | ||
18 | ieee80211_stop_queues_by_reason(hw, | 17 | ieee80211_stop_queues_by_reason(hw, |
19 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 18 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
@@ -46,7 +45,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
46 | list_for_each_entry(sta, &local->sta_list, list) { | 45 | list_for_each_entry(sta, &local->sta_list, list) { |
47 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 46 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
48 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 47 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
49 | ieee80211_sta_tear_down_BA_sessions(sta); | 48 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
50 | } | 49 | } |
51 | 50 | ||
52 | if (sta->uploaded) { | 51 | if (sta->uploaded) { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0b0e83ebe3d5..b67221def584 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -819,6 +819,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
819 | if (unlikely((ieee80211_is_data(hdr->frame_control) || | 819 | if (unlikely((ieee80211_is_data(hdr->frame_control) || |
820 | ieee80211_is_pspoll(hdr->frame_control)) && | 820 | ieee80211_is_pspoll(hdr->frame_control)) && |
821 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | 821 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
822 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && | ||
822 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { | 823 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { |
823 | if ((!ieee80211_has_fromds(hdr->frame_control) && | 824 | if ((!ieee80211_has_fromds(hdr->frame_control) && |
824 | !ieee80211_has_tods(hdr->frame_control) && | 825 | !ieee80211_has_tods(hdr->frame_control) && |
@@ -845,7 +846,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
845 | int keyidx; | 846 | int keyidx; |
846 | int hdrlen; | 847 | int hdrlen; |
847 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | 848 | ieee80211_rx_result result = RX_DROP_UNUSABLE; |
848 | struct ieee80211_key *stakey = NULL; | 849 | struct ieee80211_key *sta_ptk = NULL; |
849 | int mmie_keyidx = -1; | 850 | int mmie_keyidx = -1; |
850 | __le16 fc; | 851 | __le16 fc; |
851 | 852 | ||
@@ -887,15 +888,15 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
887 | rx->key = NULL; | 888 | rx->key = NULL; |
888 | 889 | ||
889 | if (rx->sta) | 890 | if (rx->sta) |
890 | stakey = rcu_dereference(rx->sta->key); | 891 | sta_ptk = rcu_dereference(rx->sta->ptk); |
891 | 892 | ||
892 | fc = hdr->frame_control; | 893 | fc = hdr->frame_control; |
893 | 894 | ||
894 | if (!ieee80211_has_protected(fc)) | 895 | if (!ieee80211_has_protected(fc)) |
895 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | 896 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); |
896 | 897 | ||
897 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 898 | if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) { |
898 | rx->key = stakey; | 899 | rx->key = sta_ptk; |
899 | if ((status->flag & RX_FLAG_DECRYPTED) && | 900 | if ((status->flag & RX_FLAG_DECRYPTED) && |
900 | (status->flag & RX_FLAG_IV_STRIPPED)) | 901 | (status->flag & RX_FLAG_IV_STRIPPED)) |
901 | return RX_CONTINUE; | 902 | return RX_CONTINUE; |
@@ -911,7 +912,10 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
911 | if (mmie_keyidx < NUM_DEFAULT_KEYS || | 912 | if (mmie_keyidx < NUM_DEFAULT_KEYS || |
912 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | 913 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) |
913 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | 914 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ |
914 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | 915 | if (rx->sta) |
916 | rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]); | ||
917 | if (!rx->key) | ||
918 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | ||
915 | } else if (!ieee80211_has_protected(fc)) { | 919 | } else if (!ieee80211_has_protected(fc)) { |
916 | /* | 920 | /* |
917 | * The frame was not protected, so skip decryption. However, we | 921 | * The frame was not protected, so skip decryption. However, we |
@@ -954,17 +958,25 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
954 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); | 958 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); |
955 | keyidx = keyid >> 6; | 959 | keyidx = keyid >> 6; |
956 | 960 | ||
957 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); | 961 | /* check per-station GTK first, if multicast packet */ |
962 | if (is_multicast_ether_addr(hdr->addr1) && rx->sta) | ||
963 | rx->key = rcu_dereference(rx->sta->gtk[keyidx]); | ||
958 | 964 | ||
959 | /* | 965 | /* if not found, try default key */ |
960 | * RSNA-protected unicast frames should always be sent with | 966 | if (!rx->key) { |
961 | * pairwise or station-to-station keys, but for WEP we allow | 967 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); |
962 | * using a key index as well. | 968 | |
963 | */ | 969 | /* |
964 | if (rx->key && rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && | 970 | * RSNA-protected unicast frames should always be |
965 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && | 971 | * sent with pairwise or station-to-station keys, |
966 | !is_multicast_ether_addr(hdr->addr1)) | 972 | * but for WEP we allow using a key index as well. |
967 | rx->key = NULL; | 973 | */ |
974 | if (rx->key && | ||
975 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && | ||
976 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && | ||
977 | !is_multicast_ether_addr(hdr->addr1)) | ||
978 | rx->key = NULL; | ||
979 | } | ||
968 | } | 980 | } |
969 | 981 | ||
970 | if (rx->key) { | 982 | if (rx->key) { |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 5171a9581631..fb274db77e3c 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -249,12 +249,12 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
249 | return true; | 249 | return true; |
250 | } | 250 | } |
251 | 251 | ||
252 | static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 252 | static bool __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, |
253 | bool was_hw_scan) | ||
253 | { | 254 | { |
254 | struct ieee80211_local *local = hw_to_local(hw); | 255 | struct ieee80211_local *local = hw_to_local(hw); |
255 | bool was_hw_scan; | ||
256 | 256 | ||
257 | mutex_lock(&local->mtx); | 257 | lockdep_assert_held(&local->mtx); |
258 | 258 | ||
259 | /* | 259 | /* |
260 | * It's ok to abort a not-yet-running scan (that | 260 | * It's ok to abort a not-yet-running scan (that |
@@ -265,17 +265,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
265 | if (WARN_ON(!local->scanning && !aborted)) | 265 | if (WARN_ON(!local->scanning && !aborted)) |
266 | aborted = true; | 266 | aborted = true; |
267 | 267 | ||
268 | if (WARN_ON(!local->scan_req)) { | 268 | if (WARN_ON(!local->scan_req)) |
269 | mutex_unlock(&local->mtx); | 269 | return false; |
270 | return; | ||
271 | } | ||
272 | 270 | ||
273 | was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); | ||
274 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 271 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { |
275 | ieee80211_queue_delayed_work(&local->hw, | 272 | int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req); |
276 | &local->scan_work, 0); | 273 | if (rc == 0) |
277 | mutex_unlock(&local->mtx); | 274 | return false; |
278 | return; | ||
279 | } | 275 | } |
280 | 276 | ||
281 | kfree(local->hw_scan_req); | 277 | kfree(local->hw_scan_req); |
@@ -289,23 +285,25 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
289 | local->scanning = 0; | 285 | local->scanning = 0; |
290 | local->scan_channel = NULL; | 286 | local->scan_channel = NULL; |
291 | 287 | ||
292 | /* we only have to protect scan_req and hw/sw scan */ | 288 | return true; |
293 | mutex_unlock(&local->mtx); | 289 | } |
294 | |||
295 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
296 | if (was_hw_scan) | ||
297 | goto done; | ||
298 | |||
299 | ieee80211_configure_filter(local); | ||
300 | 290 | ||
301 | drv_sw_scan_complete(local); | 291 | static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw, |
292 | bool was_hw_scan) | ||
293 | { | ||
294 | struct ieee80211_local *local = hw_to_local(hw); | ||
302 | 295 | ||
303 | ieee80211_offchannel_return(local, true); | 296 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
297 | if (!was_hw_scan) { | ||
298 | ieee80211_configure_filter(local); | ||
299 | drv_sw_scan_complete(local); | ||
300 | ieee80211_offchannel_return(local, true); | ||
301 | } | ||
304 | 302 | ||
305 | done: | ||
306 | mutex_lock(&local->mtx); | 303 | mutex_lock(&local->mtx); |
307 | ieee80211_recalc_idle(local); | 304 | ieee80211_recalc_idle(local); |
308 | mutex_unlock(&local->mtx); | 305 | mutex_unlock(&local->mtx); |
306 | |||
309 | ieee80211_mlme_notify_scan_completed(local); | 307 | ieee80211_mlme_notify_scan_completed(local); |
310 | ieee80211_ibss_notify_scan_completed(local); | 308 | ieee80211_ibss_notify_scan_completed(local); |
311 | ieee80211_mesh_notify_scan_completed(local); | 309 | ieee80211_mesh_notify_scan_completed(local); |
@@ -366,6 +364,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
366 | struct ieee80211_local *local = sdata->local; | 364 | struct ieee80211_local *local = sdata->local; |
367 | int rc; | 365 | int rc; |
368 | 366 | ||
367 | lockdep_assert_held(&local->mtx); | ||
368 | |||
369 | if (local->scan_req) | 369 | if (local->scan_req) |
370 | return -EBUSY; | 370 | return -EBUSY; |
371 | 371 | ||
@@ -447,8 +447,8 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) | |||
447 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; | 447 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; |
448 | } | 448 | } |
449 | 449 | ||
450 | static int ieee80211_scan_state_decision(struct ieee80211_local *local, | 450 | static void ieee80211_scan_state_decision(struct ieee80211_local *local, |
451 | unsigned long *next_delay) | 451 | unsigned long *next_delay) |
452 | { | 452 | { |
453 | bool associated = false; | 453 | bool associated = false; |
454 | bool tx_empty = true; | 454 | bool tx_empty = true; |
@@ -458,12 +458,6 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
458 | struct ieee80211_sub_if_data *sdata; | 458 | struct ieee80211_sub_if_data *sdata; |
459 | struct ieee80211_channel *next_chan; | 459 | struct ieee80211_channel *next_chan; |
460 | 460 | ||
461 | /* if no more bands/channels left, complete scan and advance to the idle state */ | ||
462 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | ||
463 | __ieee80211_scan_completed(&local->hw, false); | ||
464 | return 1; | ||
465 | } | ||
466 | |||
467 | /* | 461 | /* |
468 | * check if at least one STA interface is associated, | 462 | * check if at least one STA interface is associated, |
469 | * check if at least one STA interface has pending tx frames | 463 | * check if at least one STA interface has pending tx frames |
@@ -535,7 +529,6 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
535 | } | 529 | } |
536 | 530 | ||
537 | *next_delay = 0; | 531 | *next_delay = 0; |
538 | return 0; | ||
539 | } | 532 | } |
540 | 533 | ||
541 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | 534 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, |
@@ -651,28 +644,17 @@ void ieee80211_scan_work(struct work_struct *work) | |||
651 | container_of(work, struct ieee80211_local, scan_work.work); | 644 | container_of(work, struct ieee80211_local, scan_work.work); |
652 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 645 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
653 | unsigned long next_delay = 0; | 646 | unsigned long next_delay = 0; |
647 | bool aborted, hw_scan, finish; | ||
654 | 648 | ||
655 | if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { | 649 | mutex_lock(&local->mtx); |
656 | bool aborted; | ||
657 | 650 | ||
651 | if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { | ||
658 | aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); | 652 | aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); |
659 | __ieee80211_scan_completed(&local->hw, aborted); | 653 | goto out_complete; |
660 | return; | ||
661 | } | ||
662 | |||
663 | mutex_lock(&local->mtx); | ||
664 | if (!sdata || !local->scan_req) { | ||
665 | mutex_unlock(&local->mtx); | ||
666 | return; | ||
667 | } | 654 | } |
668 | 655 | ||
669 | if (local->hw_scan_req) { | 656 | if (!sdata || !local->scan_req) |
670 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); | 657 | goto out; |
671 | mutex_unlock(&local->mtx); | ||
672 | if (rc) | ||
673 | __ieee80211_scan_completed(&local->hw, true); | ||
674 | return; | ||
675 | } | ||
676 | 658 | ||
677 | if (local->scan_req && !local->scanning) { | 659 | if (local->scan_req && !local->scanning) { |
678 | struct cfg80211_scan_request *req = local->scan_req; | 660 | struct cfg80211_scan_request *req = local->scan_req; |
@@ -682,21 +664,21 @@ void ieee80211_scan_work(struct work_struct *work) | |||
682 | local->scan_sdata = NULL; | 664 | local->scan_sdata = NULL; |
683 | 665 | ||
684 | rc = __ieee80211_start_scan(sdata, req); | 666 | rc = __ieee80211_start_scan(sdata, req); |
685 | mutex_unlock(&local->mtx); | 667 | if (rc) { |
686 | 668 | /* need to complete scan in cfg80211 */ | |
687 | if (rc) | 669 | local->scan_req = req; |
688 | __ieee80211_scan_completed(&local->hw, true); | 670 | aborted = true; |
689 | return; | 671 | goto out_complete; |
672 | } else | ||
673 | goto out; | ||
690 | } | 674 | } |
691 | 675 | ||
692 | mutex_unlock(&local->mtx); | ||
693 | |||
694 | /* | 676 | /* |
695 | * Avoid re-scheduling when the sdata is going away. | 677 | * Avoid re-scheduling when the sdata is going away. |
696 | */ | 678 | */ |
697 | if (!ieee80211_sdata_running(sdata)) { | 679 | if (!ieee80211_sdata_running(sdata)) { |
698 | __ieee80211_scan_completed(&local->hw, true); | 680 | aborted = true; |
699 | return; | 681 | goto out_complete; |
700 | } | 682 | } |
701 | 683 | ||
702 | /* | 684 | /* |
@@ -706,8 +688,12 @@ void ieee80211_scan_work(struct work_struct *work) | |||
706 | do { | 688 | do { |
707 | switch (local->next_scan_state) { | 689 | switch (local->next_scan_state) { |
708 | case SCAN_DECISION: | 690 | case SCAN_DECISION: |
709 | if (ieee80211_scan_state_decision(local, &next_delay)) | 691 | /* if no more bands/channels left, complete scan */ |
710 | return; | 692 | if (local->scan_channel_idx >= local->scan_req->n_channels) { |
693 | aborted = false; | ||
694 | goto out_complete; | ||
695 | } | ||
696 | ieee80211_scan_state_decision(local, &next_delay); | ||
711 | break; | 697 | break; |
712 | case SCAN_SET_CHANNEL: | 698 | case SCAN_SET_CHANNEL: |
713 | ieee80211_scan_state_set_channel(local, &next_delay); | 699 | ieee80211_scan_state_set_channel(local, &next_delay); |
@@ -725,6 +711,19 @@ void ieee80211_scan_work(struct work_struct *work) | |||
725 | } while (next_delay == 0); | 711 | } while (next_delay == 0); |
726 | 712 | ||
727 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay); | 713 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay); |
714 | mutex_unlock(&local->mtx); | ||
715 | return; | ||
716 | |||
717 | out_complete: | ||
718 | hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); | ||
719 | finish = __ieee80211_scan_completed(&local->hw, aborted, hw_scan); | ||
720 | mutex_unlock(&local->mtx); | ||
721 | if (finish) | ||
722 | __ieee80211_scan_completed_finish(&local->hw, hw_scan); | ||
723 | return; | ||
724 | |||
725 | out: | ||
726 | mutex_unlock(&local->mtx); | ||
728 | } | 727 | } |
729 | 728 | ||
730 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 729 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
@@ -786,21 +785,40 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
786 | return ret; | 785 | return ret; |
787 | } | 786 | } |
788 | 787 | ||
788 | /* | ||
789 | * Only call this function when a scan can't be queued -- under RTNL. | ||
790 | */ | ||
789 | void ieee80211_scan_cancel(struct ieee80211_local *local) | 791 | void ieee80211_scan_cancel(struct ieee80211_local *local) |
790 | { | 792 | { |
791 | bool abortscan; | 793 | bool abortscan; |
792 | 794 | bool finish = false; | |
793 | cancel_delayed_work_sync(&local->scan_work); | ||
794 | 795 | ||
795 | /* | 796 | /* |
796 | * Only call this function when a scan can't be | 797 | * We are only canceling software scan, or deferred scan that was not |
797 | * queued -- mostly at suspend under RTNL. | 798 | * yet really started (see __ieee80211_start_scan ). |
799 | * | ||
800 | * Regarding hardware scan: | ||
801 | * - we can not call __ieee80211_scan_completed() as when | ||
802 | * SCAN_HW_SCANNING bit is set this function change | ||
803 | * local->hw_scan_req to operate on 5G band, what race with | ||
804 | * driver which can use local->hw_scan_req | ||
805 | * | ||
806 | * - we can not cancel scan_work since driver can schedule it | ||
807 | * by ieee80211_scan_completed(..., true) to finish scan | ||
808 | * | ||
809 | * Hence low lever driver is responsible for canceling HW scan. | ||
798 | */ | 810 | */ |
811 | |||
799 | mutex_lock(&local->mtx); | 812 | mutex_lock(&local->mtx); |
800 | abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || | 813 | abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning); |
801 | (!local->scanning && local->scan_req); | 814 | if (abortscan) |
815 | finish = __ieee80211_scan_completed(&local->hw, true, false); | ||
802 | mutex_unlock(&local->mtx); | 816 | mutex_unlock(&local->mtx); |
803 | 817 | ||
804 | if (abortscan) | 818 | if (abortscan) { |
805 | __ieee80211_scan_completed(&local->hw, true); | 819 | /* The scan is canceled, but stop work from being pending */ |
820 | cancel_delayed_work_sync(&local->scan_work); | ||
821 | } | ||
822 | if (finish) | ||
823 | __ieee80211_scan_completed_finish(&local->hw, false); | ||
806 | } | 824 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ca2cba9cea87..6d8f897d8763 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -616,7 +616,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
616 | struct ieee80211_sub_if_data *sdata; | 616 | struct ieee80211_sub_if_data *sdata; |
617 | struct sk_buff *skb; | 617 | struct sk_buff *skb; |
618 | unsigned long flags; | 618 | unsigned long flags; |
619 | int ret; | 619 | int ret, i; |
620 | 620 | ||
621 | might_sleep(); | 621 | might_sleep(); |
622 | 622 | ||
@@ -633,7 +633,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
633 | * will be sufficient. | 633 | * will be sufficient. |
634 | */ | 634 | */ |
635 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 635 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
636 | ieee80211_sta_tear_down_BA_sessions(sta); | 636 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
637 | 637 | ||
638 | spin_lock_irqsave(&local->sta_lock, flags); | 638 | spin_lock_irqsave(&local->sta_lock, flags); |
639 | ret = sta_info_hash_del(local, sta); | 639 | ret = sta_info_hash_del(local, sta); |
@@ -644,10 +644,10 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
644 | if (ret) | 644 | if (ret) |
645 | return ret; | 645 | return ret; |
646 | 646 | ||
647 | if (sta->key) { | 647 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) |
648 | ieee80211_key_free(local, sta->key); | 648 | ieee80211_key_free(local, sta->gtk[i]); |
649 | WARN_ON(sta->key); | 649 | if (sta->ptk) |
650 | } | 650 | ieee80211_key_free(local, sta->ptk); |
651 | 651 | ||
652 | sta->dead = true; | 652 | sta->dead = true; |
653 | 653 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 810c5ce98316..9265acadef32 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -79,6 +79,7 @@ enum ieee80211_sta_info_flags { | |||
79 | * @dialog_token: dialog token for aggregation session | 79 | * @dialog_token: dialog token for aggregation session |
80 | * @state: session state (see above) | 80 | * @state: session state (see above) |
81 | * @stop_initiator: initiator of a session stop | 81 | * @stop_initiator: initiator of a session stop |
82 | * @tx_stop: TX DelBA frame when stopping | ||
82 | * | 83 | * |
83 | * This structure is protected by RCU and the per-station | 84 | * This structure is protected by RCU and the per-station |
84 | * spinlock. Assignments to the array holding it must hold | 85 | * spinlock. Assignments to the array holding it must hold |
@@ -95,6 +96,7 @@ struct tid_ampdu_tx { | |||
95 | unsigned long state; | 96 | unsigned long state; |
96 | u8 dialog_token; | 97 | u8 dialog_token; |
97 | u8 stop_initiator; | 98 | u8 stop_initiator; |
99 | bool tx_stop; | ||
98 | }; | 100 | }; |
99 | 101 | ||
100 | /** | 102 | /** |
@@ -197,7 +199,8 @@ enum plink_state { | |||
197 | * @hnext: hash table linked list pointer | 199 | * @hnext: hash table linked list pointer |
198 | * @local: pointer to the global information | 200 | * @local: pointer to the global information |
199 | * @sdata: virtual interface this station belongs to | 201 | * @sdata: virtual interface this station belongs to |
200 | * @key: peer key negotiated with this station, if any | 202 | * @ptk: peer key negotiated with this station, if any |
203 | * @gtk: group keys negotiated with this station, if any | ||
201 | * @rate_ctrl: rate control algorithm reference | 204 | * @rate_ctrl: rate control algorithm reference |
202 | * @rate_ctrl_priv: rate control private per-STA pointer | 205 | * @rate_ctrl_priv: rate control private per-STA pointer |
203 | * @last_tx_rate: rate used for last transmit, to report to userspace as | 206 | * @last_tx_rate: rate used for last transmit, to report to userspace as |
@@ -252,7 +255,8 @@ struct sta_info { | |||
252 | struct sta_info *hnext; | 255 | struct sta_info *hnext; |
253 | struct ieee80211_local *local; | 256 | struct ieee80211_local *local; |
254 | struct ieee80211_sub_if_data *sdata; | 257 | struct ieee80211_sub_if_data *sdata; |
255 | struct ieee80211_key *key; | 258 | struct ieee80211_key *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
259 | struct ieee80211_key *ptk; | ||
256 | struct rate_control_ref *rate_ctrl; | 260 | struct rate_control_ref *rate_ctrl; |
257 | void *rate_ctrl_priv; | 261 | void *rate_ctrl_priv; |
258 | spinlock_t lock; | 262 | spinlock_t lock; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index dd85006c4fe8..3153c19893b8 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -176,7 +176,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
176 | 176 | ||
177 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 177 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
178 | /* the HW cannot have attempted that rate */ | 178 | /* the HW cannot have attempted that rate */ |
179 | if (i >= hw->max_rates) { | 179 | if (i >= hw->max_report_rates) { |
180 | info->status.rates[i].idx = -1; | 180 | info->status.rates[i].idx = -1; |
181 | info->status.rates[i].count = 0; | 181 | info->status.rates[i].count = 0; |
182 | } else if (info->status.rates[i].idx >= 0) { | 182 | } else if (info->status.rates[i].idx >= 0) { |
@@ -377,7 +377,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
377 | skb2 = skb_clone(skb, GFP_ATOMIC); | 377 | skb2 = skb_clone(skb, GFP_ATOMIC); |
378 | if (skb2) { | 378 | if (skb2) { |
379 | skb2->dev = prev_dev; | 379 | skb2->dev = prev_dev; |
380 | netif_receive_skb(skb2); | 380 | netif_rx(skb2); |
381 | } | 381 | } |
382 | } | 382 | } |
383 | 383 | ||
@@ -386,7 +386,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
386 | } | 386 | } |
387 | if (prev_dev) { | 387 | if (prev_dev) { |
388 | skb->dev = prev_dev; | 388 | skb->dev = prev_dev; |
389 | netif_receive_skb(skb); | 389 | netif_rx(skb); |
390 | skb = NULL; | 390 | skb = NULL; |
391 | } | 391 | } |
392 | rcu_read_unlock(); | 392 | rcu_read_unlock(); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e1733dcb58a7..96c594309506 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -273,6 +273,9 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
273 | */ | 273 | */ |
274 | return TX_DROP; | 274 | return TX_DROP; |
275 | 275 | ||
276 | if (tx->sdata->vif.type == NL80211_IFTYPE_WDS) | ||
277 | return TX_CONTINUE; | ||
278 | |||
276 | if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | 279 | if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
277 | return TX_CONTINUE; | 280 | return TX_CONTINUE; |
278 | 281 | ||
@@ -529,7 +532,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
529 | 532 | ||
530 | if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) | 533 | if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) |
531 | tx->key = NULL; | 534 | tx->key = NULL; |
532 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 535 | else if (tx->sta && (key = rcu_dereference(tx->sta->ptk))) |
533 | tx->key = key; | 536 | tx->key = key; |
534 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 537 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
535 | is_multicast_ether_addr(hdr->addr1) && | 538 | is_multicast_ether_addr(hdr->addr1) && |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index aba025d748e9..0b6fc92bc0d7 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1221,7 +1221,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1221 | mutex_lock(&local->sta_mtx); | 1221 | mutex_lock(&local->sta_mtx); |
1222 | 1222 | ||
1223 | list_for_each_entry(sta, &local->sta_list, list) { | 1223 | list_for_each_entry(sta, &local->sta_list, list) { |
1224 | ieee80211_sta_tear_down_BA_sessions(sta); | 1224 | ieee80211_sta_tear_down_BA_sessions(sta, true); |
1225 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); | 1225 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); |
1226 | } | 1226 | } |
1227 | 1227 | ||
@@ -1297,16 +1297,12 @@ static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, | |||
1297 | } | 1297 | } |
1298 | 1298 | ||
1299 | /* must hold iflist_mtx */ | 1299 | /* must hold iflist_mtx */ |
1300 | void ieee80211_recalc_smps(struct ieee80211_local *local, | 1300 | void ieee80211_recalc_smps(struct ieee80211_local *local) |
1301 | struct ieee80211_sub_if_data *forsdata) | ||
1302 | { | 1301 | { |
1303 | struct ieee80211_sub_if_data *sdata; | 1302 | struct ieee80211_sub_if_data *sdata; |
1304 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; | 1303 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; |
1305 | int count = 0; | 1304 | int count = 0; |
1306 | 1305 | ||
1307 | if (forsdata) | ||
1308 | lockdep_assert_held(&forsdata->u.mgd.mtx); | ||
1309 | |||
1310 | lockdep_assert_held(&local->iflist_mtx); | 1306 | lockdep_assert_held(&local->iflist_mtx); |
1311 | 1307 | ||
1312 | /* | 1308 | /* |
@@ -1324,18 +1320,8 @@ void ieee80211_recalc_smps(struct ieee80211_local *local, | |||
1324 | continue; | 1320 | continue; |
1325 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1321 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1326 | goto set; | 1322 | goto set; |
1327 | if (sdata != forsdata) { | 1323 | |
1328 | /* | 1324 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); |
1329 | * This nested is ok -- we are holding the iflist_mtx | ||
1330 | * so can't get here twice or so. But it's required | ||
1331 | * since normally we acquire it first and then the | ||
1332 | * iflist_mtx. | ||
1333 | */ | ||
1334 | mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING); | ||
1335 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); | ||
1336 | mutex_unlock(&sdata->u.mgd.mtx); | ||
1337 | } else | ||
1338 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); | ||
1339 | 1325 | ||
1340 | if (count > 1) { | 1326 | if (count > 1) { |
1341 | smps_mode = IEEE80211_SMPS_OFF; | 1327 | smps_mode = IEEE80211_SMPS_OFF; |