* aid - tid_mux4..tid_mux7
*/
#define ATH6KL_TID_MASK 0xf
+#define ATH6KL_AID_SHIFT 4
static inline u8 ath6kl_get_tid(u8 tid_mux)
{
return tid_mux & ATH6KL_TID_MASK;
}
+static inline u8 ath6kl_get_aid(u8 tid_mux)
+{
+ return tid_mux >> ATH6KL_AID_SHIFT;
+}
+
static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev,
u32 *map_no)
{
dev_kfree_skb(skb);
}
-static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid,
+static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
u16 seq_no, u8 order)
{
struct sk_buff *skb;
struct skb_hold_q *node;
u16 idx, idx_end, seq_end;
struct rxtid_stats *stats;
- struct aggr_info_conn *agg_conn;
- if (!p_aggr || !p_aggr->aggr_conn)
- return;
-
- agg_conn = p_aggr->aggr_conn;
rxtid = &agg_conn->rx_tid[tid];
stats = &agg_conn->stat[tid];
if (node->skb) {
if (node->is_amsdu)
- aggr_slice_amsdu(p_aggr, rxtid, node->skb);
+ aggr_slice_amsdu(agg_conn->aggr_info, rxtid,
+ node->skb);
else
skb_queue_tail(&rxtid->q, node->skb);
node->skb = NULL;
ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, skb);
}
-static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
+static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
u16 seq_no,
bool is_amsdu, struct sk_buff *frame)
{
u16 idx, st, cur, end;
bool is_queued = false;
u16 extended_end;
- struct aggr_info_conn *agg_conn = agg_info->aggr_conn;
rxtid = &agg_conn->rx_tid[tid];
stats = &agg_conn->stat[tid];
if (!rxtid->aggr) {
if (is_amsdu) {
- aggr_slice_amsdu(agg_info, rxtid, frame);
+ aggr_slice_amsdu(agg_conn->aggr_info, rxtid, frame);
is_queued = true;
stats->num_amsdu++;
while ((skb = skb_dequeue(&rxtid->q)))
(cur < end || cur > extended_end)) ||
((end > extended_end) && (cur > extended_end) &&
(cur < end))) {
- aggr_deque_frms(agg_info, tid, 0, 0);
+ aggr_deque_frms(agg_conn, tid, 0, 0);
if (cur >= rxtid->hold_q_sz - 1)
rxtid->seq_next = cur - (rxtid->hold_q_sz - 1);
else
st = ATH6KL_MAX_SEQ_NO -
(rxtid->hold_q_sz - 2 - cur);
- aggr_deque_frms(agg_info, tid, st, 0);
+ aggr_deque_frms(agg_conn, tid, st, 0);
}
stats->num_oow++;
spin_unlock_bh(&rxtid->lock);
- aggr_deque_frms(agg_info, tid, 0, 1);
+ aggr_deque_frms(agg_conn, tid, 0, 1);
if (agg_conn->timer_scheduled)
rxtid->progress = true;
struct sk_buff *skb1 = NULL;
struct ethhdr *datap = NULL;
struct ath6kl_vif *vif;
+ struct aggr_info_conn *aggr_conn;
u16 seq_no, offset;
u8 tid, if_idx;
datap = (struct ethhdr *) skb->data;
- if (is_unicast_ether_addr(datap->h_dest) &&
- aggr_process_recv_frm(vif->aggr_cntxt, tid, seq_no,
- is_amsdu, skb))
- /* aggregation code will handle the skb */
- return;
+ if (is_unicast_ether_addr(datap->h_dest)) {
+ if (vif->nw_type == AP_NETWORK) {
+ conn = ath6kl_find_sta(vif, datap->h_source);
+ if (!conn)
+ return;
+ aggr_conn = conn->aggr_conn;
+ } else
+ aggr_conn = vif->aggr_cntxt->aggr_conn;
+
+ if (aggr_process_recv_frm(aggr_conn, tid, seq_no,
+ is_amsdu, skb)) {
+ /* aggregation code will handle the skb */
+ return;
+ }
+ }
ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb);
}
rxtid->seq_next,
((rxtid->seq_next + rxtid->hold_q_sz-1) &
ATH6KL_MAX_SEQ_NO));
- aggr_deque_frms(aggr_conn->aggr_info, i, 0, 0);
+ aggr_deque_frms(aggr_conn, i, 0, 0);
}
aggr_conn->timer_scheduled = false;
stats = &aggr_conn->stat[tid];
if (rxtid->aggr)
- aggr_deque_frms(aggr_conn->aggr_info, tid, 0, 0);
+ aggr_deque_frms(aggr_conn, tid, 0, 0);
rxtid->aggr = false;
rxtid->progress = false;
void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no,
u8 win_sz)
{
- struct aggr_info *p_aggr = vif->aggr_cntxt;
- struct aggr_info_conn *aggr_conn;
+ struct ath6kl_sta *sta;
+ struct aggr_info_conn *aggr_conn = NULL;
struct rxtid *rxtid;
struct rxtid_stats *stats;
u16 hold_q_size;
- u8 tid;
+ u8 tid, aid;
- if (!p_aggr || !p_aggr->aggr_conn)
- return;
+ if (vif->nw_type == AP_NETWORK) {
+ aid = ath6kl_get_aid(tid_mux);
+ sta = ath6kl_find_sta_by_aid(vif->ar, aid);
+ if (sta)
+ aggr_conn = sta->aggr_conn;
+ } else
+ aggr_conn = vif->aggr_cntxt->aggr_conn;
- aggr_conn = p_aggr->aggr_conn;
+ if (!aggr_conn)
+ return;
tid = ath6kl_get_tid(tid_mux);
if (tid >= NUM_OF_TIDS)
rxtid->aggr = true;
}
-static void aggr_conn_init(struct ath6kl_vif *vif,
- struct aggr_info_conn *aggr_conn)
+void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info_conn *aggr_conn)
{
struct rxtid *rxtid;
u8 i;
void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid_mux)
{
- struct aggr_info *p_aggr = vif->aggr_cntxt;
+ struct ath6kl_sta *sta;
struct rxtid *rxtid;
- struct aggr_info_conn *aggr_conn;
- u8 tid;
+ struct aggr_info_conn *aggr_conn = NULL;
+ u8 tid, aid;
+
+ if (vif->nw_type == AP_NETWORK) {
+ aid = ath6kl_get_aid(tid_mux);
+ sta = ath6kl_find_sta_by_aid(vif->ar, aid);
+ if (sta)
+ aggr_conn = sta->aggr_conn;
+ } else
+ aggr_conn = vif->aggr_cntxt->aggr_conn;
- if (!p_aggr || !p_aggr->aggr_conn)
+ if (!aggr_conn)
return;
tid = ath6kl_get_tid(tid_mux);
if (tid >= NUM_OF_TIDS)
return;
- aggr_conn = p_aggr->aggr_conn;
rxtid = &aggr_conn->rx_tid[tid];
if (rxtid->aggr)
aggr_delete_tid_state(aggr_conn, tid);
}
-void aggr_reset_state(struct aggr_info *aggr_info)
+void aggr_reset_state(struct aggr_info_conn *aggr_conn)
{
u8 tid;
- if (!aggr_info || !aggr_info->aggr_conn)
+ if (!aggr_conn)
return;
- if (aggr_info->aggr_conn->timer_scheduled) {
- del_timer(&aggr_info->aggr_conn->timer);
- aggr_info->aggr_conn->timer_scheduled = false;
+ if (aggr_conn->timer_scheduled) {
+ del_timer(&aggr_conn->timer);
+ aggr_conn->timer_scheduled = false;
}
for (tid = 0; tid < NUM_OF_TIDS; tid++)
- aggr_delete_tid_state(aggr_info->aggr_conn, tid);
+ aggr_delete_tid_state(aggr_conn, tid);
}
/* clean up our amsdu buffer list */
void aggr_module_destroy(struct aggr_info *aggr_info)
{
- if (!aggr_info || !aggr_info->aggr_conn)
+ if (!aggr_info)
return;
- aggr_reset_state(aggr_info);
+ aggr_reset_state(aggr_info->aggr_conn);
skb_queue_purge(&aggr_info->rx_amsdu_freeq);
kfree(aggr_info->aggr_conn);
kfree(aggr_info);