aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/debugfs_sta.c19
-rw-r--r--net/mac80211/ieee80211.c64
-rw-r--r--net/mac80211/ieee80211_i.h50
-rw-r--r--net/mac80211/ieee80211_ioctl.c3
-rw-r--r--net/mac80211/ieee80211_sta.c84
-rw-r--r--net/mac80211/rx.c10
-rw-r--r--net/mac80211/sta_info.c30
-rw-r--r--net/mac80211/sta_info.h49
-rw-r--r--net/wireless/util.c6
9 files changed, 185 insertions, 130 deletions
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index fc2c1a192ed..256ea880d28 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -169,27 +169,30 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
p += scnprintf(p, sizeof(buf)+buf-p, "\n RX :");
for (i = 0; i < STA_TID_NUM; i++)
p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_rx[i].state);
+ sta->ampdu_mlme.tid_state_rx[i]);
p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
for (i = 0; i < STA_TID_NUM; i++)
p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_rx[i].dialog_token);
+ sta->ampdu_mlme.tid_state_rx[i]?
+ sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
p += scnprintf(p, sizeof(buf)+buf-p, "\n TX :");
for (i = 0; i < STA_TID_NUM; i++)
p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_tx[i].state);
+ sta->ampdu_mlme.tid_state_tx[i]);
p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
for (i = 0; i < STA_TID_NUM; i++)
p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_tx[i].dialog_token);
+ sta->ampdu_mlme.tid_state_tx[i]?
+ sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :");
for (i = 0; i < STA_TID_NUM; i++)
p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
- sta->ampdu_mlme.tid_tx[i].ssn);
+ sta->ampdu_mlme.tid_state_tx[i]?
+ sta->ampdu_mlme.tid_tx[i]->ssn : 0);
p += scnprintf(p, sizeof(buf)+buf-p, "\n");
@@ -230,11 +233,13 @@ static ssize_t sta_agg_status_write(struct file *file,
strcpy(state, "off ");
ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0,
WLAN_REASON_QSTA_REQUIRE_SETUP);
- sta->ampdu_mlme.tid_rx[tid_num].buf_size = 0xFF;
+ sta->ampdu_mlme.tid_state_rx[tid_num] |=
+ HT_AGG_STATE_DEBUGFS_CTL;
tid_static_rx[tid_num] = 0;
} else {
strcpy(state, "on ");
- sta->ampdu_mlme.tid_rx[tid_num].buf_size = 0x00;
+ sta->ampdu_mlme.tid_state_rx[tid_num] &=
+ ~HT_AGG_STATE_DEBUGFS_CTL;
tid_static_rx[tid_num] = 1;
}
printk(KERN_DEBUG "debugfs - try switching tid %u %s\n",
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 616ce10d2a3..8c0f782d21e 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -569,12 +569,12 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
/* we have tried too many times, receiver does not want A-MPDU */
- if (sta->ampdu_mlme.tid_tx[tid].addba_req_num > HT_AGG_MAX_RETRIES) {
+ if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
ret = -EBUSY;
goto start_ba_exit;
}
- state = &sta->ampdu_mlme.tid_tx[tid].state;
+ state = &sta->ampdu_mlme.tid_state_tx[tid];
/* check if the TID is not in aggregation flow already */
if (*state != HT_AGG_STATE_IDLE) {
#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -585,6 +585,23 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
goto start_ba_exit;
}
+ /* prepare A-MPDU MLME for Tx aggregation */
+ sta->ampdu_mlme.tid_tx[tid] =
+ kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
+ if (!sta->ampdu_mlme.tid_tx[tid]) {
+ if (net_ratelimit())
+ printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
+ tid);
+ ret = -ENOMEM;
+ goto start_ba_exit;
+ }
+ /* Tx timer */
+ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
+ sta_addba_resp_timer_expired;
+ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
+ (unsigned long)&sta->timer_to_tid[tid];
+ init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+
/* ensure that TX flow won't interrupt us
* until the end of the call to requeue function */
spin_lock_bh(&local->mdev->queue_lock);
@@ -596,11 +613,10 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
* don't switch to aggregation */
if (ret) {
#ifdef CONFIG_MAC80211_HT_DEBUG
- printk(KERN_DEBUG "BA request denied - no queue available for"
+ printk(KERN_DEBUG "BA request denied - queue unavailable for"
" tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
- spin_unlock_bh(&local->mdev->queue_lock);
- goto start_ba_exit;
+ goto start_ba_err;
}
sdata = sta->sdata;
@@ -618,38 +634,40 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
* allocated queue */
ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
#ifdef CONFIG_MAC80211_HT_DEBUG
- printk(KERN_DEBUG "BA request denied - HW or queue unavailable"
- " for tid %d\n", tid);
+ printk(KERN_DEBUG "BA request denied - HW unavailable for"
+ " tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
- spin_unlock_bh(&local->mdev->queue_lock);
*state = HT_AGG_STATE_IDLE;
- goto start_ba_exit;
+ goto start_ba_err;
}
/* Will put all the packets in the new SW queue */
ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
spin_unlock_bh(&local->mdev->queue_lock);
- /* We have most probably almost emptied the legacy queue */
- /* ieee80211_wake_queue(local_to_hw(local), ieee802_1d_to_ac[tid]); */
-
/* send an addBA request */
sta->ampdu_mlme.dialog_token_allocator++;
- sta->ampdu_mlme.tid_tx[tid].dialog_token =
+ sta->ampdu_mlme.tid_tx[tid]->dialog_token =
sta->ampdu_mlme.dialog_token_allocator;
- sta->ampdu_mlme.tid_tx[tid].ssn = start_seq_num;
+ sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
ieee80211_send_addba_request(sta->sdata->dev, ra, tid,
- sta->ampdu_mlme.tid_tx[tid].dialog_token,
- sta->ampdu_mlme.tid_tx[tid].ssn,
+ sta->ampdu_mlme.tid_tx[tid]->dialog_token,
+ sta->ampdu_mlme.tid_tx[tid]->ssn,
0x40, 5000);
/* activate the timer for the recipient's addBA response */
- sta->ampdu_mlme.tid_tx[tid].addba_resp_timer.expires =
+ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
jiffies + ADDBA_RESP_INTERVAL;
- add_timer(&sta->ampdu_mlme.tid_tx[tid].addba_resp_timer);
+ add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
+ goto start_ba_exit;
+start_ba_err:
+ kfree(sta->ampdu_mlme.tid_tx[tid]);
+ sta->ampdu_mlme.tid_tx[tid] = NULL;
+ spin_unlock_bh(&local->mdev->queue_lock);
+ ret = -EBUSY;
start_ba_exit:
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
rcu_read_unlock();
@@ -683,7 +701,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
}
/* check if the TID is in aggregation */
- state = &sta->ampdu_mlme.tid_tx[tid].state;
+ state = &sta->ampdu_mlme.tid_state_tx[tid];
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
if (*state != HT_AGG_STATE_OPERATIONAL) {
@@ -741,7 +759,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
return;
}
- state = &sta->ampdu_mlme.tid_tx[tid].state;
+ state = &sta->ampdu_mlme.tid_state_tx[tid];
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
@@ -790,7 +808,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
rcu_read_unlock();
return;
}
- state = &sta->ampdu_mlme.tid_tx[tid].state;
+ state = &sta->ampdu_mlme.tid_state_tx[tid];
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
@@ -819,7 +837,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
* necessarily stopped */
netif_schedule(local->mdev);
*state = HT_AGG_STATE_IDLE;
- sta->ampdu_mlme.tid_tx[tid].addba_req_num = 0;
+ 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);
rcu_read_unlock();
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a6485f01b3c..7ab80660218 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -73,11 +73,12 @@ struct ieee80211_fragment_entry {
struct ieee80211_sta_bss {
struct list_head list;
struct ieee80211_sta_bss *hnext;
+ size_t ssid_len;
+
atomic_t users;
u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
- size_t ssid_len;
u16 capability; /* host byte order */
enum ieee80211_band band;
int freq;
@@ -98,8 +99,8 @@ struct ieee80211_sta_bss {
#define IEEE80211_MAX_SUPP_RATES 32
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
size_t supp_rates_len;
- int beacon_int;
u64 timestamp;
+ int beacon_int;
int probe_resp;
unsigned long last_update;
@@ -154,9 +155,7 @@ struct ieee80211_tx_data {
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
- u16 fc, ethertype;
struct ieee80211_key *key;
- unsigned int flags;
struct ieee80211_tx_control *control;
struct ieee80211_channel *channel;
@@ -168,8 +167,11 @@ struct ieee80211_tx_data {
/* Extra fragments (in addition to the first fragment
* in skb) */
- int num_extra_frag;
struct sk_buff **extra_frag;
+ int num_extra_frag;
+
+ u16 fc, ethertype;
+ unsigned int flags;
};
@@ -192,12 +194,12 @@ struct ieee80211_rx_data {
struct ieee80211_local *local;
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
- u16 fc, ethertype;
struct ieee80211_key *key;
- unsigned int flags;
-
struct ieee80211_rx_status *status;
struct ieee80211_rate *rate;
+
+ u16 fc, ethertype;
+ unsigned int flags;
int sent_ps_buffered;
int queue;
int load;
@@ -222,9 +224,9 @@ struct ieee80211_tx_packet_data {
struct ieee80211_tx_stored_packet {
struct ieee80211_tx_control control;
struct sk_buff *skb;
- int num_extra_frag;
struct sk_buff **extra_frag;
struct ieee80211_rate *last_frag_rate;
+ int num_extra_frag;
unsigned int last_frag_rate_ctrl_probe;
};
@@ -246,8 +248,8 @@ struct ieee80211_if_ap {
* bitmap_empty :)
* NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */
u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
- atomic_t num_sta_ps; /* number of stations in PS mode */
struct sk_buff_head ps_bc_buf;
+ atomic_t num_sta_ps; /* number of stations in PS mode */
int dtim_count;
int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
int max_ratectrl_rateidx; /* max TX rateidx for rate control */
@@ -255,8 +257,8 @@ struct ieee80211_if_ap {
};
struct ieee80211_if_wds {
- u8 remote_addr[ETH_ALEN];
struct sta_info *sta;
+ u8 remote_addr[ETH_ALEN];
};
struct ieee80211_if_vlan {
@@ -290,12 +292,12 @@ struct mesh_config {
u8 dot11MeshTTL;
bool auto_open_plinks;
/* HWMP parameters */
- u32 dot11MeshHWMPactivePathTimeout;
- u16 dot11MeshHWMPpreqMinInterval;
- u16 dot11MeshHWMPnetDiameterTraversalTime;
u8 dot11MeshHWMPmaxPREQretries;
u32 path_refresh_time;
u16 min_discovery_timeout;
+ u32 dot11MeshHWMPactivePathTimeout;
+ u16 dot11MeshHWMPpreqMinInterval;
+ u16 dot11MeshHWMPnetDiameterTraversalTime;
};
@@ -314,23 +316,22 @@ struct mesh_config {
#define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
#define IEEE80211_STA_PRIVACY_INVOKED BIT(13)
struct ieee80211_if_sta {
+ struct timer_list timer;
+ struct work_struct work;
+ u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
enum {
IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED,
IEEE80211_MESH_UP
} state;
- struct timer_list timer;
- struct work_struct work;
- u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
- u8 ssid[IEEE80211_MAX_SSID_LEN];
size_t ssid_len;
u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
size_t scan_ssid_len;
#ifdef CONFIG_MAC80211_MESH
struct timer_list mesh_path_timer;
u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
- bool accepting_plinks;
size_t mesh_id_len;
/* Active Path Selection Protocol Identifier */
u8 mesh_pp_id[4];
@@ -354,6 +355,7 @@ struct ieee80211_if_sta {
struct mesh_stats mshstats;
struct mesh_config mshcfg;
u8 mesh_seqnum[3];
+ bool accepting_plinks;
#endif
u16 aid;
u16 ap_capab, capab;
@@ -364,16 +366,18 @@ struct ieee80211_if_sta {
u8 *assocreq_ies, *assocresp_ies;
size_t assocreq_ies_len, assocresp_ies_len;
+ struct sk_buff_head skb_queue;
+
int auth_tries, assoc_tries;
+ unsigned long request;
+
+ unsigned long last_probe;
+
unsigned int flags;
#define IEEE80211_STA_REQ_SCAN 0
#define IEEE80211_STA_REQ_AUTH 1
#define IEEE80211_STA_REQ_RUN 2
- unsigned long request;
- struct sk_buff_head skb_queue;
-
- unsigned long last_probe;
#define IEEE80211_AUTH_ALG_OPEN BIT(0)
#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 5af23d31872..b047eebb633 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -55,9 +55,6 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
key = sta->key;
}
- if (!key)
- return -ENOENT;
-
ieee80211_key_free(key);
return 0;
} else {
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index cf51ca6804d..f9cf2f18789 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -1216,12 +1216,11 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
buf_size = buf_size << sband->ht_info.ampdu_factor;
}
- tid_agg_rx = &sta->ampdu_mlme.tid_rx[tid];
/* examine state machine */
spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
- if (tid_agg_rx->state != HT_AGG_STATE_IDLE) {
+ if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "unexpected AddBA Req from "
@@ -1231,6 +1230,24 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
goto end;
}
+ /* prepare A-MPDU MLME for Rx aggregation */
+ sta->ampdu_mlme.tid_rx[tid] =
+ kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC);
+ if (!sta->ampdu_mlme.tid_rx[tid]) {
+ if (net_ratelimit())
+ printk(KERN_ERR "allocate rx mlme to tid %d failed\n",
+ tid);
+ goto end;
+ }
+ /* rx timer */
+ sta->ampdu_mlme.tid_rx[tid]->session_timer.function =
+ sta_rx_agg_session_timer_expired;
+ sta->ampdu_mlme.tid_rx[tid]->session_timer.data =
+ (unsigned long)&sta->timer_to_tid[tid];
+ init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
+
+ tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
+
/* prepare reordering buffer */
tid_agg_rx->reorder_buf =
kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC);
@@ -1238,6 +1255,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
if (net_ratelimit())
printk(KERN_ERR "can not allocate reordering buffer "
"to tid %d\n", tid);
+ kfree(sta->ampdu_mlme.tid_rx[tid]);
goto end;
}
memset(tid_agg_rx->reorder_buf, 0,
@@ -1252,11 +1270,13 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
if (ret) {
kfree(tid_agg_rx->reorder_buf);
+ kfree(tid_agg_rx);
+ sta->ampdu_mlme.tid_rx[tid] = NULL;
goto end;
}
/* change state and send addba resp */
- tid_agg_rx->state = HT_AGG_STATE_OPERATIONAL;
+ sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL;
tid_agg_rx->dialog_token = dialog_token;
tid_agg_rx->ssn = start_seq_num;
tid_agg_rx->head_seq_num = start_seq_num;
@@ -1295,39 +1315,37 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
- state = &sta->ampdu_mlme.tid_tx[tid].state;
+ state = &sta->ampdu_mlme.tid_state_tx[tid];
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
+ "%d\n", *state);
+ goto addba_resp_exit;
+ }
+
if (mgmt->u.action.u.addba_resp.dialog_token !=
- sta->ampdu_mlme.tid_tx[tid].dialog_token) {
+ sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
- rcu_read_unlock();
- return;
+ goto addba_resp_exit;
}
- del_timer_sync(&sta->ampdu_mlme.tid_tx[tid].addba_resp_timer);
+ del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
== WLAN_STATUS_SUCCESS) {
- if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
- printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
- "%d\n", *state);
- rcu_read_unlock();
- return;
- }
-
if (*state & HT_ADDBA_RECEIVED_MSK)
printk(KERN_DEBUG "double addBA response\n");
*state |= HT_ADDBA_RECEIVED_MSK;
- sta->ampdu_mlme.tid_tx[tid].addba_req_num = 0;
+ sta->ampdu_mlme.addba_req_num[tid] = 0;
if (*state == HT_AGG_STATE_OPERATIONAL) {
printk(KERN_DEBUG "Aggregation on for tid %d \n", tid);
@@ -1339,13 +1357,15 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
} else {
printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid);
- sta->ampdu_mlme.tid_tx[tid].addba_req_num++;
+ 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);
ieee80211_stop_tx_ba_session(hw, sta->addr, tid,
WLAN_BACK_INITIATOR);
}
+
+addba_resp_exit:
rcu_read_unlock();
}
@@ -1411,13 +1431,13 @@ 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);
- if (sta->ampdu_mlme.tid_rx[tid].state
+ if (sta->ampdu_mlme.tid_state_rx[tid]
!= HT_AGG_STATE_OPERATIONAL) {
spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
rcu_read_unlock();
return;
}
- sta->ampdu_mlme.tid_rx[tid].state =
+ 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);
@@ -1434,25 +1454,27 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
/* shutdown timer has not expired */
if (initiator != WLAN_BACK_TIMER)
- del_timer_sync(&sta->ampdu_mlme.tid_rx[tid].
- session_timer);
+ del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
/* check if this is a self generated aggregation halt */
if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
ieee80211_send_delba(dev, ra, tid, 0, reason);
/* free the reordering buffer */
- for (i = 0; i < sta->ampdu_mlme.tid_rx[tid].buf_size; i++) {
- if (sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]) {
+ for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
+ if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
/* release the reordered frames */
- dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]);
- sta->ampdu_mlme.tid_rx[tid].stored_mpdu_num--;
- sta->ampdu_mlme.tid_rx[tid].reorder_buf[i] = NULL;
+ dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
+ sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
+ sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
}
}
- kfree(sta->ampdu_mlme.tid_rx[tid].reorder_buf);
+ /* free resources */
+ kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
+ kfree(sta->ampdu_mlme.tid_rx[tid]);
+ sta->ampdu_mlme.tid_rx[tid] = NULL;
+ sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
- sta->ampdu_mlme.tid_rx[tid].state = HT_AGG_STATE_IDLE;
rcu_read_unlock();
}
@@ -1491,7 +1513,7 @@ static void ieee80211_sta_process_delba(struct net_device *dev,
WLAN_BACK_INITIATOR, 0);
else { /* WLAN_BACK_RECIPIENT */
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
- sta->ampdu_mlme.tid_tx[tid].state =
+ sta->ampdu_mlme.tid_state_tx[tid] =
HT_AGG_STATE_OPERATIONAL;
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid,
@@ -1528,7 +1550,7 @@ void sta_addba_resp_timer_expired(unsigned long data)
return;
}
- state = &sta->ampdu_mlme.tid_tx[tid].state;
+ state = &sta->ampdu_mlme.tid_state_tx[tid];
/* check if the TID waits for addBA response */
spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 644d2774469..d9c6ed5be4f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1514,9 +1514,10 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
if (!rx->sta)
return RX_CONTINUE;
tid = le16_to_cpu(bar->control) >> 12;
- tid_agg_rx = &(rx->sta->ampdu_mlme.tid_rx[tid]);
- if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
+ if (rx->sta->ampdu_mlme.tid_state_rx[tid]
+ != HT_AGG_STATE_OPERATIONAL)
return RX_CONTINUE;
+ tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
@@ -2123,11 +2124,12 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
qc = skb->data + ieee80211_get_hdrlen(fc) - QOS_CONTROL_LEN;
tid = qc[0] & QOS_CONTROL_TID_MASK;
- tid_agg_rx = &(sta->ampdu_mlme.tid_rx[tid]);
- if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
+ if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
goto end_reorder;
+ tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
+
/* null data frames are excluded */
if (unlikely(fc & IEEE80211_STYPE_NULLFUNC))
goto end_reorder;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 3b84c16cf05..f708367092d 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -170,9 +170,16 @@ void sta_info_destroy(struct sta_info *sta)
dev_kfree_skb_any(skb);
for (i = 0; i < STA_TID_NUM; i++) {
- del_timer_sync(&sta->ampdu_mlme.tid_rx[i].session_timer);
- del_timer_sync(&sta->ampdu_mlme.tid_tx[i].addba_resp_timer);
+ spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
+ if (sta->ampdu_mlme.tid_rx[i])
+ del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer);
+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ if (sta->ampdu_mlme.tid_tx[i])
+ del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer);
+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
}
+
rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
rate_control_put(sta->rate_ctrl);
@@ -227,18 +234,13 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->timer_to_tid[i] = i;
/* tid to tx queue: initialize according to HW (0 is valid) */
sta->tid_to_tx_q[i] = local->hw.queues;
- /* rx timers */
- sta->ampdu_mlme.tid_rx[i].session_timer.function =
- sta_rx_agg_session_timer_expired;
- sta->ampdu_mlme.tid_rx[i].session_timer.data =
- (unsigned long)&sta->timer_to_tid[i];
- init_timer(&sta->ampdu_mlme.tid_rx[i].session_timer);
- /* tx timers */
- sta->ampdu_mlme.tid_tx[i].addba_resp_timer.function =
- sta_addba_resp_timer_expired;
- sta->ampdu_mlme.tid_tx[i].addba_resp_timer.data =
- (unsigned long)&sta->timer_to_tid[i];
- init_timer(&sta->ampdu_mlme.tid_tx[i].addba_resp_timer);
+ /* rx */
+ sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE;
+ sta->ampdu_mlme.tid_rx[i] = NULL;
+ /* tx */
+ sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE;
+ sta->ampdu_mlme.tid_tx[i] = NULL;
+ sta->ampdu_mlme.addba_req_num[i] = 0;
}
skb_queue_head_init(&sta->ps_tx_buf);
skb_queue_head_init(&sta->tx_filtered);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index f166c8039f2..5e39a4164b9 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -63,47 +63,42 @@ enum ieee80211_sta_info_flags {
#define HT_AGG_STATE_OPERATIONAL (HT_ADDBA_REQUESTED_MSK | \
HT_ADDBA_DRV_READY_MSK | \
HT_ADDBA_RECEIVED_MSK)
+#define HT_AGG_STATE_DEBUGFS_CTL BIT(7)
/**
* struct tid_ampdu_tx - TID aggregation information (Tx).
*
- * @state: TID's state in session state machine.
- * @dialog_token: dialog token for aggregation session
- * @ssn: Starting Sequence Number expected to be aggregated.
* @addba_resp_timer: timer for peer's response to addba request
- * @addba_req_num: number of times addBA request has been sent.
+ * @ssn: Starting Sequence Number expected to be aggregated.
+ * @dialog_token: dialog token for aggregation session
*/
struct tid_ampdu_tx {
- u8 state;
- u8 dialog_token;
- u16 ssn;
struct timer_list addba_resp_timer;
- u8 addba_req_num;
+ u16 ssn;
+ u8 dialog_token;
};
/**
* struct tid_ampdu_rx - TID aggregation information (Rx).
*
- * @state: TID's state in session state machine.
- * @dialog_token: dialog token for aggregation session
+ * @reorder_buf: buffer to reorder incoming aggregated MPDUs
+ * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
+ * @head_seq_num: head sequence number in reordering buffer.
+ * @stored_mpdu_num: number of MPDUs in reordering buffer
* @ssn: Starting Sequence Number expected to be aggregated.
* @buf_size: buffer size for incoming A-MPDUs
* @timeout: reset timer value.
- * @head_seq_num: head sequence number in reordering buffer.
- * @stored_mpdu_num: number of MPDUs in reordering buffer
- * @reorder_buf: buffer to reorder incoming aggregated MPDUs
- * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
+ * @dialog_token: dialog token for aggregation session
*/
struct tid_ampdu_rx {
- u8 state;
- u8 dialog_token;
+ struct sk_buff **reorder_buf;
+ struct timer_list session_timer;
+ u16 head_seq_num;
+ u16 stored_mpdu_num;
u16 ssn;
u16 buf_size;
u16 timeout;
- u16 head_seq_num;
- u16 stored_mpdu_num;
- struct sk_buff **reorder_buf;
- struct timer_list session_timer;
+ u8 dialog_token;
};
/**
@@ -132,16 +127,24 @@ enum plink_state {
/**
* struct sta_ampdu_mlme - STA aggregation information.
*
+ * @tid_state_rx: TID's state in Rx session state machine.
* @tid_rx: aggregation info for Rx per TID
- * @tid_tx: aggregation info for Tx per TID
* @ampdu_rx: for locking sections in aggregation Rx flow
+ * @tid_state_tx: TID's state in Tx session state machine.
+ * @tid_tx: aggregation info for Tx per TID
+ * @addba_req_num: number of times addBA request has been sent.
* @ampdu_tx: for locking sectionsi in aggregation Tx flow
* @dialog_token_allocator: dialog token enumerator for each new session;
*/
struct sta_ampdu_mlme {
- struct tid_ampdu_rx tid_rx[STA_TID_NUM];
- struct tid_ampdu_tx tid_tx[STA_TID_NUM];
+ /* rx */
+ u8 tid_state_rx[STA_TID_NUM];
+ struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
spinlock_t ampdu_rx;
+ /* tx */
+ u8 tid_state_tx[STA_TID_NUM];
+ struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
+ u8 addba_req_num[STA_TID_NUM];
spinlock_t ampdu_tx;
u8 dialog_token_allocator;
};
diff --git a/net/wireless/util.c b/net/wireless/util.c
index f3e623df351..f54424693a3 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -33,8 +33,8 @@ int ieee80211_frequency_to_channel(int freq)
}
EXPORT_SYMBOL(ieee80211_frequency_to_channel);
-struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy,
- int freq)
+struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
+ int freq)
{
enum ieee80211_band band;
struct ieee80211_supported_band *sband;
@@ -54,7 +54,7 @@ struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy,
return NULL;
}
-EXPORT_SYMBOL(ieee80211_get_channel);
+EXPORT_SYMBOL(__ieee80211_get_channel);
static void set_mandatory_flags_band(struct ieee80211_supported_band *sband,
enum ieee80211_band band)