aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>2012-01-21 04:52:53 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2012-01-24 07:12:27 -0500
commit1d2a4456de20db73362c86c88fe9c02169f29d0a (patch)
tree3ecb864ad46a88bc7255a3431e4f446eb01a2829
parent3fdc099109e75359e5de54c56478c06255850741 (diff)
ath6kl: Fix bug in maintaining aggregation state in AP mode
Currently rx aggregation related states are maintained per vif, but this will not properly work when operating in AP mode. Aggregation is completely broken when more than one 11n stations are connected to AP mode vif. Fix this issue by keeping station specific aggregation state in sta_list. Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c5
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.c7
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h4
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c4
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c7
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c106
6 files changed, 88 insertions, 45 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 8bf447a6a84e..fed7b8077f5e 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2871,6 +2871,11 @@ struct ath6kl *ath6kl_cfg80211_create(void)
2871/* Note: ar variable must not be accessed after calling this! */ 2871/* Note: ar variable must not be accessed after calling this! */
2872void ath6kl_cfg80211_destroy(struct ath6kl *ar) 2872void ath6kl_cfg80211_destroy(struct ath6kl *ar)
2873{ 2873{
2874 int i;
2875
2876 for (i = 0; i < AP_MAX_NUM_STA; i++)
2877 kfree(ar->sta_list[i].aggr_conn);
2878
2874 wiphy_free(ar->wiphy); 2879 wiphy_free(ar->wiphy);
2875} 2880}
2876 2881
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index d764afec395b..0d92e7179f8a 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -253,6 +253,13 @@ struct ath6kl *ath6kl_core_create(struct device *dev)
253 spin_lock_init(&ar->sta_list[ctr].psq_lock); 253 spin_lock_init(&ar->sta_list[ctr].psq_lock);
254 skb_queue_head_init(&ar->sta_list[ctr].psq); 254 skb_queue_head_init(&ar->sta_list[ctr].psq);
255 skb_queue_head_init(&ar->sta_list[ctr].apsdq); 255 skb_queue_head_init(&ar->sta_list[ctr].apsdq);
256 ar->sta_list[ctr].aggr_conn =
257 kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL);
258 if (!ar->sta_list[ctr].aggr_conn) {
259 ath6kl_err("Failed to allocate memory for sta aggregation information\n");
260 ath6kl_core_destroy(ar);
261 return NULL;
262 }
256 } 263 }
257 264
258 skb_queue_head_init(&ar->mcastpsq); 265 skb_queue_head_init(&ar->mcastpsq);
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 1b9054f8f4e4..ed9fcc11b5fc 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -298,6 +298,7 @@ struct ath6kl_sta {
298 spinlock_t psq_lock; 298 spinlock_t psq_lock;
299 u8 apsd_info; 299 u8 apsd_info;
300 struct sk_buff_head apsdq; 300 struct sk_buff_head apsdq;
301 struct aggr_info_conn *aggr_conn;
301}; 302};
302 303
303struct ath6kl_version { 304struct ath6kl_version {
@@ -713,6 +714,7 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie);
713int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); 714int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev);
714 715
715struct aggr_info *aggr_init(struct ath6kl_vif *vif); 716struct aggr_info *aggr_init(struct ath6kl_vif *vif);
717void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info_conn *aggr_conn);
716void ath6kl_rx_refill(struct htc_target *target, 718void ath6kl_rx_refill(struct htc_target *target,
717 enum htc_endpoint_id endpoint); 719 enum htc_endpoint_id endpoint);
718void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); 720void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count);
@@ -720,7 +722,7 @@ struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
720 enum htc_endpoint_id endpoint, 722 enum htc_endpoint_id endpoint,
721 int len); 723 int len);
722void aggr_module_destroy(struct aggr_info *aggr_info); 724void aggr_module_destroy(struct aggr_info *aggr_info);
723void aggr_reset_state(struct aggr_info *aggr_info); 725void aggr_reset_state(struct aggr_info_conn *aggr_conn);
724 726
725struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr); 727struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr);
726struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); 728struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid);
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 167dc41af2de..4d8eb1cca6e9 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1660,6 +1660,7 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
1660void ath6kl_stop_txrx(struct ath6kl *ar) 1660void ath6kl_stop_txrx(struct ath6kl *ar)
1661{ 1661{
1662 struct ath6kl_vif *vif, *tmp_vif; 1662 struct ath6kl_vif *vif, *tmp_vif;
1663 int i;
1663 1664
1664 set_bit(DESTROY_IN_PROGRESS, &ar->flag); 1665 set_bit(DESTROY_IN_PROGRESS, &ar->flag);
1665 1666
@@ -1668,6 +1669,9 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
1668 return; 1669 return;
1669 } 1670 }
1670 1671
1672 for (i = 0; i < AP_MAX_NUM_STA; i++)
1673 aggr_reset_state(ar->sta_list[i].aggr_conn);
1674
1671 spin_lock_bh(&ar->list_lock); 1675 spin_lock_bh(&ar->list_lock);
1672 list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) { 1676 list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
1673 list_del(&vif->list); 1677 list_del(&vif->list);
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index acb4acb71718..39da1f98da87 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -74,6 +74,7 @@ static void ath6kl_add_new_sta(struct ath6kl_vif *vif, u8 *mac, u16 aid,
74 74
75 ar->sta_list_index = ar->sta_list_index | (1 << free_slot); 75 ar->sta_list_index = ar->sta_list_index | (1 << free_slot);
76 ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid); 76 ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid);
77 aggr_conn_init(vif, sta->aggr_conn);
77} 78}
78 79
79static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) 80static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
@@ -94,7 +95,7 @@ static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
94 sta->sta_flags = 0; 95 sta->sta_flags = 0;
95 96
96 ar->sta_list_index = ar->sta_list_index & ~(1 << i); 97 ar->sta_list_index = ar->sta_list_index & ~(1 << i);
97 98 aggr_reset_state(sta->aggr_conn);
98} 99}
99 100
100static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason) 101static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason)
@@ -602,7 +603,7 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
602 netif_carrier_on(vif->ndev); 603 netif_carrier_on(vif->ndev);
603 spin_unlock_bh(&vif->if_lock); 604 spin_unlock_bh(&vif->if_lock);
604 605
605 aggr_reset_state(vif->aggr_cntxt); 606 aggr_reset_state(vif->aggr_cntxt->aggr_conn);
606 vif->reconnect_flag = 0; 607 vif->reconnect_flag = 0;
607 608
608 if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) { 609 if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) {
@@ -924,7 +925,7 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
924 assoc_resp_len, assoc_info, 925 assoc_resp_len, assoc_info,
925 prot_reason_status); 926 prot_reason_status);
926 927
927 aggr_reset_state(vif->aggr_cntxt); 928 aggr_reset_state(vif->aggr_cntxt->aggr_conn);
928 929
929 del_timer(&vif->disconnect_timer); 930 del_timer(&vif->disconnect_timer);
930 931
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 8cf7b2fa0f41..62c12102e146 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -22,12 +22,18 @@
22 * aid - tid_mux4..tid_mux7 22 * aid - tid_mux4..tid_mux7
23 */ 23 */
24#define ATH6KL_TID_MASK 0xf 24#define ATH6KL_TID_MASK 0xf
25#define ATH6KL_AID_SHIFT 4
25 26
26static inline u8 ath6kl_get_tid(u8 tid_mux) 27static inline u8 ath6kl_get_tid(u8 tid_mux)
27{ 28{
28 return tid_mux & ATH6KL_TID_MASK; 29 return tid_mux & ATH6KL_TID_MASK;
29} 30}
30 31
32static inline u8 ath6kl_get_aid(u8 tid_mux)
33{
34 return tid_mux >> ATH6KL_AID_SHIFT;
35}
36
31static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, 37static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev,
32 u32 *map_no) 38 u32 *map_no)
33{ 39{
@@ -1003,7 +1009,7 @@ static void aggr_slice_amsdu(struct aggr_info *p_aggr,
1003 dev_kfree_skb(skb); 1009 dev_kfree_skb(skb);
1004} 1010}
1005 1011
1006static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, 1012static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
1007 u16 seq_no, u8 order) 1013 u16 seq_no, u8 order)
1008{ 1014{
1009 struct sk_buff *skb; 1015 struct sk_buff *skb;
@@ -1011,12 +1017,7 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid,
1011 struct skb_hold_q *node; 1017 struct skb_hold_q *node;
1012 u16 idx, idx_end, seq_end; 1018 u16 idx, idx_end, seq_end;
1013 struct rxtid_stats *stats; 1019 struct rxtid_stats *stats;
1014 struct aggr_info_conn *agg_conn;
1015 1020
1016 if (!p_aggr || !p_aggr->aggr_conn)
1017 return;
1018
1019 agg_conn = p_aggr->aggr_conn;
1020 rxtid = &agg_conn->rx_tid[tid]; 1021 rxtid = &agg_conn->rx_tid[tid];
1021 stats = &agg_conn->stat[tid]; 1022 stats = &agg_conn->stat[tid];
1022 1023
@@ -1047,7 +1048,8 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid,
1047 1048
1048 if (node->skb) { 1049 if (node->skb) {
1049 if (node->is_amsdu) 1050 if (node->is_amsdu)
1050 aggr_slice_amsdu(p_aggr, rxtid, node->skb); 1051 aggr_slice_amsdu(agg_conn->aggr_info, rxtid,
1052 node->skb);
1051 else 1053 else
1052 skb_queue_tail(&rxtid->q, node->skb); 1054 skb_queue_tail(&rxtid->q, node->skb);
1053 node->skb = NULL; 1055 node->skb = NULL;
@@ -1066,7 +1068,7 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid,
1066 ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, skb); 1068 ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, skb);
1067} 1069}
1068 1070
1069static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, 1071static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
1070 u16 seq_no, 1072 u16 seq_no,
1071 bool is_amsdu, struct sk_buff *frame) 1073 bool is_amsdu, struct sk_buff *frame)
1072{ 1074{
@@ -1077,7 +1079,6 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
1077 u16 idx, st, cur, end; 1079 u16 idx, st, cur, end;
1078 bool is_queued = false; 1080 bool is_queued = false;
1079 u16 extended_end; 1081 u16 extended_end;
1080 struct aggr_info_conn *agg_conn = agg_info->aggr_conn;
1081 1082
1082 rxtid = &agg_conn->rx_tid[tid]; 1083 rxtid = &agg_conn->rx_tid[tid];
1083 stats = &agg_conn->stat[tid]; 1084 stats = &agg_conn->stat[tid];
@@ -1086,7 +1087,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
1086 1087
1087 if (!rxtid->aggr) { 1088 if (!rxtid->aggr) {
1088 if (is_amsdu) { 1089 if (is_amsdu) {
1089 aggr_slice_amsdu(agg_info, rxtid, frame); 1090 aggr_slice_amsdu(agg_conn->aggr_info, rxtid, frame);
1090 is_queued = true; 1091 is_queued = true;
1091 stats->num_amsdu++; 1092 stats->num_amsdu++;
1092 while ((skb = skb_dequeue(&rxtid->q))) 1093 while ((skb = skb_dequeue(&rxtid->q)))
@@ -1110,7 +1111,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
1110 (cur < end || cur > extended_end)) || 1111 (cur < end || cur > extended_end)) ||
1111 ((end > extended_end) && (cur > extended_end) && 1112 ((end > extended_end) && (cur > extended_end) &&
1112 (cur < end))) { 1113 (cur < end))) {
1113 aggr_deque_frms(agg_info, tid, 0, 0); 1114 aggr_deque_frms(agg_conn, tid, 0, 0);
1114 if (cur >= rxtid->hold_q_sz - 1) 1115 if (cur >= rxtid->hold_q_sz - 1)
1115 rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); 1116 rxtid->seq_next = cur - (rxtid->hold_q_sz - 1);
1116 else 1117 else
@@ -1127,7 +1128,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
1127 st = ATH6KL_MAX_SEQ_NO - 1128 st = ATH6KL_MAX_SEQ_NO -
1128 (rxtid->hold_q_sz - 2 - cur); 1129 (rxtid->hold_q_sz - 2 - cur);
1129 1130
1130 aggr_deque_frms(agg_info, tid, st, 0); 1131 aggr_deque_frms(agg_conn, tid, st, 0);
1131 } 1132 }
1132 1133
1133 stats->num_oow++; 1134 stats->num_oow++;
@@ -1166,7 +1167,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
1166 1167
1167 spin_unlock_bh(&rxtid->lock); 1168 spin_unlock_bh(&rxtid->lock);
1168 1169
1169 aggr_deque_frms(agg_info, tid, 0, 1); 1170 aggr_deque_frms(agg_conn, tid, 0, 1);
1170 1171
1171 if (agg_conn->timer_scheduled) 1172 if (agg_conn->timer_scheduled)
1172 rxtid->progress = true; 1173 rxtid->progress = true;
@@ -1278,6 +1279,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
1278 struct sk_buff *skb1 = NULL; 1279 struct sk_buff *skb1 = NULL;
1279 struct ethhdr *datap = NULL; 1280 struct ethhdr *datap = NULL;
1280 struct ath6kl_vif *vif; 1281 struct ath6kl_vif *vif;
1282 struct aggr_info_conn *aggr_conn;
1281 u16 seq_no, offset; 1283 u16 seq_no, offset;
1282 u8 tid, if_idx; 1284 u8 tid, if_idx;
1283 1285
@@ -1529,11 +1531,21 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
1529 1531
1530 datap = (struct ethhdr *) skb->data; 1532 datap = (struct ethhdr *) skb->data;
1531 1533
1532 if (is_unicast_ether_addr(datap->h_dest) && 1534 if (is_unicast_ether_addr(datap->h_dest)) {
1533 aggr_process_recv_frm(vif->aggr_cntxt, tid, seq_no, 1535 if (vif->nw_type == AP_NETWORK) {
1534 is_amsdu, skb)) 1536 conn = ath6kl_find_sta(vif, datap->h_source);
1535 /* aggregation code will handle the skb */ 1537 if (!conn)
1536 return; 1538 return;
1539 aggr_conn = conn->aggr_conn;
1540 } else
1541 aggr_conn = vif->aggr_cntxt->aggr_conn;
1542
1543 if (aggr_process_recv_frm(aggr_conn, tid, seq_no,
1544 is_amsdu, skb)) {
1545 /* aggregation code will handle the skb */
1546 return;
1547 }
1548 }
1537 1549
1538 ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb); 1550 ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb);
1539} 1551}
@@ -1558,7 +1570,7 @@ static void aggr_timeout(unsigned long arg)
1558 rxtid->seq_next, 1570 rxtid->seq_next,
1559 ((rxtid->seq_next + rxtid->hold_q_sz-1) & 1571 ((rxtid->seq_next + rxtid->hold_q_sz-1) &
1560 ATH6KL_MAX_SEQ_NO)); 1572 ATH6KL_MAX_SEQ_NO));
1561 aggr_deque_frms(aggr_conn->aggr_info, i, 0, 0); 1573 aggr_deque_frms(aggr_conn, i, 0, 0);
1562 } 1574 }
1563 1575
1564 aggr_conn->timer_scheduled = false; 1576 aggr_conn->timer_scheduled = false;
@@ -1598,7 +1610,7 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid)
1598 stats = &aggr_conn->stat[tid]; 1610 stats = &aggr_conn->stat[tid];
1599 1611
1600 if (rxtid->aggr) 1612 if (rxtid->aggr)
1601 aggr_deque_frms(aggr_conn->aggr_info, tid, 0, 0); 1613 aggr_deque_frms(aggr_conn, tid, 0, 0);
1602 1614
1603 rxtid->aggr = false; 1615 rxtid->aggr = false;
1604 rxtid->progress = false; 1616 rxtid->progress = false;
@@ -1616,17 +1628,23 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid)
1616void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no, 1628void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no,
1617 u8 win_sz) 1629 u8 win_sz)
1618{ 1630{
1619 struct aggr_info *p_aggr = vif->aggr_cntxt; 1631 struct ath6kl_sta *sta;
1620 struct aggr_info_conn *aggr_conn; 1632 struct aggr_info_conn *aggr_conn = NULL;
1621 struct rxtid *rxtid; 1633 struct rxtid *rxtid;
1622 struct rxtid_stats *stats; 1634 struct rxtid_stats *stats;
1623 u16 hold_q_size; 1635 u16 hold_q_size;
1624 u8 tid; 1636 u8 tid, aid;
1625 1637
1626 if (!p_aggr || !p_aggr->aggr_conn) 1638 if (vif->nw_type == AP_NETWORK) {
1627 return; 1639 aid = ath6kl_get_aid(tid_mux);
1640 sta = ath6kl_find_sta_by_aid(vif->ar, aid);
1641 if (sta)
1642 aggr_conn = sta->aggr_conn;
1643 } else
1644 aggr_conn = vif->aggr_cntxt->aggr_conn;
1628 1645
1629 aggr_conn = p_aggr->aggr_conn; 1646 if (!aggr_conn)
1647 return;
1630 1648
1631 tid = ath6kl_get_tid(tid_mux); 1649 tid = ath6kl_get_tid(tid_mux);
1632 if (tid >= NUM_OF_TIDS) 1650 if (tid >= NUM_OF_TIDS)
@@ -1656,8 +1674,7 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no,
1656 rxtid->aggr = true; 1674 rxtid->aggr = true;
1657} 1675}
1658 1676
1659static void aggr_conn_init(struct ath6kl_vif *vif, 1677void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info_conn *aggr_conn)
1660 struct aggr_info_conn *aggr_conn)
1661{ 1678{
1662 struct rxtid *rxtid; 1679 struct rxtid *rxtid;
1663 u8 i; 1680 u8 i;
@@ -1709,39 +1726,46 @@ struct aggr_info *aggr_init(struct ath6kl_vif *vif)
1709 1726
1710void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid_mux) 1727void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid_mux)
1711{ 1728{
1712 struct aggr_info *p_aggr = vif->aggr_cntxt; 1729 struct ath6kl_sta *sta;
1713 struct rxtid *rxtid; 1730 struct rxtid *rxtid;
1714 struct aggr_info_conn *aggr_conn; 1731 struct aggr_info_conn *aggr_conn = NULL;
1715 u8 tid; 1732 u8 tid, aid;
1733
1734 if (vif->nw_type == AP_NETWORK) {
1735 aid = ath6kl_get_aid(tid_mux);
1736 sta = ath6kl_find_sta_by_aid(vif->ar, aid);
1737 if (sta)
1738 aggr_conn = sta->aggr_conn;
1739 } else
1740 aggr_conn = vif->aggr_cntxt->aggr_conn;
1716 1741
1717 if (!p_aggr || !p_aggr->aggr_conn) 1742 if (!aggr_conn)
1718 return; 1743 return;
1719 1744
1720 tid = ath6kl_get_tid(tid_mux); 1745 tid = ath6kl_get_tid(tid_mux);
1721 if (tid >= NUM_OF_TIDS) 1746 if (tid >= NUM_OF_TIDS)
1722 return; 1747 return;
1723 1748
1724 aggr_conn = p_aggr->aggr_conn;
1725 rxtid = &aggr_conn->rx_tid[tid]; 1749 rxtid = &aggr_conn->rx_tid[tid];
1726 1750
1727 if (rxtid->aggr) 1751 if (rxtid->aggr)
1728 aggr_delete_tid_state(aggr_conn, tid); 1752 aggr_delete_tid_state(aggr_conn, tid);
1729} 1753}
1730 1754
1731void aggr_reset_state(struct aggr_info *aggr_info) 1755void aggr_reset_state(struct aggr_info_conn *aggr_conn)
1732{ 1756{
1733 u8 tid; 1757 u8 tid;
1734 1758
1735 if (!aggr_info || !aggr_info->aggr_conn) 1759 if (!aggr_conn)
1736 return; 1760 return;
1737 1761
1738 if (aggr_info->aggr_conn->timer_scheduled) { 1762 if (aggr_conn->timer_scheduled) {
1739 del_timer(&aggr_info->aggr_conn->timer); 1763 del_timer(&aggr_conn->timer);
1740 aggr_info->aggr_conn->timer_scheduled = false; 1764 aggr_conn->timer_scheduled = false;
1741 } 1765 }
1742 1766
1743 for (tid = 0; tid < NUM_OF_TIDS; tid++) 1767 for (tid = 0; tid < NUM_OF_TIDS; tid++)
1744 aggr_delete_tid_state(aggr_info->aggr_conn, tid); 1768 aggr_delete_tid_state(aggr_conn, tid);
1745} 1769}
1746 1770
1747/* clean up our amsdu buffer list */ 1771/* clean up our amsdu buffer list */
@@ -1768,10 +1792,10 @@ void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar)
1768 1792
1769void aggr_module_destroy(struct aggr_info *aggr_info) 1793void aggr_module_destroy(struct aggr_info *aggr_info)
1770{ 1794{
1771 if (!aggr_info || !aggr_info->aggr_conn) 1795 if (!aggr_info)
1772 return; 1796 return;
1773 1797
1774 aggr_reset_state(aggr_info); 1798 aggr_reset_state(aggr_info->aggr_conn);
1775 skb_queue_purge(&aggr_info->rx_amsdu_freeq); 1799 skb_queue_purge(&aggr_info->rx_amsdu_freeq);
1776 kfree(aggr_info->aggr_conn); 1800 kfree(aggr_info->aggr_conn);
1777 kfree(aggr_info); 1801 kfree(aggr_info);