diff options
author | Ron Rindjunsky <ron.rindjunsky@intel.com> | 2008-03-26 14:36:03 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-27 16:03:20 -0400 |
commit | cee24a3e580f1062c8bb8b1692b95014d882bc7d (patch) | |
tree | e7df5e0f987a817ff0c9b14142a4efc583d39fa2 /net/mac80211/ieee80211_sta.c | |
parent | 6c507cd0400cb51dd2ee251c1b8756b9375a1128 (diff) |
mac80211: A-MPDU MLME use dynamic allocation
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>
Diffstat (limited to 'net/mac80211/ieee80211_sta.c')
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 84 |
1 files changed, 53 insertions, 31 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index cf51ca6804dd..f9cf2f187893 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, | |||
1216 | buf_size = buf_size << sband->ht_info.ampdu_factor; | 1216 | buf_size = buf_size << sband->ht_info.ampdu_factor; |
1217 | } | 1217 | } |
1218 | 1218 | ||
1219 | tid_agg_rx = &sta->ampdu_mlme.tid_rx[tid]; | ||
1220 | 1219 | ||
1221 | /* examine state machine */ | 1220 | /* examine state machine */ |
1222 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 1221 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); |
1223 | 1222 | ||
1224 | if (tid_agg_rx->state != HT_AGG_STATE_IDLE) { | 1223 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { |
1225 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1224 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1226 | if (net_ratelimit()) | 1225 | if (net_ratelimit()) |
1227 | printk(KERN_DEBUG "unexpected AddBA Req from " | 1226 | printk(KERN_DEBUG "unexpected AddBA Req from " |
@@ -1231,6 +1230,24 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1231 | goto end; | 1230 | goto end; |
1232 | } | 1231 | } |
1233 | 1232 | ||
1233 | /* prepare A-MPDU MLME for Rx aggregation */ | ||
1234 | sta->ampdu_mlme.tid_rx[tid] = | ||
1235 | kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | ||
1236 | if (!sta->ampdu_mlme.tid_rx[tid]) { | ||
1237 | if (net_ratelimit()) | ||
1238 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | ||
1239 | tid); | ||
1240 | goto end; | ||
1241 | } | ||
1242 | /* rx timer */ | ||
1243 | sta->ampdu_mlme.tid_rx[tid]->session_timer.function = | ||
1244 | sta_rx_agg_session_timer_expired; | ||
1245 | sta->ampdu_mlme.tid_rx[tid]->session_timer.data = | ||
1246 | (unsigned long)&sta->timer_to_tid[tid]; | ||
1247 | init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
1248 | |||
1249 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
1250 | |||
1234 | /* prepare reordering buffer */ | 1251 | /* prepare reordering buffer */ |
1235 | tid_agg_rx->reorder_buf = | 1252 | tid_agg_rx->reorder_buf = |
1236 | kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC); | 1253 | kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC); |
@@ -1238,6 +1255,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1238 | if (net_ratelimit()) | 1255 | if (net_ratelimit()) |
1239 | printk(KERN_ERR "can not allocate reordering buffer " | 1256 | printk(KERN_ERR "can not allocate reordering buffer " |
1240 | "to tid %d\n", tid); | 1257 | "to tid %d\n", tid); |
1258 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
1241 | goto end; | 1259 | goto end; |
1242 | } | 1260 | } |
1243 | memset(tid_agg_rx->reorder_buf, 0, | 1261 | memset(tid_agg_rx->reorder_buf, 0, |
@@ -1252,11 +1270,13 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1252 | 1270 | ||
1253 | if (ret) { | 1271 | if (ret) { |
1254 | kfree(tid_agg_rx->reorder_buf); | 1272 | kfree(tid_agg_rx->reorder_buf); |
1273 | kfree(tid_agg_rx); | ||
1274 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
1255 | goto end; | 1275 | goto end; |
1256 | } | 1276 | } |
1257 | 1277 | ||
1258 | /* change state and send addba resp */ | 1278 | /* change state and send addba resp */ |
1259 | tid_agg_rx->state = HT_AGG_STATE_OPERATIONAL; | 1279 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; |
1260 | tid_agg_rx->dialog_token = dialog_token; | 1280 | tid_agg_rx->dialog_token = dialog_token; |
1261 | tid_agg_rx->ssn = start_seq_num; | 1281 | tid_agg_rx->ssn = start_seq_num; |
1262 | tid_agg_rx->head_seq_num = start_seq_num; | 1282 | tid_agg_rx->head_seq_num = start_seq_num; |
@@ -1295,39 +1315,37 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1295 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 1315 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
1296 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 1316 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
1297 | 1317 | ||
1298 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 1318 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
1299 | 1319 | ||
1300 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1320 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
1301 | 1321 | ||
1322 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
1323 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
1324 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" | ||
1325 | "%d\n", *state); | ||
1326 | goto addba_resp_exit; | ||
1327 | } | ||
1328 | |||
1302 | if (mgmt->u.action.u.addba_resp.dialog_token != | 1329 | if (mgmt->u.action.u.addba_resp.dialog_token != |
1303 | sta->ampdu_mlme.tid_tx[tid].dialog_token) { | 1330 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { |
1304 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1331 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
1305 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1332 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1306 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | 1333 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); |
1307 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1334 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
1308 | rcu_read_unlock(); | 1335 | goto addba_resp_exit; |
1309 | return; | ||
1310 | } | 1336 | } |
1311 | 1337 | ||
1312 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid].addba_resp_timer); | 1338 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
1313 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1339 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1314 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | 1340 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); |
1315 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1341 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
1316 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 1342 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
1317 | == WLAN_STATUS_SUCCESS) { | 1343 | == WLAN_STATUS_SUCCESS) { |
1318 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
1319 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
1320 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" | ||
1321 | "%d\n", *state); | ||
1322 | rcu_read_unlock(); | ||
1323 | return; | ||
1324 | } | ||
1325 | |||
1326 | if (*state & HT_ADDBA_RECEIVED_MSK) | 1344 | if (*state & HT_ADDBA_RECEIVED_MSK) |
1327 | printk(KERN_DEBUG "double addBA response\n"); | 1345 | printk(KERN_DEBUG "double addBA response\n"); |
1328 | 1346 | ||
1329 | *state |= HT_ADDBA_RECEIVED_MSK; | 1347 | *state |= HT_ADDBA_RECEIVED_MSK; |
1330 | sta->ampdu_mlme.tid_tx[tid].addba_req_num = 0; | 1348 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
1331 | 1349 | ||
1332 | if (*state == HT_AGG_STATE_OPERATIONAL) { | 1350 | if (*state == HT_AGG_STATE_OPERATIONAL) { |
1333 | printk(KERN_DEBUG "Aggregation on for tid %d \n", tid); | 1351 | 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, | |||
1339 | } else { | 1357 | } else { |
1340 | printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid); | 1358 | printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid); |
1341 | 1359 | ||
1342 | sta->ampdu_mlme.tid_tx[tid].addba_req_num++; | 1360 | sta->ampdu_mlme.addba_req_num[tid]++; |
1343 | /* this will allow the state check in stop_BA_session */ | 1361 | /* this will allow the state check in stop_BA_session */ |
1344 | *state = HT_AGG_STATE_OPERATIONAL; | 1362 | *state = HT_AGG_STATE_OPERATIONAL; |
1345 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1363 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
1346 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, | 1364 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, |
1347 | WLAN_BACK_INITIATOR); | 1365 | WLAN_BACK_INITIATOR); |
1348 | } | 1366 | } |
1367 | |||
1368 | addba_resp_exit: | ||
1349 | rcu_read_unlock(); | 1369 | rcu_read_unlock(); |
1350 | } | 1370 | } |
1351 | 1371 | ||
@@ -1411,13 +1431,13 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | |||
1411 | 1431 | ||
1412 | /* check if TID is in operational state */ | 1432 | /* check if TID is in operational state */ |
1413 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 1433 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); |
1414 | if (sta->ampdu_mlme.tid_rx[tid].state | 1434 | if (sta->ampdu_mlme.tid_state_rx[tid] |
1415 | != HT_AGG_STATE_OPERATIONAL) { | 1435 | != HT_AGG_STATE_OPERATIONAL) { |
1416 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1436 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); |
1417 | rcu_read_unlock(); | 1437 | rcu_read_unlock(); |
1418 | return; | 1438 | return; |
1419 | } | 1439 | } |
1420 | sta->ampdu_mlme.tid_rx[tid].state = | 1440 | sta->ampdu_mlme.tid_state_rx[tid] = |
1421 | HT_AGG_STATE_REQ_STOP_BA_MSK | | 1441 | HT_AGG_STATE_REQ_STOP_BA_MSK | |
1422 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 1442 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
1423 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1443 | 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, | |||
1434 | 1454 | ||
1435 | /* shutdown timer has not expired */ | 1455 | /* shutdown timer has not expired */ |
1436 | if (initiator != WLAN_BACK_TIMER) | 1456 | if (initiator != WLAN_BACK_TIMER) |
1437 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]. | 1457 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); |
1438 | session_timer); | ||
1439 | 1458 | ||
1440 | /* check if this is a self generated aggregation halt */ | 1459 | /* check if this is a self generated aggregation halt */ |
1441 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | 1460 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) |
1442 | ieee80211_send_delba(dev, ra, tid, 0, reason); | 1461 | ieee80211_send_delba(dev, ra, tid, 0, reason); |
1443 | 1462 | ||
1444 | /* free the reordering buffer */ | 1463 | /* free the reordering buffer */ |
1445 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid].buf_size; i++) { | 1464 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { |
1446 | if (sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]) { | 1465 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { |
1447 | /* release the reordered frames */ | 1466 | /* release the reordered frames */ |
1448 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]); | 1467 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); |
1449 | sta->ampdu_mlme.tid_rx[tid].stored_mpdu_num--; | 1468 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; |
1450 | sta->ampdu_mlme.tid_rx[tid].reorder_buf[i] = NULL; | 1469 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; |
1451 | } | 1470 | } |
1452 | } | 1471 | } |
1453 | kfree(sta->ampdu_mlme.tid_rx[tid].reorder_buf); | 1472 | /* free resources */ |
1473 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | ||
1474 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
1475 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
1476 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
1454 | 1477 | ||
1455 | sta->ampdu_mlme.tid_rx[tid].state = HT_AGG_STATE_IDLE; | ||
1456 | rcu_read_unlock(); | 1478 | rcu_read_unlock(); |
1457 | } | 1479 | } |
1458 | 1480 | ||
@@ -1491,7 +1513,7 @@ static void ieee80211_sta_process_delba(struct net_device *dev, | |||
1491 | WLAN_BACK_INITIATOR, 0); | 1513 | WLAN_BACK_INITIATOR, 0); |
1492 | else { /* WLAN_BACK_RECIPIENT */ | 1514 | else { /* WLAN_BACK_RECIPIENT */ |
1493 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1515 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
1494 | sta->ampdu_mlme.tid_tx[tid].state = | 1516 | sta->ampdu_mlme.tid_state_tx[tid] = |
1495 | HT_AGG_STATE_OPERATIONAL; | 1517 | HT_AGG_STATE_OPERATIONAL; |
1496 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1518 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
1497 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, | 1519 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, |
@@ -1528,7 +1550,7 @@ void sta_addba_resp_timer_expired(unsigned long data) | |||
1528 | return; | 1550 | return; |
1529 | } | 1551 | } |
1530 | 1552 | ||
1531 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 1553 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
1532 | /* check if the TID waits for addBA response */ | 1554 | /* check if the TID waits for addBA response */ |
1533 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1555 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
1534 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 1556 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |