diff options
author | Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> | 2012-01-21 04:52:50 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2012-01-24 07:12:27 -0500 |
commit | 7baef812eb5f02ccacf6fac3888c1cfa36293e91 (patch) | |
tree | e7052ede90f2068eec52d57e647f586d658b5179 /drivers/net/wireless/ath | |
parent | 0e7de662bcf33567cc957995c38dc10959cc22bf (diff) |
ath6kl: Define a structure for connection specific aggregation information
This patch just groups connection specific aggregation information
from struct aggr_info into a new structure (struct aggr_info_conn)
so that, in softAP mode, this can be used when each connected station
is made to have it's own aggregation state.
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/txrx.c | 166 |
3 files changed, 98 insertions, 81 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 594d246da8e1..8bf447a6a84e 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -2694,7 +2694,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar) | |||
2694 | 2694 | ||
2695 | static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) | 2695 | static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) |
2696 | { | 2696 | { |
2697 | vif->aggr_cntxt = aggr_init(vif->ndev); | 2697 | vif->aggr_cntxt = aggr_init(vif); |
2698 | if (!vif->aggr_cntxt) { | 2698 | if (!vif->aggr_cntxt) { |
2699 | ath6kl_err("failed to initialize aggr\n"); | 2699 | ath6kl_err("failed to initialize aggr\n"); |
2700 | return -ENOMEM; | 2700 | return -ENOMEM; |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 67b22e4bbcc2..1b9054f8f4e4 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -242,14 +242,19 @@ struct rxtid_stats { | |||
242 | u32 num_bar; | 242 | u32 num_bar; |
243 | }; | 243 | }; |
244 | 244 | ||
245 | struct aggr_info { | 245 | struct aggr_info_conn { |
246 | u8 aggr_sz; | 246 | u8 aggr_sz; |
247 | u8 timer_scheduled; | 247 | u8 timer_scheduled; |
248 | struct timer_list timer; | 248 | struct timer_list timer; |
249 | struct net_device *dev; | 249 | struct net_device *dev; |
250 | struct rxtid rx_tid[NUM_OF_TIDS]; | 250 | struct rxtid rx_tid[NUM_OF_TIDS]; |
251 | struct sk_buff_head free_q; | ||
252 | struct rxtid_stats stat[NUM_OF_TIDS]; | 251 | struct rxtid_stats stat[NUM_OF_TIDS]; |
252 | struct aggr_info *aggr_info; | ||
253 | }; | ||
254 | |||
255 | struct aggr_info { | ||
256 | struct aggr_info_conn *aggr_conn; | ||
257 | struct sk_buff_head rx_amsdu_freeq; | ||
253 | }; | 258 | }; |
254 | 259 | ||
255 | struct ath6kl_wep_key { | 260 | struct ath6kl_wep_key { |
@@ -707,7 +712,7 @@ struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar); | |||
707 | void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); | 712 | void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); |
708 | int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); | 713 | int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); |
709 | 714 | ||
710 | struct aggr_info *aggr_init(struct net_device *dev); | 715 | struct aggr_info *aggr_init(struct ath6kl_vif *vif); |
711 | void ath6kl_rx_refill(struct htc_target *target, | 716 | void ath6kl_rx_refill(struct htc_target *target, |
712 | enum htc_endpoint_id endpoint); | 717 | enum htc_endpoint_id endpoint); |
713 | void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); | 718 | void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); |
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index cb7421a31619..8407d0103dcd 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -819,10 +819,12 @@ static struct sk_buff *aggr_get_free_skb(struct aggr_info *p_aggr) | |||
819 | { | 819 | { |
820 | struct sk_buff *skb = NULL; | 820 | struct sk_buff *skb = NULL; |
821 | 821 | ||
822 | if (skb_queue_len(&p_aggr->free_q) < (AGGR_NUM_OF_FREE_NETBUFS >> 2)) | 822 | if (skb_queue_len(&p_aggr->rx_amsdu_freeq) < |
823 | ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS); | 823 | (AGGR_NUM_OF_FREE_NETBUFS >> 2)) |
824 | ath6kl_alloc_netbufs(&p_aggr->rx_amsdu_freeq, | ||
825 | AGGR_NUM_OF_FREE_NETBUFS); | ||
824 | 826 | ||
825 | skb = skb_dequeue(&p_aggr->free_q); | 827 | skb = skb_dequeue(&p_aggr->rx_amsdu_freeq); |
826 | 828 | ||
827 | return skb; | 829 | return skb; |
828 | } | 830 | } |
@@ -998,12 +1000,14 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, | |||
998 | struct skb_hold_q *node; | 1000 | struct skb_hold_q *node; |
999 | u16 idx, idx_end, seq_end; | 1001 | u16 idx, idx_end, seq_end; |
1000 | struct rxtid_stats *stats; | 1002 | struct rxtid_stats *stats; |
1003 | struct aggr_info_conn *agg_conn; | ||
1001 | 1004 | ||
1002 | if (!p_aggr) | 1005 | if (!p_aggr || !p_aggr->aggr_conn) |
1003 | return; | 1006 | return; |
1004 | 1007 | ||
1005 | rxtid = &p_aggr->rx_tid[tid]; | 1008 | agg_conn = p_aggr->aggr_conn; |
1006 | stats = &p_aggr->stat[tid]; | 1009 | rxtid = &agg_conn->rx_tid[tid]; |
1010 | stats = &agg_conn->stat[tid]; | ||
1007 | 1011 | ||
1008 | idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); | 1012 | idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); |
1009 | 1013 | ||
@@ -1048,7 +1052,7 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, | |||
1048 | stats->num_delivered += skb_queue_len(&rxtid->q); | 1052 | stats->num_delivered += skb_queue_len(&rxtid->q); |
1049 | 1053 | ||
1050 | while ((skb = skb_dequeue(&rxtid->q))) | 1054 | while ((skb = skb_dequeue(&rxtid->q))) |
1051 | ath6kl_deliver_frames_to_nw_stack(p_aggr->dev, skb); | 1055 | ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, skb); |
1052 | } | 1056 | } |
1053 | 1057 | ||
1054 | static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | 1058 | static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, |
@@ -1062,9 +1066,10 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
1062 | u16 idx, st, cur, end; | 1066 | u16 idx, st, cur, end; |
1063 | bool is_queued = false; | 1067 | bool is_queued = false; |
1064 | u16 extended_end; | 1068 | u16 extended_end; |
1069 | struct aggr_info_conn *agg_conn = agg_info->aggr_conn; | ||
1065 | 1070 | ||
1066 | rxtid = &agg_info->rx_tid[tid]; | 1071 | rxtid = &agg_conn->rx_tid[tid]; |
1067 | stats = &agg_info->stat[tid]; | 1072 | stats = &agg_conn->stat[tid]; |
1068 | 1073 | ||
1069 | stats->num_into_aggr++; | 1074 | stats->num_into_aggr++; |
1070 | 1075 | ||
@@ -1074,7 +1079,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
1074 | is_queued = true; | 1079 | is_queued = true; |
1075 | stats->num_amsdu++; | 1080 | stats->num_amsdu++; |
1076 | while ((skb = skb_dequeue(&rxtid->q))) | 1081 | while ((skb = skb_dequeue(&rxtid->q))) |
1077 | ath6kl_deliver_frames_to_nw_stack(agg_info->dev, | 1082 | ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, |
1078 | skb); | 1083 | skb); |
1079 | } | 1084 | } |
1080 | return is_queued; | 1085 | return is_queued; |
@@ -1152,7 +1157,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
1152 | 1157 | ||
1153 | aggr_deque_frms(agg_info, tid, 0, 1); | 1158 | aggr_deque_frms(agg_info, tid, 0, 1); |
1154 | 1159 | ||
1155 | if (agg_info->timer_scheduled) | 1160 | if (agg_conn->timer_scheduled) |
1156 | rxtid->progress = true; | 1161 | rxtid->progress = true; |
1157 | else | 1162 | else |
1158 | for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { | 1163 | for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { |
@@ -1163,8 +1168,8 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
1163 | * the frame doesn't remain stuck | 1168 | * the frame doesn't remain stuck |
1164 | * forever. | 1169 | * forever. |
1165 | */ | 1170 | */ |
1166 | agg_info->timer_scheduled = true; | 1171 | agg_conn->timer_scheduled = true; |
1167 | mod_timer(&agg_info->timer, | 1172 | mod_timer(&agg_conn->timer, |
1168 | (jiffies + | 1173 | (jiffies + |
1169 | HZ * (AGGR_RX_TIMEOUT) / 1000)); | 1174 | HZ * (AGGR_RX_TIMEOUT) / 1000)); |
1170 | rxtid->progress = false; | 1175 | rxtid->progress = false; |
@@ -1525,13 +1530,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1525 | static void aggr_timeout(unsigned long arg) | 1530 | static void aggr_timeout(unsigned long arg) |
1526 | { | 1531 | { |
1527 | u8 i, j; | 1532 | u8 i, j; |
1528 | struct aggr_info *p_aggr = (struct aggr_info *) arg; | 1533 | struct aggr_info_conn *aggr_conn = (struct aggr_info_conn *) arg; |
1529 | struct rxtid *rxtid; | 1534 | struct rxtid *rxtid; |
1530 | struct rxtid_stats *stats; | 1535 | struct rxtid_stats *stats; |
1531 | 1536 | ||
1532 | for (i = 0; i < NUM_OF_TIDS; i++) { | 1537 | for (i = 0; i < NUM_OF_TIDS; i++) { |
1533 | rxtid = &p_aggr->rx_tid[i]; | 1538 | rxtid = &aggr_conn->rx_tid[i]; |
1534 | stats = &p_aggr->stat[i]; | 1539 | stats = &aggr_conn->stat[i]; |
1535 | 1540 | ||
1536 | if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) | 1541 | if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) |
1537 | continue; | 1542 | continue; |
@@ -1542,18 +1547,18 @@ static void aggr_timeout(unsigned long arg) | |||
1542 | rxtid->seq_next, | 1547 | rxtid->seq_next, |
1543 | ((rxtid->seq_next + rxtid->hold_q_sz-1) & | 1548 | ((rxtid->seq_next + rxtid->hold_q_sz-1) & |
1544 | ATH6KL_MAX_SEQ_NO)); | 1549 | ATH6KL_MAX_SEQ_NO)); |
1545 | aggr_deque_frms(p_aggr, i, 0, 0); | 1550 | aggr_deque_frms(aggr_conn->aggr_info, i, 0, 0); |
1546 | } | 1551 | } |
1547 | 1552 | ||
1548 | p_aggr->timer_scheduled = false; | 1553 | aggr_conn->timer_scheduled = false; |
1549 | 1554 | ||
1550 | for (i = 0; i < NUM_OF_TIDS; i++) { | 1555 | for (i = 0; i < NUM_OF_TIDS; i++) { |
1551 | rxtid = &p_aggr->rx_tid[i]; | 1556 | rxtid = &aggr_conn->rx_tid[i]; |
1552 | 1557 | ||
1553 | if (rxtid->aggr && rxtid->hold_q) { | 1558 | if (rxtid->aggr && rxtid->hold_q) { |
1554 | for (j = 0; j < rxtid->hold_q_sz; j++) { | 1559 | for (j = 0; j < rxtid->hold_q_sz; j++) { |
1555 | if (rxtid->hold_q[j].skb) { | 1560 | if (rxtid->hold_q[j].skb) { |
1556 | p_aggr->timer_scheduled = true; | 1561 | aggr_conn->timer_scheduled = true; |
1557 | rxtid->timer_mon = true; | 1562 | rxtid->timer_mon = true; |
1558 | rxtid->progress = false; | 1563 | rxtid->progress = false; |
1559 | break; | 1564 | break; |
@@ -1565,24 +1570,24 @@ static void aggr_timeout(unsigned long arg) | |||
1565 | } | 1570 | } |
1566 | } | 1571 | } |
1567 | 1572 | ||
1568 | if (p_aggr->timer_scheduled) | 1573 | if (aggr_conn->timer_scheduled) |
1569 | mod_timer(&p_aggr->timer, | 1574 | mod_timer(&aggr_conn->timer, |
1570 | jiffies + msecs_to_jiffies(AGGR_RX_TIMEOUT)); | 1575 | jiffies + msecs_to_jiffies(AGGR_RX_TIMEOUT)); |
1571 | } | 1576 | } |
1572 | 1577 | ||
1573 | static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid) | 1578 | static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) |
1574 | { | 1579 | { |
1575 | struct rxtid *rxtid; | 1580 | struct rxtid *rxtid; |
1576 | struct rxtid_stats *stats; | 1581 | struct rxtid_stats *stats; |
1577 | 1582 | ||
1578 | if (!p_aggr || tid >= NUM_OF_TIDS) | 1583 | if (!aggr_conn || tid >= NUM_OF_TIDS) |
1579 | return; | 1584 | return; |
1580 | 1585 | ||
1581 | rxtid = &p_aggr->rx_tid[tid]; | 1586 | rxtid = &aggr_conn->rx_tid[tid]; |
1582 | stats = &p_aggr->stat[tid]; | 1587 | stats = &aggr_conn->stat[tid]; |
1583 | 1588 | ||
1584 | if (rxtid->aggr) | 1589 | if (rxtid->aggr) |
1585 | aggr_deque_frms(p_aggr, tid, 0, 0); | 1590 | aggr_deque_frms(aggr_conn->aggr_info, tid, 0, 0); |
1586 | 1591 | ||
1587 | rxtid->aggr = false; | 1592 | rxtid->aggr = false; |
1588 | rxtid->progress = false; | 1593 | rxtid->progress = false; |
@@ -1601,22 +1606,25 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, | |||
1601 | u8 win_sz) | 1606 | u8 win_sz) |
1602 | { | 1607 | { |
1603 | struct aggr_info *p_aggr = vif->aggr_cntxt; | 1608 | struct aggr_info *p_aggr = vif->aggr_cntxt; |
1609 | struct aggr_info_conn *aggr_conn; | ||
1604 | struct rxtid *rxtid; | 1610 | struct rxtid *rxtid; |
1605 | struct rxtid_stats *stats; | 1611 | struct rxtid_stats *stats; |
1606 | u16 hold_q_size; | 1612 | u16 hold_q_size; |
1607 | 1613 | ||
1608 | if (!p_aggr) | 1614 | if (!p_aggr || !p_aggr->aggr_conn) |
1609 | return; | 1615 | return; |
1610 | 1616 | ||
1611 | rxtid = &p_aggr->rx_tid[tid]; | 1617 | aggr_conn = p_aggr->aggr_conn; |
1612 | stats = &p_aggr->stat[tid]; | 1618 | |
1619 | rxtid = &aggr_conn->rx_tid[tid]; | ||
1620 | stats = &aggr_conn->stat[tid]; | ||
1613 | 1621 | ||
1614 | if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) | 1622 | if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) |
1615 | ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n", | 1623 | ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n", |
1616 | __func__, win_sz, tid); | 1624 | __func__, win_sz, tid); |
1617 | 1625 | ||
1618 | if (rxtid->aggr) | 1626 | if (rxtid->aggr) |
1619 | aggr_delete_tid_state(p_aggr, tid); | 1627 | aggr_delete_tid_state(aggr_conn, tid); |
1620 | 1628 | ||
1621 | rxtid->seq_next = seq_no; | 1629 | rxtid->seq_next = seq_no; |
1622 | hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q); | 1630 | hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q); |
@@ -1632,31 +1640,23 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, | |||
1632 | rxtid->aggr = true; | 1640 | rxtid->aggr = true; |
1633 | } | 1641 | } |
1634 | 1642 | ||
1635 | struct aggr_info *aggr_init(struct net_device *dev) | 1643 | static void aggr_conn_init(struct ath6kl_vif *vif, |
1644 | struct aggr_info_conn *aggr_conn) | ||
1636 | { | 1645 | { |
1637 | struct aggr_info *p_aggr = NULL; | ||
1638 | struct rxtid *rxtid; | 1646 | struct rxtid *rxtid; |
1639 | u8 i; | 1647 | u8 i; |
1640 | 1648 | ||
1641 | p_aggr = kzalloc(sizeof(struct aggr_info), GFP_KERNEL); | 1649 | aggr_conn->aggr_sz = AGGR_SZ_DEFAULT; |
1642 | if (!p_aggr) { | 1650 | aggr_conn->dev = vif->ndev; |
1643 | ath6kl_err("failed to alloc memory for aggr_node\n"); | 1651 | init_timer(&aggr_conn->timer); |
1644 | return NULL; | 1652 | aggr_conn->timer.function = aggr_timeout; |
1645 | } | 1653 | aggr_conn->timer.data = (unsigned long) aggr_conn; |
1646 | 1654 | aggr_conn->aggr_info = vif->aggr_cntxt; | |
1647 | p_aggr->aggr_sz = AGGR_SZ_DEFAULT; | ||
1648 | p_aggr->dev = dev; | ||
1649 | init_timer(&p_aggr->timer); | ||
1650 | p_aggr->timer.function = aggr_timeout; | ||
1651 | p_aggr->timer.data = (unsigned long) p_aggr; | ||
1652 | |||
1653 | p_aggr->timer_scheduled = false; | ||
1654 | skb_queue_head_init(&p_aggr->free_q); | ||
1655 | 1655 | ||
1656 | ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS); | 1656 | aggr_conn->timer_scheduled = false; |
1657 | 1657 | ||
1658 | for (i = 0; i < NUM_OF_TIDS; i++) { | 1658 | for (i = 0; i < NUM_OF_TIDS; i++) { |
1659 | rxtid = &p_aggr->rx_tid[i]; | 1659 | rxtid = &aggr_conn->rx_tid[i]; |
1660 | rxtid->aggr = false; | 1660 | rxtid->aggr = false; |
1661 | rxtid->progress = false; | 1661 | rxtid->progress = false; |
1662 | rxtid->timer_mon = false; | 1662 | rxtid->timer_mon = false; |
@@ -1664,6 +1664,30 @@ struct aggr_info *aggr_init(struct net_device *dev) | |||
1664 | spin_lock_init(&rxtid->lock); | 1664 | spin_lock_init(&rxtid->lock); |
1665 | } | 1665 | } |
1666 | 1666 | ||
1667 | } | ||
1668 | |||
1669 | struct aggr_info *aggr_init(struct ath6kl_vif *vif) | ||
1670 | { | ||
1671 | struct aggr_info *p_aggr = NULL; | ||
1672 | |||
1673 | p_aggr = kzalloc(sizeof(struct aggr_info), GFP_KERNEL); | ||
1674 | if (!p_aggr) { | ||
1675 | ath6kl_err("failed to alloc memory for aggr_node\n"); | ||
1676 | return NULL; | ||
1677 | } | ||
1678 | |||
1679 | p_aggr->aggr_conn = kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL); | ||
1680 | if (!p_aggr->aggr_conn) { | ||
1681 | ath6kl_err("failed to alloc memory for connection specific aggr info\n"); | ||
1682 | kfree(p_aggr); | ||
1683 | return NULL; | ||
1684 | } | ||
1685 | |||
1686 | aggr_conn_init(vif, p_aggr->aggr_conn); | ||
1687 | |||
1688 | skb_queue_head_init(&p_aggr->rx_amsdu_freeq); | ||
1689 | ath6kl_alloc_netbufs(&p_aggr->rx_amsdu_freeq, AGGR_NUM_OF_FREE_NETBUFS); | ||
1690 | |||
1667 | return p_aggr; | 1691 | return p_aggr; |
1668 | } | 1692 | } |
1669 | 1693 | ||
@@ -1671,27 +1695,32 @@ void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid) | |||
1671 | { | 1695 | { |
1672 | struct aggr_info *p_aggr = vif->aggr_cntxt; | 1696 | struct aggr_info *p_aggr = vif->aggr_cntxt; |
1673 | struct rxtid *rxtid; | 1697 | struct rxtid *rxtid; |
1698 | struct aggr_info_conn *aggr_conn; | ||
1674 | 1699 | ||
1675 | if (!p_aggr) | 1700 | if (!p_aggr || !p_aggr->aggr_conn) |
1676 | return; | 1701 | return; |
1677 | 1702 | ||
1678 | rxtid = &p_aggr->rx_tid[tid]; | 1703 | aggr_conn = p_aggr->aggr_conn; |
1704 | rxtid = &aggr_conn->rx_tid[tid]; | ||
1679 | 1705 | ||
1680 | if (rxtid->aggr) | 1706 | if (rxtid->aggr) |
1681 | aggr_delete_tid_state(p_aggr, tid); | 1707 | aggr_delete_tid_state(aggr_conn, tid); |
1682 | } | 1708 | } |
1683 | 1709 | ||
1684 | void aggr_reset_state(struct aggr_info *aggr_info) | 1710 | void aggr_reset_state(struct aggr_info *aggr_info) |
1685 | { | 1711 | { |
1686 | u8 tid; | 1712 | u8 tid; |
1687 | 1713 | ||
1688 | if (aggr_info->timer_scheduled) { | 1714 | if (!aggr_info || !aggr_info->aggr_conn) |
1689 | del_timer(&aggr_info->timer); | 1715 | return; |
1690 | aggr_info->timer_scheduled = false; | 1716 | |
1717 | if (aggr_info->aggr_conn->timer_scheduled) { | ||
1718 | del_timer(&aggr_info->aggr_conn->timer); | ||
1719 | aggr_info->aggr_conn->timer_scheduled = false; | ||
1691 | } | 1720 | } |
1692 | 1721 | ||
1693 | for (tid = 0; tid < NUM_OF_TIDS; tid++) | 1722 | for (tid = 0; tid < NUM_OF_TIDS; tid++) |
1694 | aggr_delete_tid_state(aggr_info, tid); | 1723 | aggr_delete_tid_state(aggr_info->aggr_conn, tid); |
1695 | } | 1724 | } |
1696 | 1725 | ||
1697 | /* clean up our amsdu buffer list */ | 1726 | /* clean up our amsdu buffer list */ |
@@ -1718,28 +1747,11 @@ void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar) | |||
1718 | 1747 | ||
1719 | void aggr_module_destroy(struct aggr_info *aggr_info) | 1748 | void aggr_module_destroy(struct aggr_info *aggr_info) |
1720 | { | 1749 | { |
1721 | struct rxtid *rxtid; | 1750 | if (!aggr_info || !aggr_info->aggr_conn) |
1722 | u8 i, k; | ||
1723 | |||
1724 | if (!aggr_info) | ||
1725 | return; | 1751 | return; |
1726 | 1752 | ||
1727 | if (aggr_info->timer_scheduled) { | 1753 | aggr_reset_state(aggr_info); |
1728 | del_timer(&aggr_info->timer); | 1754 | skb_queue_purge(&aggr_info->rx_amsdu_freeq); |
1729 | aggr_info->timer_scheduled = false; | 1755 | kfree(aggr_info->aggr_conn); |
1730 | } | ||
1731 | |||
1732 | for (i = 0; i < NUM_OF_TIDS; i++) { | ||
1733 | rxtid = &aggr_info->rx_tid[i]; | ||
1734 | if (rxtid->hold_q) { | ||
1735 | for (k = 0; k < rxtid->hold_q_sz; k++) | ||
1736 | dev_kfree_skb(rxtid->hold_q[k].skb); | ||
1737 | kfree(rxtid->hold_q); | ||
1738 | } | ||
1739 | |||
1740 | skb_queue_purge(&rxtid->q); | ||
1741 | } | ||
1742 | |||
1743 | skb_queue_purge(&aggr_info->free_q); | ||
1744 | kfree(aggr_info); | 1756 | kfree(aggr_info); |
1745 | } | 1757 | } |