Skip to content

Commit

Permalink
mac80211: A-MPDU MLME use dynamic allocation
Browse files Browse the repository at this point in the history
This patch alters the A-MPDU MLME in sta_info to use dynamic allocation,
thus drastically improving memory usage - from a constant ~2 Kbyte in
the previous (static) allocation to a lower limit of ~200 Byte and an upper
limit of ~2 Kbyte.

Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Ron Rindjunsky authored and John W. Linville committed Mar 27, 2008
1 parent 6c507cd commit cee24a3
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 100 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/iwl-4965-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
DECLARE_MAC_BUF(mac);

spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
state = sta->ampdu_mlme.tid_tx[tid].state;
state = sta->ampdu_mlme.tid_state_tx[tid];
spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);

if (state == HT_AGG_STATE_IDLE &&
Expand Down
17 changes: 10 additions & 7 deletions net/mac80211/debugfs_sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -230,12 +233,12 @@ 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].state |=
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].state &=
sta->ampdu_mlme.tid_state_rx[tid_num] &=
~HT_AGG_STATE_DEBUGFS_CTL;
tid_static_rx[tid_num] = 1;
}
Expand Down
64 changes: 42 additions & 22 deletions net/mac80211/ieee80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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;

Expand All @@ -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();
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down
Loading

0 comments on commit cee24a3

Please sign in to comment.