Commit c2c98fde authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

mac80211: optimise station flags

The flaglock in struct sta_info has long been
something that I wanted to get rid of, this
finally does the conversion to atomic bitops.

The conversion itself is straight-forward in
most places, a few things needed to change a
bit since we can no longer use multiple bits
at the same time.

On x86-64, this is a fairly significant code
size reduction:
   text	   data	    bss	    dec	    hex
 427861	  23648	   1008	 452517	  6e7a5	before
 425383	  23648	    976	 450007	  6ddd7	after
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent deeaee19
...@@ -223,7 +223,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, ...@@ -223,7 +223,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
status = WLAN_STATUS_REQUEST_DECLINED; status = WLAN_STATUS_REQUEST_DECLINED;
if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Suspend in progress. " printk(KERN_DEBUG "Suspend in progress. "
"Denying ADDBA request\n"); "Denying ADDBA request\n");
......
...@@ -382,7 +382,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, ...@@ -382,7 +382,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
sdata->vif.type != NL80211_IFTYPE_AP) sdata->vif.type != NL80211_IFTYPE_AP)
return -EINVAL; return -EINVAL;
if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "BA sessions blocked. " printk(KERN_DEBUG "BA sessions blocked. "
"Denying BA session request\n"); "Denying BA session request\n");
......
...@@ -668,7 +668,6 @@ static void sta_apply_parameters(struct ieee80211_local *local, ...@@ -668,7 +668,6 @@ static void sta_apply_parameters(struct ieee80211_local *local,
struct sta_info *sta, struct sta_info *sta,
struct station_parameters *params) struct station_parameters *params)
{ {
unsigned long flags;
u32 rates; u32 rates;
int i, j; int i, j;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
...@@ -677,49 +676,53 @@ static void sta_apply_parameters(struct ieee80211_local *local, ...@@ -677,49 +676,53 @@ static void sta_apply_parameters(struct ieee80211_local *local,
sband = local->hw.wiphy->bands[local->oper_channel->band]; sband = local->hw.wiphy->bands[local->oper_channel->band];
spin_lock_irqsave(&sta->flaglock, flags);
mask = params->sta_flags_mask; mask = params->sta_flags_mask;
set = params->sta_flags_set; set = params->sta_flags_set;
if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
sta->flags &= ~WLAN_STA_AUTHORIZED;
if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
sta->flags |= WLAN_STA_AUTHORIZED; set_sta_flag(sta, WLAN_STA_AUTHORIZED);
else
clear_sta_flag(sta, WLAN_STA_AUTHORIZED);
} }
if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
sta->flags |= WLAN_STA_SHORT_PREAMBLE; set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
else
clear_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
} }
if (mask & BIT(NL80211_STA_FLAG_WME)) { if (mask & BIT(NL80211_STA_FLAG_WME)) {
sta->flags &= ~WLAN_STA_WME;
sta->sta.wme = false;
if (set & BIT(NL80211_STA_FLAG_WME)) { if (set & BIT(NL80211_STA_FLAG_WME)) {
sta->flags |= WLAN_STA_WME; set_sta_flag(sta, WLAN_STA_WME);
sta->sta.wme = true; sta->sta.wme = true;
} else {
clear_sta_flag(sta, WLAN_STA_WME);
sta->sta.wme = false;
} }
} }
if (mask & BIT(NL80211_STA_FLAG_MFP)) { if (mask & BIT(NL80211_STA_FLAG_MFP)) {
sta->flags &= ~WLAN_STA_MFP;
if (set & BIT(NL80211_STA_FLAG_MFP)) if (set & BIT(NL80211_STA_FLAG_MFP))
sta->flags |= WLAN_STA_MFP; set_sta_flag(sta, WLAN_STA_MFP);
else
clear_sta_flag(sta, WLAN_STA_MFP);
} }
if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
sta->flags &= ~WLAN_STA_AUTH;
if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
sta->flags |= WLAN_STA_AUTH; set_sta_flag(sta, WLAN_STA_AUTH);
else
clear_sta_flag(sta, WLAN_STA_AUTH);
} }
if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) { if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
sta->flags &= ~WLAN_STA_TDLS_PEER;
if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
sta->flags |= WLAN_STA_TDLS_PEER; set_sta_flag(sta, WLAN_STA_TDLS_PEER);
else
clear_sta_flag(sta, WLAN_STA_TDLS_PEER);
} }
spin_unlock_irqrestore(&sta->flaglock, flags);
if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) { if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
sta->sta.uapsd_queues = params->uapsd_queues; sta->sta.uapsd_queues = params->uapsd_queues;
...@@ -815,12 +818,13 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, ...@@ -815,12 +818,13 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
if (!sta) if (!sta)
return -ENOMEM; return -ENOMEM;
sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; set_sta_flag(sta, WLAN_STA_AUTH);
set_sta_flag(sta, WLAN_STA_ASSOC);
sta_apply_parameters(local, sta, params); sta_apply_parameters(local, sta, params);
/* Only TDLS-supporting stations can add TDLS peers */ /* Only TDLS-supporting stations can add TDLS peers */
if ((sta->flags & WLAN_STA_TDLS_PEER) && if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
!((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) && !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
sdata->vif.type == NL80211_IFTYPE_STATION)) sdata->vif.type == NL80211_IFTYPE_STATION))
return -ENOTSUPP; return -ENOTSUPP;
...@@ -880,7 +884,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, ...@@ -880,7 +884,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
/* The TDLS bit cannot be toggled after the STA was added */ /* The TDLS bit cannot be toggled after the STA was added */
if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) && if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
!!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) != !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) !=
!!test_sta_flags(sta, WLAN_STA_TDLS_PEER)) { !!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
rcu_read_unlock(); rcu_read_unlock();
return -EINVAL; return -EINVAL;
} }
...@@ -2449,7 +2453,7 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, ...@@ -2449,7 +2453,7 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
return -ENOLINK; return -ENOLINK;
} }
set_sta_flags(sta, WLAN_STA_TDLS_PEER_AUTH); set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
rcu_read_unlock(); rcu_read_unlock();
break; break;
case NL80211_TDLS_DISABLE_LINK: case NL80211_TDLS_DISABLE_LINK:
......
...@@ -58,17 +58,17 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, ...@@ -58,17 +58,17 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
{ {
char buf[100]; char buf[100];
struct sta_info *sta = file->private_data; 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%s%s", int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
staflags & WLAN_STA_AUTH ? "AUTH\n" : "", test_sta_flag(sta, WLAN_STA_AUTH) ? "AUTH\n" : "",
staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "", test_sta_flag(sta, WLAN_STA_ASSOC) ? "ASSOC\n" : "",
staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "", test_sta_flag(sta, WLAN_STA_PS_STA) ? "PS (sta)\n" : "",
staflags & WLAN_STA_PS_DRIVER ? "PS (driver)\n" : "", test_sta_flag(sta, WLAN_STA_PS_DRIVER) ? "PS (driver)\n" : "",
staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", test_sta_flag(sta, WLAN_STA_AUTHORIZED) ? "AUTHORIZED\n" : "",
staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "", test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE) ? "SHORT PREAMBLE\n" : "",
staflags & WLAN_STA_WME ? "WME\n" : "", test_sta_flag(sta, WLAN_STA_WME) ? "WME\n" : "",
staflags & WLAN_STA_WDS ? "WDS\n" : "", test_sta_flag(sta, WLAN_STA_WDS) ? "WDS\n" : "",
staflags & WLAN_STA_MFP ? "MFP\n" : ""); test_sta_flag(sta, WLAN_STA_MFP) ? "MFP\n" : "");
return simple_read_from_buffer(userbuf, count, ppos, buf, res); return simple_read_from_buffer(userbuf, count, ppos, buf, res);
} }
STA_OPS(flags); STA_OPS(flags);
......
...@@ -130,7 +130,7 @@ void ieee80211_ba_session_work(struct work_struct *work) ...@@ -130,7 +130,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
* down by the code that set the flag, so this * down by the code that set the flag, so this
* need not run. * need not run.
*/ */
if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) if (test_sta_flag(sta, WLAN_STA_BLOCK_BA))
return; return;
mutex_lock(&sta->ampdu_mlme.mtx); mutex_lock(&sta->ampdu_mlme.mtx);
......
...@@ -314,7 +314,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ...@@ -314,7 +314,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
} }
if (sta && elems->wmm_info) if (sta && elems->wmm_info)
set_sta_flags(sta, WLAN_STA_WME); set_sta_flag(sta, WLAN_STA_WME);
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -452,7 +452,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, ...@@ -452,7 +452,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
return NULL; return NULL;
sta->last_rx = jiffies; sta->last_rx = jiffies;
set_sta_flags(sta, WLAN_STA_AUTHORIZED); set_sta_flag(sta, WLAN_STA_AUTHORIZED);
/* make sure mandatory rates are always added */ /* make sure mandatory rates are always added */
sta->sta.supp_rates[band] = supp_rates | sta->sta.supp_rates[band] = supp_rates |
......
...@@ -299,8 +299,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) ...@@ -299,8 +299,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
goto err_del_interface; goto err_del_interface;
} }
/* no locking required since STA is not live yet */ /* no atomic bitop required since STA is not live yet */
sta->flags |= WLAN_STA_AUTHORIZED; set_sta_flag(sta, WLAN_STA_AUTHORIZED);
res = sta_info_insert(sta); res = sta_info_insert(sta);
if (res) { if (res) {
......
...@@ -464,7 +464,7 @@ int ieee80211_key_link(struct ieee80211_key *key, ...@@ -464,7 +464,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
* some hardware cannot handle TKIP with QoS, so * some hardware cannot handle TKIP with QoS, so
* we indicate whether QoS could be in use. * we indicate whether QoS could be in use.
*/ */
if (test_sta_flags(sta, WLAN_STA_WME)) if (test_sta_flag(sta, WLAN_STA_WME))
key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
} else { } else {
if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->vif.type == NL80211_IFTYPE_STATION) {
...@@ -478,7 +478,7 @@ int ieee80211_key_link(struct ieee80211_key *key, ...@@ -478,7 +478,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
/* same here, the AP could be using QoS */ /* same here, the AP could be using QoS */
ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
if (ap) { if (ap) {
if (test_sta_flags(ap, WLAN_STA_WME)) if (test_sta_flag(ap, WLAN_STA_WME))
key->conf.flags |= key->conf.flags |=
IEEE80211_KEY_FLAG_WMM_STA; IEEE80211_KEY_FLAG_WMM_STA;
} }
......
...@@ -92,7 +92,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, ...@@ -92,7 +92,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
if (!sta) if (!sta)
return NULL; return NULL;
sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH | WLAN_STA_WME; set_sta_flag(sta, WLAN_STA_AUTH);
set_sta_flag(sta, WLAN_STA_AUTHORIZED);
set_sta_flag(sta, WLAN_STA_WME);
sta->sta.supp_rates[local->hw.conf.channel->band] = rates; sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
rate_control_rate_init(sta); rate_control_rate_init(sta);
...@@ -383,7 +385,7 @@ int mesh_plink_open(struct sta_info *sta) ...@@ -383,7 +385,7 @@ int mesh_plink_open(struct sta_info *sta)
__le16 llid; __le16 llid;
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_sub_if_data *sdata = sta->sdata;
if (!test_sta_flags(sta, WLAN_STA_AUTH)) if (!test_sta_flag(sta, WLAN_STA_AUTH))
return -EPERM; return -EPERM;
spin_lock_bh(&sta->lock); spin_lock_bh(&sta->lock);
...@@ -503,7 +505,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ...@@ -503,7 +505,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
return; return;
} }
if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) { if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
rcu_read_unlock(); rcu_read_unlock();
return; return;
......
...@@ -627,7 +627,7 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) ...@@ -627,7 +627,7 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_managed *mgd = &sdata->u.mgd; struct ieee80211_if_managed *mgd = &sdata->u.mgd;
struct sta_info *sta = NULL; struct sta_info *sta = NULL;
u32 sta_flags = 0; bool authorized = false;
if (!mgd->powersave) if (!mgd->powersave)
return false; return false;
...@@ -645,13 +645,10 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) ...@@ -645,13 +645,10 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
rcu_read_lock(); rcu_read_lock();
sta = sta_info_get(sdata, mgd->bssid); sta = sta_info_get(sdata, mgd->bssid);
if (sta) if (sta)
sta_flags = get_sta_flags(sta); authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
rcu_read_unlock(); rcu_read_unlock();
if (!(sta_flags & WLAN_STA_AUTHORIZED)) return authorized;
return false;
return true;
} }
/* need to hold RTNL or interface lock */ /* need to hold RTNL or interface lock */
...@@ -1095,7 +1092,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ...@@ -1095,7 +1092,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
mutex_lock(&local->sta_mtx); mutex_lock(&local->sta_mtx);
sta = sta_info_get(sdata, bssid); sta = sta_info_get(sdata, bssid);
if (sta) { if (sta) {
set_sta_flags(sta, WLAN_STA_BLOCK_BA); set_sta_flag(sta, WLAN_STA_BLOCK_BA);
ieee80211_sta_tear_down_BA_sessions(sta, tx); ieee80211_sta_tear_down_BA_sessions(sta, tx);
} }
mutex_unlock(&local->sta_mtx); mutex_unlock(&local->sta_mtx);
...@@ -1513,10 +1510,11 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, ...@@ -1513,10 +1510,11 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
return false; return false;
} }
set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | set_sta_flag(sta, WLAN_STA_AUTH);
WLAN_STA_ASSOC_AP); set_sta_flag(sta, WLAN_STA_ASSOC);
set_sta_flag(sta, WLAN_STA_ASSOC_AP);
if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
set_sta_flags(sta, WLAN_STA_AUTHORIZED); set_sta_flag(sta, WLAN_STA_AUTHORIZED);
rates = 0; rates = 0;
basic_rates = 0; basic_rates = 0;
...@@ -1575,10 +1573,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, ...@@ -1575,10 +1573,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
rate_control_rate_init(sta); rate_control_rate_init(sta);
if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
set_sta_flags(sta, WLAN_STA_MFP); set_sta_flag(sta, WLAN_STA_MFP);
if (elems.wmm_param) if (elems.wmm_param)
set_sta_flags(sta, WLAN_STA_WME); set_sta_flag(sta, WLAN_STA_WME);
/* sta_info_reinsert will also unlock the mutex lock */ /* sta_info_reinsert will also unlock the mutex lock */
err = sta_info_reinsert(sta); err = sta_info_reinsert(sta);
......
...@@ -42,7 +42,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) ...@@ -42,7 +42,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
mutex_lock(&local->sta_mtx); mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) { list_for_each_entry(sta, &local->sta_list, list) {
set_sta_flags(sta, WLAN_STA_BLOCK_BA); set_sta_flag(sta, WLAN_STA_BLOCK_BA);
ieee80211_sta_tear_down_BA_sessions(sta, true); ieee80211_sta_tear_down_BA_sessions(sta, true);
} }
mutex_unlock(&local->sta_mtx); mutex_unlock(&local->sta_mtx);
......
...@@ -841,7 +841,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) ...@@ -841,7 +841,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
ieee80211_is_pspoll(hdr->frame_control)) && ieee80211_is_pspoll(hdr->frame_control)) &&
rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
rx->sdata->vif.type != NL80211_IFTYPE_WDS && rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
(!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
if (rx->sta && rx->sta->dummy && if (rx->sta && rx->sta->dummy &&
ieee80211_is_data_present(hdr->frame_control)) { ieee80211_is_data_present(hdr->frame_control)) {
u16 ethertype; u16 ethertype;
...@@ -1110,7 +1110,7 @@ static void ap_sta_ps_start(struct sta_info *sta) ...@@ -1110,7 +1110,7 @@ static void ap_sta_ps_start(struct sta_info *sta)
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
atomic_inc(&sdata->bss->num_sta_ps); atomic_inc(&sdata->bss->num_sta_ps);
set_sta_flags(sta, WLAN_STA_PS_STA); set_sta_flag(sta, WLAN_STA_PS_STA);
if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
...@@ -1130,7 +1130,7 @@ static void ap_sta_ps_end(struct sta_info *sta) ...@@ -1130,7 +1130,7 @@ static void ap_sta_ps_end(struct sta_info *sta)
sdata->name, sta->sta.addr, sta->sta.aid); sdata->name, sta->sta.addr, sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) { if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n",
sdata->name, sta->sta.addr, sta->sta.aid); sdata->name, sta->sta.addr, sta->sta.aid);
...@@ -1149,7 +1149,7 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start) ...@@ -1149,7 +1149,7 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS)); WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS));
/* Don't let the same PS state be set twice */ /* Don't let the same PS state be set twice */
in_ps = test_sta_flags(sta_inf, WLAN_STA_PS_STA); in_ps = test_sta_flag(sta_inf, WLAN_STA_PS_STA);
if ((start && in_ps) || (!start && !in_ps)) if ((start && in_ps) || (!start && !in_ps))
return -EINVAL; return -EINVAL;
...@@ -1190,15 +1190,15 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) ...@@ -1190,15 +1190,15 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
* the uAPSD case, the station will probably be marked asleep, * the uAPSD case, the station will probably be marked asleep,
* in the PS-Poll case the station must be confused ... * in the PS-Poll case the station must be confused ...
*/ */
if (!test_sta_flags(rx->sta, WLAN_STA_PS_STA)) if (!test_sta_flag(rx->sta, WLAN_STA_PS_STA))
return RX_CONTINUE; return RX_CONTINUE;
if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) { if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) {
if (!test_sta_flags(rx->sta, WLAN_STA_SP)) { if (!test_sta_flag(rx->sta, WLAN_STA_SP)) {
if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER)) if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
ieee80211_sta_ps_deliver_poll_response(rx->sta); ieee80211_sta_ps_deliver_poll_response(rx->sta);
else else
set_sta_flags(rx->sta, WLAN_STA_PSPOLL); set_sta_flag(rx->sta, WLAN_STA_PSPOLL);
} }
/* Free PS Poll skb here instead of returning RX_DROP that would /* Free PS Poll skb here instead of returning RX_DROP that would
...@@ -1225,13 +1225,13 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) ...@@ -1225,13 +1225,13 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
return RX_CONTINUE; return RX_CONTINUE;
/* if we are in a service period, do nothing */ /* if we are in a service period, do nothing */
if (test_sta_flags(rx->sta, WLAN_STA_SP)) if (test_sta_flag(rx->sta, WLAN_STA_SP))
return RX_CONTINUE; return RX_CONTINUE;
if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER)) if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
ieee80211_sta_ps_deliver_uapsd(rx->sta); ieee80211_sta_ps_deliver_uapsd(rx->sta);
else else
set_sta_flags(rx->sta, WLAN_STA_UAPSD); set_sta_flag(rx->sta, WLAN_STA_UAPSD);
} }
return RX_CONTINUE; return RX_CONTINUE;
...@@ -1295,7 +1295,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ...@@ -1295,7 +1295,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
!(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
(rx->sdata->vif.type == NL80211_IFTYPE_AP || (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
if (test_sta_flags(sta, WLAN_STA_PS_STA)) { if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
/* /*
* Ignore doze->wake transitions that are * Ignore doze->wake transitions that are
* indicated by non-data frames, the standard * indicated by non-data frames, the standard
...@@ -1570,7 +1570,7 @@ static int ...@@ -1570,7 +1570,7 @@ static int
ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
{ {
if (unlikely(!rx->sta || if (unlikely(!rx->sta ||
!test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED)))
return -EACCES; return -EACCES;
return 0; return 0;
...@@ -1613,7 +1613,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) ...@@ -1613,7 +1613,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
if (status->flag & RX_FLAG_DECRYPTED) if (status->flag & RX_FLAG_DECRYPTED)
return 0; return 0;
if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { if (rx->sta && test_sta_flag(rx->sta, WLAN_STA_MFP)) {
if (unlikely(!ieee80211_has_protected(fc) && if (unlikely(!ieee80211_has_protected(fc) &&
ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
rx->key)) { rx->key)) {
......
...@@ -244,22 +244,22 @@ static void sta_unblock(struct work_struct *wk) ...@@ -244,22 +244,22 @@ static void sta_unblock(struct work_struct *wk)
if (sta->dead) if (sta->dead)
return; return;
if (!test_sta_flags(sta, WLAN_STA_PS_STA)) if (!test_sta_flag(sta, WLAN_STA_PS_STA))
ieee80211_sta_ps_deliver_wakeup(sta); ieee80211_sta_ps_deliver_wakeup(sta);
else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) { else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
clear_sta_flags(sta, WLAN_STA_PS_DRIVER); clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
local_bh_disable(); local_bh_disable();
ieee80211_sta_ps_deliver_poll_response(sta); ieee80211_sta_ps_deliver_poll_response(sta);
local_bh_enable(); local_bh_enable();
} else if (test_and_clear_sta_flags(sta, WLAN_STA_UAPSD)) { } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) {
clear_sta_flags(sta, WLAN_STA_PS_DRIVER); clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
local_bh_disable(); local_bh_disable();
ieee80211_sta_ps_deliver_uapsd(sta); ieee80211_sta_ps_deliver_uapsd(sta);
local_bh_enable(); local_bh_enable();
} else } else
clear_sta_flags(sta, WLAN_STA_PS_DRIVER); clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
} }
static int sta_prepare_rate_control(struct ieee80211_local *local, static int sta_prepare_rate_control(struct ieee80211_local *local,
...@@ -292,7 +292,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, ...@@ -292,7 +292,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
return NULL; return NULL;
spin_lock_init(&sta->lock); spin_lock_init(&sta->lock);
spin_lock_init(&sta->flaglock);
INIT_WORK(&sta->drv_unblock_wk, sta_unblock); INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
mutex_init(&sta->ampdu_mlme.mtx); mutex_init(&sta->ampdu_mlme.mtx);
...@@ -871,7 +870,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) ...@@ -871,7 +870,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
* sessions -- block that to make sure the tear-down * sessions -- block that to make sure the tear-down
* will be sufficient. * will be sufficient.
*/ */
set_sta_flags(sta, WLAN_STA_BLOCK_BA); set_sta_flag(sta, WLAN_STA_BLOCK_BA);
ieee80211_sta_tear_down_BA_sessions(sta, true); ieee80211_sta_tear_down_BA_sessions(sta, true);
spin_lock_irqsave(&local->sta_lock, flags); spin_lock_irqsave(&local->sta_lock, flags);
...@@ -892,10 +891,13 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) ...@@ -892,10 +891,13 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
sta->dead = true; sta->dead = true;
if (test_and_clear_sta_flags(sta, if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
BUG_ON(!sdata->bss); BUG_ON(!sdata->bss);
clear_sta_flag(sta, WLAN_STA_PS_STA);
clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
atomic_dec(&sdata->bss->num_sta_ps); atomic_dec(&sdata->bss->num_sta_ps);
sta_info_recalc_tim(sta); sta_info_recalc_tim(sta);
} }
...@@ -1116,7 +1118,8 @@ static void clear_sta_ps_flags(void *_sta) ...@@ -1116,7 +1118,8 @@ static void clear_sta_ps_flags(void *_sta)
{ {
struct sta_info *sta = _sta; struct sta_info *sta = _sta;
clear_sta_flags(sta, WLAN_STA_PS_DRIVER | WLAN_STA_PS_STA); clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
clear_sta_flag(sta, WLAN_STA_PS_STA);
} }
/* powersave support code */ /* powersave support code */
...@@ -1127,7 +1130,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) ...@@ -1127,7 +1130,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
struct sk_buff_head pending; struct sk_buff_head pending;
int filtered = 0, buffered = 0, ac; int filtered = 0, buffered = 0, ac;
clear_sta_flags(sta, WLAN_STA_SP); clear_sta_flag(sta, WLAN_STA_SP);
BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1); BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1);
sta->driver_buffered_tids = 0; sta->driver_buffered_tids = 0;
...@@ -1173,7 +1176,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, ...@@ -1173,7 +1176,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb; struct sk_buff *skb;
int size = sizeof(*nullfunc); int size = sizeof(*nullfunc);
__le16 fc; __le16 fc;
bool qos = test_sta_flags(sta, WLAN_STA_WME); bool qos = test_sta_flag(sta, WLAN_STA_WME);
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
if (qos) { if (qos) {
...@@ -1241,7 +1244,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, ...@@ -1241,7 +1244,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
struct sk_buff_head frames; struct sk_buff_head frames;
/* Service or PS-Poll period starts */ /* Service or PS-Poll period starts */
set_sta_flags(sta, WLAN_STA_SP); set_sta_flag(sta, WLAN_STA_SP);
__skb_queue_head_init(&frames); __skb_queue_head_init(&frames);
...@@ -1453,8 +1456,8 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, ...@@ -1453,8 +1456,8 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
trace_api_sta_block_awake(sta->local, pubsta, block); trace_api_sta_block_awake(sta->local, pubsta, block);
if (block) if (block)
set_sta_flags(sta, WLAN_STA_PS_DRIVER); set_sta_flag(sta, WLAN_STA_PS_DRIVER);
else if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER))
ieee80211_queue_work(hw, &sta->drv_unblock_wk); ieee80211_queue_work(hw, &sta->drv_unblock_wk);
} }
EXPORT_SYMBOL(ieee80211_sta_block_awake); EXPORT_SYMBOL(ieee80211_sta_block_awake);
......
...@@ -19,7 +19,8 @@ ...@@ -19,7 +19,8 @@
/** /**
* enum ieee80211_sta_info_flags - Stations flags * enum ieee80211_sta_info_flags - Stations flags
* *
* These flags are used with &struct sta_info's @flags member. * These flags are used with &struct sta_info's @flags member, but
* only indirectly with set_sta_flag() and friends.
* *
* @WLAN_STA_AUTH: Station is authenticated. * @WLAN_STA_AUTH: Station is authenticated.
* @WLAN_STA_ASSOC: Station is associated. * @WLAN_STA_ASSOC: Station is associated.
...@@ -53,23 +54,23 @@ ...@@ -53,23 +54,23 @@
* reply to other uAPSD trigger frames or PS-Poll. * reply to other uAPSD trigger frames or PS-Poll.
*/ */
enum ieee80211_sta_info_flags { enum ieee80211_sta_info_flags {
WLAN_STA_AUTH = 1<<0, WLAN_STA_AUTH,
WLAN_STA_ASSOC = 1<<1, WLAN_STA_ASSOC,
WLAN_STA_PS_STA = 1<<2, WLAN_STA_PS_STA,
WLAN_STA_AUTHORIZED = 1<<3, WLAN_STA_AUTHORIZED,
WLAN_STA_SHORT_PREAMBLE = 1<<4, WLAN_STA_SHORT_PREAMBLE,
WLAN_STA_ASSOC_AP = 1<<5, WLAN_STA_ASSOC_AP,
WLAN_STA_WME = 1<<6, WLAN_STA_WME,
WLAN_STA_WDS = 1<<7, WLAN_STA_WDS,
WLAN_STA_CLEAR_PS_FILT = 1<<9, WLAN_STA_CLEAR_PS_FILT,
WLAN_STA_MFP = 1<<10, WLAN_STA_MFP,
WLAN_STA_BLOCK_BA = 1<<11, WLAN_STA_BLOCK_BA,
WLAN_STA_PS_DRIVER = 1<<12, WLAN_STA_PS_DRIVER,
WLAN_STA_PSPOLL = 1<<13, WLAN_STA_PSPOLL,
WLAN_STA_TDLS_PEER = 1<<15, WLAN_STA_TDLS_PEER,
WLAN_STA_TDLS_PEER_AUTH = 1<<16, WLAN_STA_TDLS_PEER_AUTH,
WLAN_STA_UAPSD = 1<<17, WLAN_STA_UAPSD,
WLAN_STA_SP = 1<<18, WLAN_STA_SP,
}; };
#define STA_TID_NUM 16 #define STA_TID_NUM 16
...@@ -212,10 +213,9 @@ struct sta_ampdu_mlme { ...@@ -212,10 +213,9 @@ struct sta_ampdu_mlme {
* @last_rx_rate_flag: rx status flag of the last data packet * @last_rx_rate_flag: rx status flag of the last data packet
* @lock: used for locking all fields that require locking, see comments * @lock: used for locking all fields that require locking, see comments
* in the header file. * in the header file.
* @flaglock: spinlock for flags accesses
* @drv_unblock_wk: used for driver PS unblocking * @drv_unblock_wk: used for driver PS unblocking
* @listen_interval: listen interval of this station, when we're acting as AP * @listen_interval: listen interval of this station, when we're acting as AP
* @flags: STA flags, see &enum ieee80211_sta_info_flags * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
* @ps_tx_buf: buffers (per AC) of frames to transmit to this station * @ps_tx_buf: buffers (per AC) of frames to transmit to this station
* when it leaves power saving state or polls * when it leaves power saving state or polls
* @tx_filtered: buffers (per AC) of frames we already tried to * @tx_filtered: buffers (per AC) of frames we already tried to
...@@ -272,7 +272,6 @@ struct sta_info { ...@@ -272,7 +272,6 @@ struct sta_info {
struct rate_control_ref *rate_ctrl; struct rate_control_ref *rate_ctrl;
void *rate_ctrl_priv; void *rate_ctrl_priv;
spinlock_t lock; spinlock_t lock;
spinlock_t flaglock;
struct work_struct drv_unblock_wk; struct work_struct drv_unblock_wk;
...@@ -282,11 +281,8 @@ struct sta_info { ...@@ -282,11 +281,8 @@ struct sta_info {
bool uploaded; bool uploaded;
/* /* use the accessors defined below */
* frequently updated, locked with own spinlock (flaglock), unsigned long _flags;
* use the accessors defined below
*/
u32 flags;
/* /*
* STA powersave frame queues, no more than the internal * STA powersave frame queues, no more than the internal
...@@ -370,60 +366,28 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta) ...@@ -370,60 +366,28 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta)
return NL80211_PLINK_LISTEN; return NL80211_PLINK_LISTEN;
} }
static inline void set_sta_flags(struct sta_info *sta, const u32 flags) static inline void set_sta_flag(struct sta_info *sta,
enum ieee80211_sta_info_flags flag)
{ {
unsigned long irqfl; set_bit(flag, &sta->_flags);
spin_lock_irqsave(&sta->flaglock, irqfl);
sta->flags |= flags;
spin_unlock_irqrestore(&sta->flaglock, irqfl);
} }
static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) static inline void clear_sta_flag(struct sta_info *sta,
enum ieee80211_sta_info_flags flag)
{ {
unsigned long irqfl; clear_bit(flag, &sta->_flags);
spin_lock_irqsave(&sta->flaglock, irqfl);
sta->flags &= ~flags;
spin_unlock_irqrestore(&sta->flaglock, irqfl);
} }
static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) static inline int test_sta_flag(struct sta_info *sta,
enum ieee80211_sta_info_flags flag)
{ {
u32 ret; return test_bit(flag, &sta->_flags);
unsigned long irqfl;
spin_lock_irqsave(&sta->flaglock, irqfl);
ret = sta->flags & flags;
spin_unlock_irqrestore(&sta->flaglock, irqfl);
return ret;
} }
static inline u32 test_and_clear_sta_flags(struct sta_info *sta, static inline int test_and_clear_sta_flag(struct sta_info *sta,
const u32 flags) enum ieee80211_sta_info_flags flag)
{ {
u32 ret; return test_and_clear_bit(flag, &sta->_flags);
unsigned long irqfl;
spin_lock_irqsave(&sta->flaglock, irqfl);
ret = sta->flags & flags;
sta->flags &= ~flags;
spin_unlock_irqrestore(&sta->flaglock, irqfl);
return ret;
}
static inline u32 get_sta_flags(struct sta_info *sta)
{
u32 ret;
unsigned long irqfl;
spin_lock_irqsave(&sta->flaglock, irqfl);
ret = sta->flags;
spin_unlock_irqrestore(&sta->flaglock, irqfl);
return ret;
} }
void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
......
...@@ -96,7 +96,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, ...@@ -96,7 +96,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
* packet. If the STA went to power save mode, this will happen * packet. If the STA went to power save mode, this will happen
* when it wakes up for the next time. * when it wakes up for the next time.
*/ */
set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT);
/* /*
* This code races in the following way: * This code races in the following way:
...@@ -132,7 +132,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, ...@@ -132,7 +132,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
* changes before calling TX status events if ordering can be * changes before calling TX status events if ordering can be
* unknown. * unknown.
*/ */
if (test_sta_flags(sta, WLAN_STA_PS_STA) && if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
skb_queue_len(&sta->tx_filtered[ac]) < STA_MAX_TX_BUFFER) { skb_queue_len(&sta->tx_filtered[ac]) < STA_MAX_TX_BUFFER) {
skb_queue_tail(&sta->tx_filtered[ac], skb); skb_queue_tail(&sta->tx_filtered[ac], skb);
sta_info_recalc_tim(sta); sta_info_recalc_tim(sta);
...@@ -144,7 +144,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, ...@@ -144,7 +144,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
return; return;
} }
if (!test_sta_flags(sta, WLAN_STA_PS_STA) && if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
!(info->flags & IEEE80211_TX_INTFL_RETRIED)) { !(info->flags & IEEE80211_TX_INTFL_RETRIED)) {
/* Software retry the packet once */ /* Software retry the packet once */
info->flags |= IEEE80211_TX_INTFL_RETRIED; info->flags |= IEEE80211_TX_INTFL_RETRIED;
...@@ -157,7 +157,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, ...@@ -157,7 +157,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
wiphy_debug(local->hw.wiphy, wiphy_debug(local->hw.wiphy,
"dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
skb_queue_len(&sta->tx_filtered[ac]), skb_queue_len(&sta->tx_filtered[ac]),
!!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
#endif #endif
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
...@@ -285,10 +285,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) ...@@ -285,10 +285,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
continue; continue;
if (info->flags & IEEE80211_TX_STATUS_EOSP) if (info->flags & IEEE80211_TX_STATUS_EOSP)
clear_sta_flags(sta, WLAN_STA_SP); clear_sta_flag(sta, WLAN_STA_SP);
acked = !!(info->flags & IEEE80211_TX_STAT_ACK); acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) { if (!acked && test_sta_flag(sta, WLAN_STA_PS_STA)) {
/* /*
* The STA is in power save mode, so assume * The STA is in power save mode, so assume
* that this TX packet failed because of that. * that this TX packet failed because of that.
......
...@@ -253,7 +253,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) ...@@ -253,7 +253,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
u32 sta_flags; bool assoc = false;
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
return TX_CONTINUE; return TX_CONTINUE;
...@@ -284,10 +284,11 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) ...@@ -284,10 +284,11 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
if (tx->flags & IEEE80211_TX_PS_BUFFERED) if (tx->flags & IEEE80211_TX_PS_BUFFERED)
return TX_CONTINUE; return TX_CONTINUE;
sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; if (tx->sta)
assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
if (likely(tx->flags & IEEE80211_TX_UNICAST)) { if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && if (unlikely(!assoc &&
tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && tx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
ieee80211_is_data(hdr->frame_control))) { ieee80211_is_data(hdr->frame_control))) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
...@@ -427,7 +428,7 @@ static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, ...@@ -427,7 +428,7 @@ static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
if (!ieee80211_is_mgmt(fc)) if (!ieee80211_is_mgmt(fc))
return 0; return 0;
if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP)) if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
return 0; return 0;
if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *)
...@@ -444,7 +445,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) ...@@ -444,7 +445,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
struct ieee80211_local *local = tx->local; struct ieee80211_local *local = tx->local;
u32 staflags;
if (unlikely(!sta || if (unlikely(!sta ||
ieee80211_is_probe_resp(hdr->frame_control) || ieee80211_is_probe_resp(hdr->frame_control) ||
...@@ -453,9 +453,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) ...@@ -453,9 +453,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
ieee80211_is_reassoc_resp(hdr->frame_control))) ieee80211_is_reassoc_resp(hdr->frame_control)))
return TX_CONTINUE; return TX_CONTINUE;
staflags = get_sta_flags(sta); if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) &&
!(info->flags & IEEE80211_TX_CTL_POLL_RESPONSE))) { !(info->flags & IEEE80211_TX_CTL_POLL_RESPONSE))) {
int ac = skb_get_queue_mapping(tx->skb); int ac = skb_get_queue_mapping(tx->skb);
...@@ -496,7 +495,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) ...@@ -496,7 +495,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
return TX_QUEUED; return TX_QUEUED;
} }
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
else if (unlikely(staflags & WLAN_STA_PS_STA)) { else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) {
printk(KERN_DEBUG printk(KERN_DEBUG
"%s: STA %pM in PS mode, but polling/in SP -> send frame\n", "%s: STA %pM in PS mode, but polling/in SP -> send frame\n",
tx->sdata->name, sta->sta.addr); tx->sdata->name, sta->sta.addr);
...@@ -557,7 +556,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) ...@@ -557,7 +556,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
!(info->flags & IEEE80211_TX_CTL_INJECTED) && !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
(!ieee80211_is_robust_mgmt_frame(hdr) || (!ieee80211_is_robust_mgmt_frame(hdr) ||
(ieee80211_is_action(hdr->frame_control) && (ieee80211_is_action(hdr->frame_control) &&
tx->sta && test_sta_flags(tx->sta, WLAN_STA_MFP)))) { tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))) {
I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
return TX_DROP; return TX_DROP;
} else } else
...@@ -616,7 +615,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) ...@@ -616,7 +615,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
u32 len; u32 len;
bool inval = false, rts = false, short_preamble = false; bool inval = false, rts = false, short_preamble = false;
struct ieee80211_tx_rate_control txrc; struct ieee80211_tx_rate_control txrc;
u32 sta_flags; bool assoc = false;
memset(&txrc, 0, sizeof(txrc)); memset(&txrc, 0, sizeof(txrc));
...@@ -652,17 +651,17 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) ...@@ -652,17 +651,17 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
*/ */
if (tx->sdata->vif.bss_conf.use_short_preamble && if (tx->sdata->vif.bss_conf.use_short_preamble &&
(ieee80211_is_data(hdr->frame_control) || (ieee80211_is_data(hdr->frame_control) ||
(tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) (tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
txrc.short_preamble = short_preamble = true; txrc.short_preamble = short_preamble = true;
sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; if (tx->sta)
assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
/* /*
* Lets not bother rate control if we're associated and cannot * Lets not bother rate control if we're associated and cannot
* talk to the sta. This should not happen. * talk to the sta. This should not happen.
*/ */
if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc &&
(sta_flags & WLAN_STA_ASSOC) &&
!rate_usable_index_exists(sband, &tx->sta->sta), !rate_usable_index_exists(sband, &tx->sta->sta),
"%s: Dropped data frame as no usable bitrate found while " "%s: Dropped data frame as no usable bitrate found while "
"scanning and associated. Target station: " "scanning and associated. Target station: "
...@@ -1278,7 +1277,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, ...@@ -1278,7 +1277,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
if (!tx->sta) if (!tx->sta)
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT))
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
...@@ -1728,7 +1727,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, ...@@ -1728,7 +1727,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
int encaps_len, skip_header_bytes; int encaps_len, skip_header_bytes;
int nh_pos, h_pos; int nh_pos, h_pos;
struct sta_info *sta = NULL; struct sta_info *sta = NULL;
u32 sta_flags = 0; bool wme_sta = false, authorized = false, tdls_auth = false;
struct sk_buff *tmp_skb; struct sk_buff *tmp_skb;
bool tdls_direct = false; bool tdls_direct = false;
...@@ -1754,7 +1753,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, ...@@ -1754,7 +1753,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
memcpy(hdr.addr3, skb->data, ETH_ALEN); memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 30; hdrlen = 30;
sta_flags = get_sta_flags(sta); authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
wme_sta = test_sta_flag(sta, WLAN_STA_WME);
} }
rcu_read_unlock(); rcu_read_unlock();
if (sta) if (sta)
...@@ -1843,10 +1843,19 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, ...@@ -1843,10 +1843,19 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
#endif #endif
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
bool tdls_peer = false;
rcu_read_lock(); rcu_read_lock();
sta = sta_info_get(sdata, skb->data); sta = sta_info_get(sdata, skb->data);
if (sta) if (sta) {
sta_flags = get_sta_flags(sta); authorized = test_sta_flag(sta,
WLAN_STA_AUTHORIZED);
wme_sta = test_sta_flag(sta, WLAN_STA_WME);
tdls_peer = test_sta_flag(sta,
WLAN_STA_TDLS_PEER);
tdls_auth = test_sta_flag(sta,
WLAN_STA_TDLS_PEER_AUTH);
}
rcu_read_unlock(); rcu_read_unlock();
/* /*
...@@ -1854,16 +1863,14 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, ...@@ -1854,16 +1863,14 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
* directly. Otherwise, allow TDLS setup frames * directly. Otherwise, allow TDLS setup frames
* to be transmitted indirectly. * to be transmitted indirectly.
*/ */
tdls_direct = tdls_direct = tdls_peer && (tdls_auth ||
(sta_flags & WLAN_STA_TDLS_PEER) &&
((sta_flags & WLAN_STA_TDLS_PEER_AUTH) ||
!(ethertype == ETH_P_TDLS && skb->len > 14 && !(ethertype == ETH_P_TDLS && skb->len > 14 &&
skb->data[14] == WLAN_TDLS_SNAP_RFTYPE)); skb->data[14] == WLAN_TDLS_SNAP_RFTYPE));
} }
if (tdls_direct) { if (tdls_direct) {
/* link during setup - throw out frames to peer */ /* link during setup - throw out frames to peer */
if (!(sta_flags & WLAN_STA_TDLS_PEER_AUTH)) { if (!tdls_auth) {
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
goto fail; goto fail;
} }
...@@ -1912,17 +1919,19 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, ...@@ -1912,17 +1919,19 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
if (!is_multicast_ether_addr(hdr.addr1)) { if (!is_multicast_ether_addr(hdr.addr1)) {
rcu_read_lock(); rcu_read_lock();
sta = sta_info_get(sdata, hdr.addr1); sta = sta_info_get(sdata, hdr.addr1);
if (sta) if (sta) {
sta_flags = get_sta_flags(sta); authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
wme_sta = test_sta_flag(sta, WLAN_STA_WME);
}
rcu_read_unlock(); rcu_read_unlock();
} }
/* For mesh, the use of the QoS header is mandatory */ /* For mesh, the use of the QoS header is mandatory */
if (ieee80211_vif_is_mesh(&sdata->vif)) if (ieee80211_vif_is_mesh(&sdata->vif))
sta_flags |= WLAN_STA_WME; wme_sta = true;
/* receiver and we are QoS enabled, use a QoS type frame */ /* receiver and we are QoS enabled, use a QoS type frame */
if ((sta_flags & WLAN_STA_WME) && local->hw.queues >= 4) { if (wme_sta && local->hw.queues >= 4) {
fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
hdrlen += 2; hdrlen += 2;
} }
...@@ -1932,8 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, ...@@ -1932,8 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
* EAPOL frames from the local station. * EAPOL frames from the local station.
*/ */
if (!ieee80211_vif_is_mesh(&sdata->vif) && if (!ieee80211_vif_is_mesh(&sdata->vif) &&
unlikely(!is_multicast_ether_addr(hdr.addr1) && unlikely(!is_multicast_ether_addr(hdr.addr1) && !authorized &&
!(sta_flags & WLAN_STA_AUTHORIZED) &&
!(cpu_to_be16(ethertype) == sdata->control_port_protocol && !(cpu_to_be16(ethertype) == sdata->control_port_protocol &&
compare_ether_addr(sdata->vif.addr, compare_ether_addr(sdata->vif.addr,
skb->data + ETH_ALEN) == 0))) { skb->data + ETH_ALEN) == 0))) {
......
...@@ -1122,7 +1122,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -1122,7 +1122,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
list_for_each_entry(sta, &local->sta_list, list) { list_for_each_entry(sta, &local->sta_list, list) {
ieee80211_sta_tear_down_BA_sessions(sta, true); ieee80211_sta_tear_down_BA_sessions(sta, true);
clear_sta_flags(sta, WLAN_STA_BLOCK_BA); clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
} }
mutex_unlock(&local->sta_mtx); mutex_unlock(&local->sta_mtx);
......
...@@ -72,7 +72,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, ...@@ -72,7 +72,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_AP_VLAN:
sta = rcu_dereference(sdata->u.vlan.sta); sta = rcu_dereference(sdata->u.vlan.sta);
if (sta) { if (sta) {
qos = get_sta_flags(sta) & WLAN_STA_WME; qos = test_sta_flag(sta, WLAN_STA_WME);
break; break;
} }
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
...@@ -99,7 +99,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, ...@@ -99,7 +99,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
if (!sta && ra && !is_multicast_ether_addr(ra)) { if (!sta && ra && !is_multicast_ether_addr(ra)) {
sta = sta_info_get(sdata, ra); sta = sta_info_get(sdata, ra);
if (sta) if (sta)
qos = get_sta_flags(sta) & WLAN_STA_WME; qos = test_sta_flag(sta, WLAN_STA_WME);
} }
rcu_read_unlock(); rcu_read_unlock();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment