aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-05-02 19:02:02 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-14 16:29:34 -0400
commit07346f81e87d6e4cca7ae9adfa711d0c61c87b56 (patch)
tree237450c49843e0e19afc79356240a891da64d9fa /net/mac80211/mlme.c
parent3434fbd39862d471c92b66c28cd449deea8e9f90 (diff)
mac80211: proper STA info locking
As discussed earlier, we can unify locking in struct sta_info and use just a single spinlock protecting all members of the structure that need protection. Many don't, but one of the especially bad ones is the 'flags' member that can currently be clobbered when RX and TX is being processed on different CPUs at the same time. Because having four spinlocks for different, mostly exclusive parts of a single structure is overkill, this patch also kills the ampdu and mesh plink spinlocks and uses just a single one for everything. Because none of the spinlocks are nested, this is safe. It remains to be seen whether or not we should make the sta flags use atomic bit operations instead, for now though this is a safe thing and using atomic operations instead will be very simple using the new static inline functions this patch introduces for accessing sta->flags. Since spin_lock_bh() is used with this lock, there shouldn't be any contention even if aggregation is enabled at around the same time as both requires frame transmission/reception which is in a bh context. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Cc: Tomas Winkler <tomasw@gmail.com> Cc: Ron Rindjunsky <ron.rindjunsky@intel.com> Cc: Luis Carlos Cobo <luisca@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c38
1 files changed, 19 insertions, 19 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 108c6fc42fe2..6c4b27be35da 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1241,7 +1241,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
1241 1241
1242 1242
1243 /* examine state machine */ 1243 /* examine state machine */
1244 spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); 1244 spin_lock_bh(&sta->lock);
1245 1245
1246 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { 1246 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
1247#ifdef CONFIG_MAC80211_HT_DEBUG 1247#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -1308,7 +1308,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
1308 tid_agg_rx->stored_mpdu_num = 0; 1308 tid_agg_rx->stored_mpdu_num = 0;
1309 status = WLAN_STATUS_SUCCESS; 1309 status = WLAN_STATUS_SUCCESS;
1310end: 1310end:
1311 spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); 1311 spin_unlock_bh(&sta->lock);
1312 1312
1313end_no_lock: 1313end_no_lock:
1314 ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, 1314 ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid,
@@ -1340,10 +1340,10 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
1340 1340
1341 state = &sta->ampdu_mlme.tid_state_tx[tid]; 1341 state = &sta->ampdu_mlme.tid_state_tx[tid];
1342 1342
1343 spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); 1343 spin_lock_bh(&sta->lock);
1344 1344
1345 if (!(*state & HT_ADDBA_REQUESTED_MSK)) { 1345 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
1346 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 1346 spin_unlock_bh(&sta->lock);
1347 printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" 1347 printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
1348 "%d\n", *state); 1348 "%d\n", *state);
1349 goto addba_resp_exit; 1349 goto addba_resp_exit;
@@ -1351,7 +1351,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
1351 1351
1352 if (mgmt->u.action.u.addba_resp.dialog_token != 1352 if (mgmt->u.action.u.addba_resp.dialog_token !=
1353 sta->ampdu_mlme.tid_tx[tid]->dialog_token) { 1353 sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
1354 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 1354 spin_unlock_bh(&sta->lock);
1355#ifdef CONFIG_MAC80211_HT_DEBUG 1355#ifdef CONFIG_MAC80211_HT_DEBUG
1356 printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); 1356 printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
1357#endif /* CONFIG_MAC80211_HT_DEBUG */ 1357#endif /* CONFIG_MAC80211_HT_DEBUG */
@@ -1375,7 +1375,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
1375 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); 1375 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
1376 } 1376 }
1377 1377
1378 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 1378 spin_unlock_bh(&sta->lock);
1379 printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid); 1379 printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid);
1380 } else { 1380 } else {
1381 printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid); 1381 printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid);
@@ -1383,7 +1383,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
1383 sta->ampdu_mlme.addba_req_num[tid]++; 1383 sta->ampdu_mlme.addba_req_num[tid]++;
1384 /* this will allow the state check in stop_BA_session */ 1384 /* this will allow the state check in stop_BA_session */
1385 *state = HT_AGG_STATE_OPERATIONAL; 1385 *state = HT_AGG_STATE_OPERATIONAL;
1386 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 1386 spin_unlock_bh(&sta->lock);
1387 ieee80211_stop_tx_ba_session(hw, sta->addr, tid, 1387 ieee80211_stop_tx_ba_session(hw, sta->addr, tid,
1388 WLAN_BACK_INITIATOR); 1388 WLAN_BACK_INITIATOR);
1389 } 1389 }
@@ -1453,17 +1453,17 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
1453 } 1453 }
1454 1454
1455 /* check if TID is in operational state */ 1455 /* check if TID is in operational state */
1456 spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); 1456 spin_lock_bh(&sta->lock);
1457 if (sta->ampdu_mlme.tid_state_rx[tid] 1457 if (sta->ampdu_mlme.tid_state_rx[tid]
1458 != HT_AGG_STATE_OPERATIONAL) { 1458 != HT_AGG_STATE_OPERATIONAL) {
1459 spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); 1459 spin_unlock_bh(&sta->lock);
1460 rcu_read_unlock(); 1460 rcu_read_unlock();
1461 return; 1461 return;
1462 } 1462 }
1463 sta->ampdu_mlme.tid_state_rx[tid] = 1463 sta->ampdu_mlme.tid_state_rx[tid] =
1464 HT_AGG_STATE_REQ_STOP_BA_MSK | 1464 HT_AGG_STATE_REQ_STOP_BA_MSK |
1465 (initiator << HT_AGG_STATE_INITIATOR_SHIFT); 1465 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
1466 spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); 1466 spin_unlock_bh(&sta->lock);
1467 1467
1468 /* stop HW Rx aggregation. ampdu_action existence 1468 /* stop HW Rx aggregation. ampdu_action existence
1469 * already verified in session init so we add the BUG_ON */ 1469 * already verified in session init so we add the BUG_ON */
@@ -1540,10 +1540,10 @@ static void ieee80211_sta_process_delba(struct net_device *dev,
1540 ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, 1540 ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid,
1541 WLAN_BACK_INITIATOR, 0); 1541 WLAN_BACK_INITIATOR, 0);
1542 else { /* WLAN_BACK_RECIPIENT */ 1542 else { /* WLAN_BACK_RECIPIENT */
1543 spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); 1543 spin_lock_bh(&sta->lock);
1544 sta->ampdu_mlme.tid_state_tx[tid] = 1544 sta->ampdu_mlme.tid_state_tx[tid] =
1545 HT_AGG_STATE_OPERATIONAL; 1545 HT_AGG_STATE_OPERATIONAL;
1546 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 1546 spin_unlock_bh(&sta->lock);
1547 ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, 1547 ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid,
1548 WLAN_BACK_RECIPIENT); 1548 WLAN_BACK_RECIPIENT);
1549 } 1549 }
@@ -1580,9 +1580,9 @@ void sta_addba_resp_timer_expired(unsigned long data)
1580 1580
1581 state = &sta->ampdu_mlme.tid_state_tx[tid]; 1581 state = &sta->ampdu_mlme.tid_state_tx[tid];
1582 /* check if the TID waits for addBA response */ 1582 /* check if the TID waits for addBA response */
1583 spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); 1583 spin_lock_bh(&sta->lock);
1584 if (!(*state & HT_ADDBA_REQUESTED_MSK)) { 1584 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
1585 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 1585 spin_unlock_bh(&sta->lock);
1586 *state = HT_AGG_STATE_IDLE; 1586 *state = HT_AGG_STATE_IDLE;
1587 printk(KERN_DEBUG "timer expired on tid %d but we are not " 1587 printk(KERN_DEBUG "timer expired on tid %d but we are not "
1588 "expecting addBA response there", tid); 1588 "expecting addBA response there", tid);
@@ -1593,7 +1593,7 @@ void sta_addba_resp_timer_expired(unsigned long data)
1593 1593
1594 /* go through the state check in stop_BA_session */ 1594 /* go through the state check in stop_BA_session */
1595 *state = HT_AGG_STATE_OPERATIONAL; 1595 *state = HT_AGG_STATE_OPERATIONAL;
1596 spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); 1596 spin_unlock_bh(&sta->lock);
1597 ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, 1597 ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid,
1598 WLAN_BACK_INITIATOR); 1598 WLAN_BACK_INITIATOR);
1599 1599
@@ -1984,8 +1984,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1984 * to between the sta_info_alloc() and sta_info_insert() above. 1984 * to between the sta_info_alloc() and sta_info_insert() above.
1985 */ 1985 */
1986 1986
1987 sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | 1987 set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
1988 WLAN_STA_AUTHORIZED; 1988 WLAN_STA_AUTHORIZED);
1989 1989
1990 rates = 0; 1990 rates = 0;
1991 basic_rates = 0; 1991 basic_rates = 0;
@@ -2044,7 +2044,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2044 rate_control_rate_init(sta, local); 2044 rate_control_rate_init(sta, local);
2045 2045
2046 if (elems.wmm_param) { 2046 if (elems.wmm_param) {
2047 sta->flags |= WLAN_STA_WME; 2047 set_sta_flags(sta, WLAN_STA_WME);
2048 rcu_read_unlock(); 2048 rcu_read_unlock();
2049 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, 2049 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
2050 elems.wmm_param_len); 2050 elems.wmm_param_len);
@@ -4237,7 +4237,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev,
4237 if (!sta) 4237 if (!sta)
4238 return NULL; 4238 return NULL;
4239 4239
4240 sta->flags |= WLAN_STA_AUTHORIZED; 4240 set_sta_flags(sta, WLAN_STA_AUTHORIZED);
4241 4241
4242 sta->supp_rates[local->hw.conf.channel->band] = 4242 sta->supp_rates[local->hw.conf.channel->band] =
4243 sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band]; 4243 sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band];