int i;
for (i = 0; i < tid_rx->buf_size; i++)
- __skb_queue_purge(&tid_rx->reorder_buf[i]);
- kfree(tid_rx->reorder_buf);
- kfree(tid_rx->reorder_time);
+ __skb_queue_purge(&tid_rx->reorder[i].buf);
kfree(tid_rx);
}
}
/* prepare A-MPDU MLME for Rx aggregation */
- tid_agg_rx = kzalloc_obj(*tid_agg_rx);
+ tid_agg_rx = kzalloc_flex(*tid_agg_rx, reorder, buf_size);
if (!tid_agg_rx)
goto end;
timer_setup(&tid_agg_rx->reorder_timer,
sta_rx_agg_reorder_timer_expired, 0);
- /* prepare reordering buffer */
- tid_agg_rx->reorder_buf =
- kzalloc_objs(struct sk_buff_head, buf_size);
- tid_agg_rx->reorder_time =
- kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
- if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
- kfree(tid_agg_rx->reorder_buf);
- kfree(tid_agg_rx->reorder_time);
- kfree(tid_agg_rx);
- goto end;
- }
-
for (i = 0; i < buf_size; i++)
- __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
+ __skb_queue_head_init(&tid_agg_rx->reorder[i].buf);
ret = drv_ampdu_action(local, sta->sdata, ¶ms);
ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
sta->sta.addr, tid, ret);
if (ret) {
- kfree(tid_agg_rx->reorder_buf);
- kfree(tid_agg_rx->reorder_time);
kfree(tid_agg_rx);
goto end;
}
static inline bool ieee80211_rx_reorder_ready(struct tid_ampdu_rx *tid_agg_rx,
int index)
{
- struct sk_buff_head *frames = &tid_agg_rx->reorder_buf[index];
+ struct sk_buff_head *frames = &tid_agg_rx->reorder[index].buf;
struct sk_buff *tail = skb_peek_tail(frames);
struct ieee80211_rx_status *status;
int index,
struct sk_buff_head *frames)
{
- struct sk_buff_head *skb_list = &tid_agg_rx->reorder_buf[index];
+ struct sk_buff_head *skb_list = &tid_agg_rx->reorder[index].buf;
struct sk_buff *skb;
struct ieee80211_rx_status *status;
continue;
}
if (skipped &&
- !time_after(jiffies, tid_agg_rx->reorder_time[j] +
+ !time_after(jiffies, tid_agg_rx->reorder[j].time +
HT_RX_REORDER_BUF_TIMEOUT))
goto set_release_timer;
/* don't leave incomplete A-MSDUs around */
for (i = (index + 1) % tid_agg_rx->buf_size; i != j;
i = (i + 1) % tid_agg_rx->buf_size)
- __skb_queue_purge(&tid_agg_rx->reorder_buf[i]);
+ __skb_queue_purge(&tid_agg_rx->reorder[i].buf);
ht_dbg_ratelimited(sdata,
"release an RX reorder frame due to timeout on earlier frames\n");
if (!tid_agg_rx->removed)
mod_timer(&tid_agg_rx->reorder_timer,
- tid_agg_rx->reorder_time[j] + 1 +
+ tid_agg_rx->reorder[j].time + 1 +
HT_RX_REORDER_BUF_TIMEOUT);
} else {
timer_delete(&tid_agg_rx->reorder_timer);
}
/* put the frame in the reordering buffer */
- __skb_queue_tail(&tid_agg_rx->reorder_buf[index], skb);
+ __skb_queue_tail(&tid_agg_rx->reorder[index].buf, skb);
if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
- tid_agg_rx->reorder_time[index] = jiffies;
+ tid_agg_rx->reorder[index].time = jiffies;
tid_agg_rx->stored_mpdu_num++;
ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames);
}
/**
* struct tid_ampdu_rx - TID aggregation information (Rx).
*
- * @reorder_buf: buffer to reorder incoming aggregated MPDUs. An MPDU may be an
- * A-MSDU with individually reported subframes.
* @reorder_buf_filtered: bitmap indicating where there are filtered frames in
* the reorder buffer that should be ignored when releasing frames
- * @reorder_time: jiffies when skb was added
* @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
* @reorder_timer: releases expired frames from the reorder buffer.
* @sta: station we are attached to
* and ssn.
* @removed: this session is removed (but might have been found due to RCU)
* @started: this session has started (head ssn or higher was received)
+ * @reorder: reorder buffer entries
+ * @reorder.buf: &struct sk_buff_head for the frames, since there could be
+ * multiple at each entry from an A-MSDU reported as individual subframes
+ * @reorder.time: time when this entry was filled (jiffies)
*
* This structure's lifetime is managed by RCU, assignments to
* the array holding it must hold the aggregation mutex.
struct rcu_head rcu_head;
spinlock_t reorder_lock;
u64 reorder_buf_filtered;
- struct sk_buff_head *reorder_buf;
- unsigned long *reorder_time;
struct sta_info *sta;
struct timer_list session_timer;
struct timer_list reorder_timer;
u8 auto_seq:1,
removed:1,
started:1;
+ struct {
+ struct sk_buff_head buf;
+ unsigned long time;
+ } reorder[];
};
/**