Commit 07346f81 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

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: default avatarJohannes 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: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3434fbd3
......@@ -360,9 +360,9 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
unsigned long state;
DECLARE_MAC_BUF(mac);
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_lock_bh(&sta->lock);
state = sta->ampdu_mlme.tid_state_tx[tid];
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
if (state == HT_AGG_STATE_IDLE &&
rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
......
......@@ -602,6 +602,7 @@ static void sta_apply_parameters(struct ieee80211_local *local,
*/
if (params->station_flags & STATION_FLAG_CHANGED) {
spin_lock_bh(&sta->lock);
sta->flags &= ~WLAN_STA_AUTHORIZED;
if (params->station_flags & STATION_FLAG_AUTHORIZED)
sta->flags |= WLAN_STA_AUTHORIZED;
......@@ -613,6 +614,7 @@ static void sta_apply_parameters(struct ieee80211_local *local,
sta->flags &= ~WLAN_STA_WME;
if (params->station_flags & STATION_FLAG_WME)
sta->flags |= WLAN_STA_WME;
spin_unlock_bh(&sta->lock);
}
/*
......
......@@ -74,14 +74,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
{
char buf[100];
struct sta_info *sta = file->private_data;
u32 staflags = get_sta_flags(sta);
int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
sta->flags & WLAN_STA_PS ? "PS\n" : "",
sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
sta->flags & WLAN_STA_WME ? "WME\n" : "",
sta->flags & WLAN_STA_WDS ? "WDS\n" : "");
staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
staflags & WLAN_STA_PS ? "PS\n" : "",
staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
staflags & WLAN_STA_WME ? "WME\n" : "",
staflags & WLAN_STA_WDS ? "WDS\n" : "");
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
STA_OPS(flags);
......
......@@ -321,7 +321,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
* some hardware cannot handle TKIP with QoS, so
* we indicate whether QoS could be in use.
*/
if (sta->flags & WLAN_STA_WME)
if (test_sta_flags(sta, WLAN_STA_WME))
key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
/*
......@@ -342,7 +342,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
/* same here, the AP could be using QoS */
ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
if (ap) {
if (ap->flags & WLAN_STA_WME)
if (test_sta_flags(ap, WLAN_STA_WME))
key->conf.flags |=
IEEE80211_KEY_FLAG_WMM_STA;
}
......
......@@ -346,6 +346,7 @@ static int ieee80211_open(struct net_device *dev)
goto err_del_interface;
}
/* no locking required since STA is not live yet */
sta->flags |= WLAN_STA_AUTHORIZED;
res = sta_info_insert(sta);
......@@ -588,7 +589,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
return -ENOENT;
}
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_lock_bh(&sta->lock);
/* we have tried too many times, receiver does not want A-MPDU */
if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
......@@ -691,7 +692,7 @@ start_ba_err:
spin_unlock_bh(&local->mdev->queue_lock);
ret = -EBUSY;
start_ba_exit:
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return ret;
}
......@@ -719,7 +720,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
/* check if the TID is in aggregation */
state = &sta->ampdu_mlme.tid_state_tx[tid];
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_lock_bh(&sta->lock);
if (*state != HT_AGG_STATE_OPERATIONAL) {
ret = -ENOENT;
......@@ -749,7 +750,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
}
stop_BA_exit:
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return ret;
}
......@@ -778,12 +779,12 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
}
state = &sta->ampdu_mlme.tid_state_tx[tid];
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_lock_bh(&sta->lock);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
*state);
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
}
......@@ -796,7 +797,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
}
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
}
EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
......@@ -830,10 +831,10 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
}
state = &sta->ampdu_mlme.tid_state_tx[tid];
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_lock_bh(&sta->lock);
if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
}
......@@ -860,7 +861,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
sta->ampdu_mlme.addba_req_num[tid] = 0;
kfree(sta->ampdu_mlme.tid_tx[tid]);
sta->ampdu_mlme.tid_tx[tid] = NULL;
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
}
......@@ -1315,7 +1316,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
* packet. If the STA went to power save mode, this will happen
* happen when it wakes up for the next time.
*/
sta->flags |= WLAN_STA_CLEAR_PS_FILT;
set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT);
/*
* This code races in the following way:
......@@ -1347,7 +1348,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
* can be unknown, for example with different interrupt status
* bits.
*/
if (sta->flags & WLAN_STA_PS &&
if (test_sta_flags(sta, WLAN_STA_PS) &&
skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
ieee80211_remove_tx_extra(local, sta->key, skb,
&status->control);
......@@ -1355,7 +1356,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
return;
}
if (!(sta->flags & WLAN_STA_PS) &&
if (!test_sta_flags(sta, WLAN_STA_PS) &&
!(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
/* Software retry the packet once */
status->control.flags |= IEEE80211_TXCTL_REQUEUE;
......@@ -1370,7 +1371,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
"queue_len=%d PS=%d @%lu\n",
wiphy_name(local->hw.wiphy),
skb_queue_len(&sta->tx_filtered),
!!(sta->flags & WLAN_STA_PS), jiffies);
!!test_sta_flags(sta, WLAN_STA_PS), jiffies);
dev_kfree_skb(skb);
}
......@@ -1399,7 +1400,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
struct sta_info *sta;
sta = sta_info_get(local, hdr->addr1);
if (sta) {
if (sta->flags & WLAN_STA_PS) {
if (test_sta_flags(sta, WLAN_STA_PS)) {
/*
* The STA is in power save mode, so assume
* that this TX packet failed because of that.
......
......@@ -79,7 +79,7 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
*
* @sta: mes peer link to restart
*
* Locking: this function must be called holding sta->plink_lock
* Locking: this function must be called holding sta->lock
*/
static inline void mesh_plink_fsm_restart(struct sta_info *sta)
{
......@@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
if (!sta)
return NULL;
sta->flags |= WLAN_STA_AUTHORIZED;
sta->flags = WLAN_STA_AUTHORIZED;
sta->supp_rates[local->hw.conf.channel->band] = rates;
return sta;
......@@ -118,7 +118,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
*
* All mesh paths with this peer as next hop will be flushed
*
* Locking: the caller must hold sta->plink_lock
* Locking: the caller must hold sta->lock
*/
static void __mesh_plink_deactivate(struct sta_info *sta)
{
......@@ -139,9 +139,9 @@ static void __mesh_plink_deactivate(struct sta_info *sta)
*/
void mesh_plink_deactivate(struct sta_info *sta)
{
spin_lock_bh(&sta->plink_lock);
spin_lock_bh(&sta->lock);
__mesh_plink_deactivate(sta);
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
}
static int mesh_plink_frame_tx(struct net_device *dev,
......@@ -270,10 +270,10 @@ static void mesh_plink_timer(unsigned long data)
*/
sta = (struct sta_info *) data;
spin_lock_bh(&sta->plink_lock);
spin_lock_bh(&sta->lock);
if (sta->ignore_plink_timer) {
sta->ignore_plink_timer = false;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
return;
}
mpl_dbg("Mesh plink timer for %s fired on state %d\n",
......@@ -298,7 +298,7 @@ static void mesh_plink_timer(unsigned long data)
rand % sta->plink_timeout;
++sta->plink_retries;
mod_plink_timer(sta, sta->plink_timeout);
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
0, 0);
break;
......@@ -311,7 +311,7 @@ static void mesh_plink_timer(unsigned long data)
reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT);
sta->plink_state = PLINK_HOLDING;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid,
reason);
break;
......@@ -319,10 +319,10 @@ static void mesh_plink_timer(unsigned long data)
/* holding timer */
del_timer(&sta->plink_timer);
mesh_plink_fsm_restart(sta);
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
default:
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
}
}
......@@ -344,16 +344,16 @@ int mesh_plink_open(struct sta_info *sta)
DECLARE_MAC_BUF(mac);
#endif
spin_lock_bh(&sta->plink_lock);
spin_lock_bh(&sta->lock);
get_random_bytes(&llid, 2);
sta->llid = llid;
if (sta->plink_state != PLINK_LISTEN) {
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
return -EBUSY;
}
sta->plink_state = PLINK_OPN_SNT;
mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mpl_dbg("Mesh plink: starting establishment with %s\n",
print_mac(mac, sta->addr));
......@@ -367,10 +367,10 @@ void mesh_plink_block(struct sta_info *sta)
DECLARE_MAC_BUF(mac);
#endif
spin_lock_bh(&sta->plink_lock);
spin_lock_bh(&sta->lock);
__mesh_plink_deactivate(sta);
sta->plink_state = PLINK_BLOCKED;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
}
int mesh_plink_close(struct sta_info *sta)
......@@ -383,14 +383,14 @@ int mesh_plink_close(struct sta_info *sta)
mpl_dbg("Mesh plink: closing link with %s\n",
print_mac(mac, sta->addr));
spin_lock_bh(&sta->plink_lock);
spin_lock_bh(&sta->lock);
sta->reason = cpu_to_le16(MESH_LINK_CANCELLED);
reason = sta->reason;
if (sta->plink_state == PLINK_LISTEN ||
sta->plink_state == PLINK_BLOCKED) {
mesh_plink_fsm_restart(sta);
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
return 0;
} else if (sta->plink_state == PLINK_ESTAB) {
__mesh_plink_deactivate(sta);
......@@ -402,7 +402,7 @@ int mesh_plink_close(struct sta_info *sta)
sta->plink_state = PLINK_HOLDING;
llid = sta->llid;
plid = sta->plid;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
return 0;
......@@ -490,7 +490,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
/* avoid warning */
break;
}
spin_lock_bh(&sta->plink_lock);
spin_lock_bh(&sta->lock);
} else if (!sta) {
/* ftype == PLINK_OPEN */
u64 rates;
......@@ -512,9 +512,9 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
return;
}
event = OPN_ACPT;
spin_lock_bh(&sta->plink_lock);
spin_lock_bh(&sta->lock);
} else {
spin_lock_bh(&sta->plink_lock);
spin_lock_bh(&sta->lock);
switch (ftype) {
case PLINK_OPEN:
if (!mesh_plink_free_count(sdata) ||
......@@ -551,7 +551,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
break;
default:
mpl_dbg("Mesh plink: unknown frame subtype\n");
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
}
......@@ -568,7 +568,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
switch (event) {
case CLS_ACPT:
mesh_plink_fsm_restart(sta);
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
case OPN_ACPT:
sta->plink_state = PLINK_OPN_RCVD;
......@@ -576,14 +576,14 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
get_random_bytes(&llid, 2);
sta->llid = llid;
mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
0, 0);
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr,
llid, plid, 0);
break;
default:
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
}
break;
......@@ -603,7 +603,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->ignore_plink_timer = true;
llid = sta->llid;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
......@@ -612,7 +612,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->plink_state = PLINK_OPN_RCVD;
sta->plid = plid;
llid = sta->llid;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
plid, 0);
break;
......@@ -622,10 +622,10 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
dot11MeshConfirmTimeout(sdata)))
sta->ignore_plink_timer = true;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
default:
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
}
break;
......@@ -645,13 +645,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->ignore_plink_timer = true;
llid = sta->llid;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
case OPN_ACPT:
llid = sta->llid;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
plid, 0);
break;
......@@ -659,12 +659,12 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
del_timer(&sta->plink_timer);
sta->plink_state = PLINK_ESTAB;
mesh_plink_inc_estab_count(sdata);
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mpl_dbg("Mesh plink with %s ESTABLISHED\n",
print_mac(mac, sta->addr));
break;
default:
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
}
break;
......@@ -684,7 +684,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->ignore_plink_timer = true;
llid = sta->llid;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
......@@ -692,14 +692,14 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
del_timer(&sta->plink_timer);
sta->plink_state = PLINK_ESTAB;
mesh_plink_inc_estab_count(sdata);
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mpl_dbg("Mesh plink with %s ESTABLISHED\n",
print_mac(mac, sta->addr));
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
plid, 0);
break;
default:
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
}
break;
......@@ -713,18 +713,18 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->plink_state = PLINK_HOLDING;
llid = sta->llid;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
case OPN_ACPT:
llid = sta->llid;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
plid, 0);
break;
default:
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
}
break;
......@@ -734,7 +734,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
if (del_timer(&sta->plink_timer))
sta->ignore_plink_timer = 1;
mesh_plink_fsm_restart(sta);
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
case OPN_ACPT:
case CNF_ACPT:
......@@ -742,19 +742,19 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
case CNF_RJCT:
llid = sta->llid;
reason = sta->reason;
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
default:
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
}
break;
default:
/* should not get here, PLINK_BLOCKED is dealt with at the
* beggining of the function
*/
spin_unlock_bh(&sta->plink_lock);
spin_unlock_bh(&sta->lock);
break;
}
......
......@@ -1241,7 +1241,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
/* examine state machine */
spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
spin_lock_bh(&sta->lock);
if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
#ifdef CONFIG_MAC80211_HT_DEBUG
......@@ -1308,7 +1308,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
tid_agg_rx->stored_mpdu_num = 0;
status = WLAN_STATUS_SUCCESS;
end:
spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
spin_unlock_bh(&sta->lock);
end_no_lock:
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,
state = &sta->ampdu_mlme.tid_state_tx[tid];
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_lock_bh(&sta->lock);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
"%d\n", *state);
goto addba_resp_exit;
......@@ -1351,7 +1351,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
if (mgmt->u.action.u.addba_resp.dialog_token !=
sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
......@@ -1375,7 +1375,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
}
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid);
} else {
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,
sta->ampdu_mlme.addba_req_num[tid]++;
/* this will allow the state check in stop_BA_session */
*state = HT_AGG_STATE_OPERATIONAL;
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
ieee80211_stop_tx_ba_session(hw, sta->addr, tid,
WLAN_BACK_INITIATOR);
}
......@@ -1453,17 +1453,17 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
}
/* check if TID is in operational state */
spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
spin_lock_bh(&sta->lock);
if (sta->ampdu_mlme.tid_state_rx[tid]
!= HT_AGG_STATE_OPERATIONAL) {
spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
}
sta->ampdu_mlme.tid_state_rx[tid] =
HT_AGG_STATE_REQ_STOP_BA_MSK |
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
spin_unlock_bh(&sta->lock);
/* stop HW Rx aggregation. ampdu_action existence
* 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,
ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid,
WLAN_BACK_INITIATOR, 0);
else { /* WLAN_BACK_RECIPIENT */
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_lock_bh(&sta->lock);
sta->ampdu_mlme.tid_state_tx[tid] =
HT_AGG_STATE_OPERATIONAL;
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
spin_unlock_bh(&sta->lock);
ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid,
WLAN_BACK_RECIPIENT);
}
......@@ -1580,9 +1580,9 @@ void sta_addba_resp_timer_expired(unsigned long data)