aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>2012-01-21 04:52:50 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2012-01-24 07:12:27 -0500
commit7baef812eb5f02ccacf6fac3888c1cfa36293e91 (patch)
treee7052ede90f2068eec52d57e647f586d658b5179 /drivers/net/wireless/ath
parent0e7de662bcf33567cc957995c38dc10959cc22bf (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.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h11
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c166
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
2695static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) 2695static 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
245struct aggr_info { 245struct 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
255struct aggr_info {
256 struct aggr_info_conn *aggr_conn;
257 struct sk_buff_head rx_amsdu_freeq;
253}; 258};
254 259
255struct ath6kl_wep_key { 260struct ath6kl_wep_key {
@@ -707,7 +712,7 @@ struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar);
707void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); 712void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie);
708int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); 713int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev);
709 714
710struct aggr_info *aggr_init(struct net_device *dev); 715struct aggr_info *aggr_init(struct ath6kl_vif *vif);
711void ath6kl_rx_refill(struct htc_target *target, 716void ath6kl_rx_refill(struct htc_target *target,
712 enum htc_endpoint_id endpoint); 717 enum htc_endpoint_id endpoint);
713void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); 718void 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
1054static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, 1058static 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)
1525static void aggr_timeout(unsigned long arg) 1530static 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
1573static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid) 1578static 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
1635struct aggr_info *aggr_init(struct net_device *dev) 1643static 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
1669struct 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
1684void aggr_reset_state(struct aggr_info *aggr_info) 1710void 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
1719void aggr_module_destroy(struct aggr_info *aggr_info) 1748void 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}