@ -819,10 +819,12 @@ static struct sk_buff *aggr_get_free_skb(struct aggr_info *p_aggr)
{
struct sk_buff * skb = NULL ;
if ( skb_queue_len ( & p_aggr - > free_q ) < ( AGGR_NUM_OF_FREE_NETBUFS > > 2 ) )
ath6kl_alloc_netbufs ( & p_aggr - > free_q , AGGR_NUM_OF_FREE_NETBUFS ) ;
if ( skb_queue_len ( & p_aggr - > rx_amsdu_freeq ) <
( AGGR_NUM_OF_FREE_NETBUFS > > 2 ) )
ath6kl_alloc_netbufs ( & p_aggr - > rx_amsdu_freeq ,
AGGR_NUM_OF_FREE_NETBUFS ) ;
skb = skb_dequeue ( & p_aggr - > free_q ) ;
skb = skb_dequeue ( & p_aggr - > rx_amsdu_ freeq) ;
return skb ;
}
@ -998,12 +1000,14 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid,
struct skb_hold_q * node ;
u16 idx , idx_end , seq_end ;
struct rxtid_stats * stats ;
struct aggr_info_conn * agg_conn ;
if ( ! p_aggr )
if ( ! p_aggr | | ! p_aggr - > aggr_conn )
return ;
rxtid = & p_aggr - > rx_tid [ tid ] ;
stats = & p_aggr - > stat [ tid ] ;
agg_conn = p_aggr - > aggr_conn ;
rxtid = & agg_conn - > rx_tid [ tid ] ;
stats = & agg_conn - > stat [ tid ] ;
idx = AGGR_WIN_IDX ( rxtid - > seq_next , rxtid - > hold_q_sz ) ;
@ -1048,7 +1052,7 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid,
stats - > num_delivered + = skb_queue_len ( & rxtid - > q ) ;
while ( ( skb = skb_dequeue ( & rxtid - > q ) ) )
ath6kl_deliver_frames_to_nw_stack ( p_aggr - > dev , skb ) ;
ath6kl_deliver_frames_to_nw_stack ( agg_conn - > dev , skb ) ;
}
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,
u16 idx , st , cur , end ;
bool is_queued = false ;
u16 extended_end ;
struct aggr_info_conn * agg_conn = agg_info - > aggr_conn ;
rxtid = & agg_info - > rx_tid [ tid ] ;
stats = & agg_info - > stat [ tid ] ;
rxtid = & agg_conn - > rx_tid [ tid ] ;
stats = & agg_conn - > stat [ tid ] ;
stats - > num_into_aggr + + ;
@ -1074,7 +1079,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
is_queued = true ;
stats - > num_amsdu + + ;
while ( ( skb = skb_dequeue ( & rxtid - > q ) ) )
ath6kl_deliver_frames_to_nw_stack ( agg_info - > dev ,
ath6kl_deliver_frames_to_nw_stack ( agg_conn - > dev ,
skb ) ;
}
return is_queued ;
@ -1152,7 +1157,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
aggr_deque_frms ( agg_info , tid , 0 , 1 ) ;
if ( agg_info - > timer_scheduled )
if ( agg_conn - > timer_scheduled )
rxtid - > progress = true ;
else
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,
* the frame doesn ' t remain stuck
* forever .
*/
agg_info - > timer_scheduled = true ;
mod_timer ( & agg_info - > timer ,
agg_conn - > timer_scheduled = true ;
mod_timer ( & agg_conn - > timer ,
( jiffies +
HZ * ( AGGR_RX_TIMEOUT ) / 1000 ) ) ;
rxtid - > progress = false ;
@ -1525,13 +1530,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
static void aggr_timeout ( unsigned long arg )
{
u8 i , j ;
struct aggr_info * p_ aggr = ( struct aggr_info * ) arg ;
struct aggr_info_conn * aggr_conn = ( struct aggr_info_conn * ) arg ;
struct rxtid * rxtid ;
struct rxtid_stats * stats ;
for ( i = 0 ; i < NUM_OF_TIDS ; i + + ) {
rxtid = & p_ aggr- > rx_tid [ i ] ;
stats = & p_ aggr- > stat [ i ] ;
rxtid = & aggr_conn - > rx_tid [ i ] ;
stats = & aggr_conn - > stat [ i ] ;
if ( ! rxtid - > aggr | | ! rxtid - > timer_mon | | rxtid - > progress )
continue ;
@ -1542,18 +1547,18 @@ static void aggr_timeout(unsigned long arg)
rxtid - > seq_next ,
( ( rxtid - > seq_next + rxtid - > hold_q_sz - 1 ) &
ATH6KL_MAX_SEQ_NO ) ) ;
aggr_deque_frms ( p_aggr , i , 0 , 0 ) ;
aggr_deque_frms ( aggr_conn - > aggr_info , i , 0 , 0 ) ;
}
p_ aggr- > timer_scheduled = false ;
aggr_conn - > timer_scheduled = false ;
for ( i = 0 ; i < NUM_OF_TIDS ; i + + ) {
rxtid = & p_ aggr- > rx_tid [ i ] ;
rxtid = & aggr_conn - > rx_tid [ i ] ;
if ( rxtid - > aggr & & rxtid - > hold_q ) {
for ( j = 0 ; j < rxtid - > hold_q_sz ; j + + ) {
if ( rxtid - > hold_q [ j ] . skb ) {
p_ aggr- > timer_scheduled = true ;
aggr_conn - > timer_scheduled = true ;
rxtid - > timer_mon = true ;
rxtid - > progress = false ;
break ;
@ -1565,24 +1570,24 @@ static void aggr_timeout(unsigned long arg)
}
}
if ( p_ aggr- > timer_scheduled )
mod_timer ( & p_ aggr- > timer ,
if ( aggr_conn - > timer_scheduled )
mod_timer ( & aggr_conn - > timer ,
jiffies + msecs_to_jiffies ( AGGR_RX_TIMEOUT ) ) ;
}
static void aggr_delete_tid_state ( struct aggr_info * p_ aggr, u8 tid )
static void aggr_delete_tid_state ( struct aggr_info_conn * aggr_conn , u8 tid )
{
struct rxtid * rxtid ;
struct rxtid_stats * stats ;
if ( ! p_ aggr | | tid > = NUM_OF_TIDS )
if ( ! aggr_conn | | tid > = NUM_OF_TIDS )
return ;
rxtid = & p_ aggr- > rx_tid [ tid ] ;
stats = & p_ aggr- > stat [ tid ] ;
rxtid = & aggr_conn - > rx_tid [ tid ] ;
stats = & aggr_conn - > stat [ tid ] ;
if ( rxtid - > aggr )
aggr_deque_frms ( p_aggr , tid , 0 , 0 ) ;
aggr_deque_frms ( aggr_conn - > aggr_info , tid , 0 , 0 ) ;
rxtid - > aggr = false ;
rxtid - > progress = false ;
@ -1601,22 +1606,25 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
u8 win_sz )
{
struct aggr_info * p_aggr = vif - > aggr_cntxt ;
struct aggr_info_conn * aggr_conn ;
struct rxtid * rxtid ;
struct rxtid_stats * stats ;
u16 hold_q_size ;
if ( ! p_aggr )
if ( ! p_aggr | | ! p_aggr - > aggr_conn )
return ;
rxtid = & p_aggr - > rx_tid [ tid ] ;
stats = & p_aggr - > stat [ tid ] ;
aggr_conn = p_aggr - > aggr_conn ;
rxtid = & aggr_conn - > rx_tid [ tid ] ;
stats = & aggr_conn - > stat [ tid ] ;
if ( win_sz < AGGR_WIN_SZ_MIN | | win_sz > AGGR_WIN_SZ_MAX )
ath6kl_dbg ( ATH6KL_DBG_WLAN_RX , " %s: win_sz %d, tid %d \n " ,
__func__ , win_sz , tid ) ;
if ( rxtid - > aggr )
aggr_delete_tid_state ( p_ aggr, tid ) ;
aggr_delete_tid_state ( aggr_conn , tid ) ;
rxtid - > seq_next = seq_no ;
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,
rxtid - > aggr = true ;
}
struct aggr_info * aggr_init ( struct net_device * dev )
static void aggr_conn_init ( struct ath6kl_vif * vif ,
struct aggr_info_conn * aggr_conn )
{
struct aggr_info * p_aggr = NULL ;
struct rxtid * rxtid ;
u8 i ;
p_aggr = kzalloc ( sizeof ( struct aggr_info ) , GFP_KERNEL ) ;
if ( ! p_aggr ) {
ath6kl_err ( " failed to alloc memory for aggr_node \n " ) ;
return NULL ;
}
p_aggr - > aggr_sz = AGGR_SZ_DEFAULT ;
p_aggr - > dev = dev ;
init_timer ( & p_aggr - > timer ) ;
p_aggr - > timer . function = aggr_timeout ;
p_aggr - > timer . data = ( unsigned long ) p_aggr ;
p_aggr - > timer_scheduled = false ;
skb_queue_head_init ( & p_aggr - > free_q ) ;
aggr_conn - > aggr_sz = AGGR_SZ_DEFAULT ;
aggr_conn - > dev = vif - > ndev ;
init_timer ( & aggr_conn - > timer ) ;
aggr_conn - > timer . function = aggr_timeout ;
aggr_conn - > timer . data = ( unsigned long ) aggr_conn ;
aggr_conn - > aggr_info = vif - > aggr_cntxt ;
ath6kl_alloc_netbufs ( & p_aggr - > free_q , AGGR_NUM_OF_FREE_NETBUFS ) ;
aggr_conn - > timer_scheduled = false ;
for ( i = 0 ; i < NUM_OF_TIDS ; i + + ) {
rxtid = & p_ aggr- > rx_tid [ i ] ;
rxtid = & aggr_conn - > rx_tid [ i ] ;
rxtid - > aggr = false ;
rxtid - > progress = false ;
rxtid - > timer_mon = false ;
@ -1664,6 +1664,30 @@ struct aggr_info *aggr_init(struct net_device *dev)
spin_lock_init ( & rxtid - > lock ) ;
}
}
struct aggr_info * aggr_init ( struct ath6kl_vif * vif )
{
struct aggr_info * p_aggr = NULL ;
p_aggr = kzalloc ( sizeof ( struct aggr_info ) , GFP_KERNEL ) ;
if ( ! p_aggr ) {
ath6kl_err ( " failed to alloc memory for aggr_node \n " ) ;
return NULL ;
}
p_aggr - > aggr_conn = kzalloc ( sizeof ( struct aggr_info_conn ) , GFP_KERNEL ) ;
if ( ! p_aggr - > aggr_conn ) {
ath6kl_err ( " failed to alloc memory for connection specific aggr info \n " ) ;
kfree ( p_aggr ) ;
return NULL ;
}
aggr_conn_init ( vif , p_aggr - > aggr_conn ) ;
skb_queue_head_init ( & p_aggr - > rx_amsdu_freeq ) ;
ath6kl_alloc_netbufs ( & p_aggr - > rx_amsdu_freeq , AGGR_NUM_OF_FREE_NETBUFS ) ;
return p_aggr ;
}
@ -1671,27 +1695,32 @@ void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid)
{
struct aggr_info * p_aggr = vif - > aggr_cntxt ;
struct rxtid * rxtid ;
struct aggr_info_conn * aggr_conn ;
if ( ! p_aggr )
if ( ! p_aggr | | ! p_aggr - > aggr_conn )
return ;
rxtid = & p_aggr - > rx_tid [ tid ] ;
aggr_conn = p_aggr - > aggr_conn ;
rxtid = & aggr_conn - > rx_tid [ tid ] ;
if ( rxtid - > aggr )
aggr_delete_tid_state ( p_ aggr, tid ) ;
aggr_delete_tid_state ( aggr_conn , tid ) ;
}
void aggr_reset_state ( struct aggr_info * aggr_info )
{
u8 tid ;
if ( aggr_info - > timer_scheduled ) {
del_timer ( & aggr_info - > timer ) ;
aggr_info - > timer_scheduled = false ;
if ( ! aggr_info | | ! aggr_info - > aggr_conn )
return ;
if ( aggr_info - > aggr_conn - > timer_scheduled ) {
del_timer ( & aggr_info - > aggr_conn - > timer ) ;
aggr_info - > aggr_conn - > timer_scheduled = false ;
}
for ( tid = 0 ; tid < NUM_OF_TIDS ; tid + + )
aggr_delete_tid_state ( aggr_info , tid ) ;
aggr_delete_tid_state ( aggr_info - > aggr_conn , tid ) ;
}
/* clean up our amsdu buffer list */
@ -1718,28 +1747,11 @@ void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar)
void aggr_module_destroy ( struct aggr_info * aggr_info )
{
struct rxtid * rxtid ;
u8 i , k ;
if ( ! aggr_info )
if ( ! aggr_info | | ! aggr_info - > aggr_conn )
return ;
if ( aggr_info - > timer_scheduled ) {
del_timer ( & aggr_info - > timer ) ;
aggr_info - > timer_scheduled = false ;
}
for ( i = 0 ; i < NUM_OF_TIDS ; i + + ) {
rxtid = & aggr_info - > rx_tid [ i ] ;
if ( rxtid - > hold_q ) {
for ( k = 0 ; k < rxtid - > hold_q_sz ; k + + )
dev_kfree_skb ( rxtid - > hold_q [ k ] . skb ) ;
kfree ( rxtid - > hold_q ) ;
}
skb_queue_purge ( & rxtid - > q ) ;
}
skb_queue_purge ( & aggr_info - > free_q ) ;
aggr_reset_state ( aggr_info ) ;
skb_queue_purge ( & aggr_info - > rx_amsdu_freeq ) ;
kfree ( aggr_info - > aggr_conn ) ;
kfree ( aggr_info ) ;
}