0001
0002
0003
0004
0005
0006
0007
0008 #include "decl.h"
0009 #include "ioctl.h"
0010 #include "util.h"
0011 #include "fw.h"
0012 #include "main.h"
0013 #include "wmm.h"
0014 #include "11n.h"
0015 #include "11n_rxreorder.h"
0016
0017
0018
0019
0020 static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
0021 struct sk_buff *skb)
0022 {
0023 struct rxpd *local_rx_pd = (struct rxpd *)(skb->data);
0024 int ret;
0025
0026 if (le16_to_cpu(local_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) {
0027 struct sk_buff_head list;
0028 struct sk_buff *rx_skb;
0029
0030 __skb_queue_head_init(&list);
0031
0032 skb_pull(skb, le16_to_cpu(local_rx_pd->rx_pkt_offset));
0033 skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
0034
0035 ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
0036 priv->wdev.iftype, 0, NULL, NULL);
0037
0038 while (!skb_queue_empty(&list)) {
0039 struct rx_packet_hdr *rx_hdr;
0040
0041 rx_skb = __skb_dequeue(&list);
0042 rx_hdr = (struct rx_packet_hdr *)rx_skb->data;
0043 if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
0044 ntohs(rx_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
0045 mwifiex_process_tdls_action_frame(priv,
0046 (u8 *)rx_hdr,
0047 skb->len);
0048 }
0049
0050 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
0051 ret = mwifiex_uap_recv_packet(priv, rx_skb);
0052 else
0053 ret = mwifiex_recv_packet(priv, rx_skb);
0054 if (ret == -1)
0055 mwifiex_dbg(priv->adapter, ERROR,
0056 "Rx of A-MSDU failed");
0057 }
0058 return 0;
0059 }
0060
0061 return -1;
0062 }
0063
0064
0065
0066
0067 static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
0068 struct sk_buff *payload)
0069 {
0070
0071 int ret;
0072
0073 if (!payload) {
0074 mwifiex_dbg(priv->adapter, INFO, "info: fw drop data\n");
0075 return 0;
0076 }
0077
0078 ret = mwifiex_11n_dispatch_amsdu_pkt(priv, payload);
0079 if (!ret)
0080 return 0;
0081
0082 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
0083 return mwifiex_handle_uap_rx_forward(priv, payload);
0084
0085 return mwifiex_process_rx_packet(priv, payload);
0086 }
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 static void
0097 mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,
0098 struct mwifiex_rx_reorder_tbl *tbl,
0099 int start_win)
0100 {
0101 struct sk_buff_head list;
0102 struct sk_buff *skb;
0103 int pkt_to_send, i;
0104
0105 __skb_queue_head_init(&list);
0106 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0107
0108 pkt_to_send = (start_win > tbl->start_win) ?
0109 min((start_win - tbl->start_win), tbl->win_size) :
0110 tbl->win_size;
0111
0112 for (i = 0; i < pkt_to_send; ++i) {
0113 if (tbl->rx_reorder_ptr[i]) {
0114 skb = tbl->rx_reorder_ptr[i];
0115 __skb_queue_tail(&list, skb);
0116 tbl->rx_reorder_ptr[i] = NULL;
0117 }
0118 }
0119
0120
0121
0122
0123
0124 for (i = 0; i < tbl->win_size - pkt_to_send; ++i) {
0125 tbl->rx_reorder_ptr[i] = tbl->rx_reorder_ptr[pkt_to_send + i];
0126 tbl->rx_reorder_ptr[pkt_to_send + i] = NULL;
0127 }
0128
0129 tbl->start_win = start_win;
0130 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0131
0132 while ((skb = __skb_dequeue(&list)))
0133 mwifiex_11n_dispatch_pkt(priv, skb);
0134 }
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 static void
0145 mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
0146 struct mwifiex_rx_reorder_tbl *tbl)
0147 {
0148 struct sk_buff_head list;
0149 struct sk_buff *skb;
0150 int i, j, xchg;
0151
0152 __skb_queue_head_init(&list);
0153 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0154
0155 for (i = 0; i < tbl->win_size; ++i) {
0156 if (!tbl->rx_reorder_ptr[i])
0157 break;
0158 skb = tbl->rx_reorder_ptr[i];
0159 __skb_queue_tail(&list, skb);
0160 tbl->rx_reorder_ptr[i] = NULL;
0161 }
0162
0163
0164
0165
0166
0167 if (i > 0) {
0168 xchg = tbl->win_size - i;
0169 for (j = 0; j < xchg; ++j) {
0170 tbl->rx_reorder_ptr[j] = tbl->rx_reorder_ptr[i + j];
0171 tbl->rx_reorder_ptr[i + j] = NULL;
0172 }
0173 }
0174 tbl->start_win = (tbl->start_win + i) & (MAX_TID_VALUE - 1);
0175
0176 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0177
0178 while ((skb = __skb_dequeue(&list)))
0179 mwifiex_11n_dispatch_pkt(priv, skb);
0180 }
0181
0182
0183
0184
0185
0186
0187
0188 static void
0189 mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
0190 struct mwifiex_rx_reorder_tbl *tbl)
0191 {
0192 int start_win;
0193
0194 if (!tbl)
0195 return;
0196
0197 spin_lock_bh(&priv->adapter->rx_proc_lock);
0198 priv->adapter->rx_locked = true;
0199 if (priv->adapter->rx_processing) {
0200 spin_unlock_bh(&priv->adapter->rx_proc_lock);
0201 flush_workqueue(priv->adapter->rx_workqueue);
0202 } else {
0203 spin_unlock_bh(&priv->adapter->rx_proc_lock);
0204 }
0205
0206 start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1);
0207 mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
0208
0209 del_timer_sync(&tbl->timer_context.timer);
0210 tbl->timer_context.timer_is_set = false;
0211
0212 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0213 list_del(&tbl->list);
0214 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0215
0216 kfree(tbl->rx_reorder_ptr);
0217 kfree(tbl);
0218
0219 spin_lock_bh(&priv->adapter->rx_proc_lock);
0220 priv->adapter->rx_locked = false;
0221 spin_unlock_bh(&priv->adapter->rx_proc_lock);
0222
0223 }
0224
0225
0226
0227
0228
0229 struct mwifiex_rx_reorder_tbl *
0230 mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
0231 {
0232 struct mwifiex_rx_reorder_tbl *tbl;
0233
0234 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0235 list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) {
0236 if (!memcmp(tbl->ta, ta, ETH_ALEN) && tbl->tid == tid) {
0237 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0238 return tbl;
0239 }
0240 }
0241 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0242
0243 return NULL;
0244 }
0245
0246
0247
0248
0249 void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
0250 {
0251 struct mwifiex_rx_reorder_tbl *tbl, *tmp;
0252
0253 if (!ta)
0254 return;
0255
0256 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0257 list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) {
0258 if (!memcmp(tbl->ta, ta, ETH_ALEN)) {
0259 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0260 mwifiex_del_rx_reorder_entry(priv, tbl);
0261 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0262 }
0263 }
0264 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0265
0266 return;
0267 }
0268
0269
0270
0271
0272
0273 static int
0274 mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx)
0275 {
0276 struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr;
0277 struct mwifiex_private *priv = ctx->priv;
0278 int i;
0279
0280 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0281 for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) {
0282 if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
0283 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0284 return i;
0285 }
0286 }
0287 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0288
0289 return -1;
0290 }
0291
0292
0293
0294
0295
0296
0297
0298
0299 static void
0300 mwifiex_flush_data(struct timer_list *t)
0301 {
0302 struct reorder_tmr_cnxt *ctx =
0303 from_timer(ctx, t, timer);
0304 int start_win, seq_num;
0305
0306 ctx->timer_is_set = false;
0307 seq_num = mwifiex_11n_find_last_seq_num(ctx);
0308
0309 if (seq_num < 0)
0310 return;
0311
0312 mwifiex_dbg(ctx->priv->adapter, INFO, "info: flush data %d\n", seq_num);
0313 start_win = (ctx->ptr->start_win + seq_num + 1) & (MAX_TID_VALUE - 1);
0314 mwifiex_11n_dispatch_pkt_until_start_win(ctx->priv, ctx->ptr,
0315 start_win);
0316 }
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328 static void
0329 mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
0330 int tid, int win_size, int seq_num)
0331 {
0332 int i;
0333 struct mwifiex_rx_reorder_tbl *tbl, *new_node;
0334 u16 last_seq = 0;
0335 struct mwifiex_sta_node *node;
0336
0337
0338
0339
0340
0341 tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
0342 if (tbl) {
0343 mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, seq_num);
0344 return;
0345 }
0346
0347 new_node = kzalloc(sizeof(struct mwifiex_rx_reorder_tbl), GFP_KERNEL);
0348 if (!new_node)
0349 return;
0350
0351 INIT_LIST_HEAD(&new_node->list);
0352 new_node->tid = tid;
0353 memcpy(new_node->ta, ta, ETH_ALEN);
0354 new_node->start_win = seq_num;
0355 new_node->init_win = seq_num;
0356 new_node->flags = 0;
0357
0358 spin_lock_bh(&priv->sta_list_spinlock);
0359 if (mwifiex_queuing_ra_based(priv)) {
0360 if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
0361 node = mwifiex_get_sta_entry(priv, ta);
0362 if (node)
0363 last_seq = node->rx_seq[tid];
0364 }
0365 } else {
0366 node = mwifiex_get_sta_entry(priv, ta);
0367 if (node)
0368 last_seq = node->rx_seq[tid];
0369 else
0370 last_seq = priv->rx_seq[tid];
0371 }
0372 spin_unlock_bh(&priv->sta_list_spinlock);
0373
0374 mwifiex_dbg(priv->adapter, INFO,
0375 "info: last_seq=%d start_win=%d\n",
0376 last_seq, new_node->start_win);
0377
0378 if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
0379 last_seq >= new_node->start_win) {
0380 new_node->start_win = last_seq + 1;
0381 new_node->flags |= RXREOR_INIT_WINDOW_SHIFT;
0382 }
0383
0384 new_node->win_size = win_size;
0385
0386 new_node->rx_reorder_ptr = kcalloc(win_size, sizeof(void *),
0387 GFP_KERNEL);
0388 if (!new_node->rx_reorder_ptr) {
0389 kfree(new_node);
0390 mwifiex_dbg(priv->adapter, ERROR,
0391 "%s: failed to alloc reorder_ptr\n", __func__);
0392 return;
0393 }
0394
0395 new_node->timer_context.ptr = new_node;
0396 new_node->timer_context.priv = priv;
0397 new_node->timer_context.timer_is_set = false;
0398
0399 timer_setup(&new_node->timer_context.timer, mwifiex_flush_data, 0);
0400
0401 for (i = 0; i < win_size; ++i)
0402 new_node->rx_reorder_ptr[i] = NULL;
0403
0404 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0405 list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr);
0406 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0407 }
0408
0409 static void
0410 mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl)
0411 {
0412 u32 min_flush_time;
0413
0414 if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32)
0415 min_flush_time = MIN_FLUSH_TIMER_15_MS;
0416 else
0417 min_flush_time = MIN_FLUSH_TIMER_MS;
0418
0419 mod_timer(&tbl->timer_context.timer,
0420 jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size));
0421
0422 tbl->timer_context.timer_is_set = true;
0423 }
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433 int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)
0434 {
0435 struct host_cmd_ds_11n_addba_req *add_ba_req = &cmd->params.add_ba_req;
0436
0437 cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_REQ);
0438 cmd->size = cpu_to_le16(sizeof(*add_ba_req) + S_DS_GEN);
0439 memcpy(add_ba_req, data_buf, sizeof(*add_ba_req));
0440
0441 return 0;
0442 }
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
0453 struct host_cmd_ds_command *cmd,
0454 struct host_cmd_ds_11n_addba_req
0455 *cmd_addba_req)
0456 {
0457 struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &cmd->params.add_ba_rsp;
0458 struct mwifiex_sta_node *sta_ptr;
0459 u32 rx_win_size = priv->add_ba_param.rx_win_size;
0460 u8 tid;
0461 int win_size;
0462 uint16_t block_ack_param_set;
0463
0464 if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
0465 ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
0466 priv->adapter->is_hw_11ac_capable &&
0467 memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) {
0468 spin_lock_bh(&priv->sta_list_spinlock);
0469 sta_ptr = mwifiex_get_sta_entry(priv,
0470 cmd_addba_req->peer_mac_addr);
0471 if (!sta_ptr) {
0472 spin_unlock_bh(&priv->sta_list_spinlock);
0473 mwifiex_dbg(priv->adapter, ERROR,
0474 "BA setup with unknown TDLS peer %pM!\n",
0475 cmd_addba_req->peer_mac_addr);
0476 return -1;
0477 }
0478 if (sta_ptr->is_11ac_enabled)
0479 rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
0480 spin_unlock_bh(&priv->sta_list_spinlock);
0481 }
0482
0483 cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
0484 cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN);
0485
0486 memcpy(add_ba_rsp->peer_mac_addr, cmd_addba_req->peer_mac_addr,
0487 ETH_ALEN);
0488 add_ba_rsp->dialog_token = cmd_addba_req->dialog_token;
0489 add_ba_rsp->block_ack_tmo = cmd_addba_req->block_ack_tmo;
0490 add_ba_rsp->ssn = cmd_addba_req->ssn;
0491
0492 block_ack_param_set = le16_to_cpu(cmd_addba_req->block_ack_param_set);
0493 tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
0494 >> BLOCKACKPARAM_TID_POS;
0495 add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT);
0496 block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
0497
0498
0499 if (!priv->add_ba_param.rx_amsdu ||
0500 (priv->aggr_prio_tbl[tid].amsdu == BA_STREAM_NOT_ALLOWED))
0501 block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK;
0502 block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS;
0503 add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set);
0504 win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set)
0505 & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
0506 >> BLOCKACKPARAM_WINSIZE_POS;
0507 cmd_addba_req->block_ack_param_set = cpu_to_le16(block_ack_param_set);
0508
0509 mwifiex_11n_create_rx_reorder_tbl(priv, cmd_addba_req->peer_mac_addr,
0510 tid, win_size,
0511 le16_to_cpu(cmd_addba_req->ssn));
0512 return 0;
0513 }
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523 int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf)
0524 {
0525 struct host_cmd_ds_11n_delba *del_ba = &cmd->params.del_ba;
0526
0527 cmd->command = cpu_to_le16(HostCmd_CMD_11N_DELBA);
0528 cmd->size = cpu_to_le16(sizeof(*del_ba) + S_DS_GEN);
0529 memcpy(del_ba, data_buf, sizeof(*del_ba));
0530
0531 return 0;
0532 }
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547 int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
0548 u16 seq_num, u16 tid,
0549 u8 *ta, u8 pkt_type, void *payload)
0550 {
0551 struct mwifiex_rx_reorder_tbl *tbl;
0552 int prev_start_win, start_win, end_win, win_size;
0553 u16 pkt_index;
0554 bool init_window_shift = false;
0555 int ret = 0;
0556
0557 tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
0558 if (!tbl) {
0559 if (pkt_type != PKT_TYPE_BAR)
0560 mwifiex_11n_dispatch_pkt(priv, payload);
0561 return ret;
0562 }
0563
0564 if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
0565 mwifiex_11n_dispatch_pkt(priv, payload);
0566 return ret;
0567 }
0568
0569 start_win = tbl->start_win;
0570 prev_start_win = start_win;
0571 win_size = tbl->win_size;
0572 end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
0573 if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) {
0574 init_window_shift = true;
0575 tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT;
0576 }
0577
0578 if (tbl->flags & RXREOR_FORCE_NO_DROP) {
0579 mwifiex_dbg(priv->adapter, INFO,
0580 "RXREOR_FORCE_NO_DROP when HS is activated\n");
0581 tbl->flags &= ~RXREOR_FORCE_NO_DROP;
0582 } else if (init_window_shift && seq_num < start_win &&
0583 seq_num >= tbl->init_win) {
0584 mwifiex_dbg(priv->adapter, INFO,
0585 "Sender TID sequence number reset %d->%d for SSN %d\n",
0586 start_win, seq_num, tbl->init_win);
0587 tbl->start_win = start_win = seq_num;
0588 end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
0589 } else {
0590
0591
0592
0593
0594 if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
0595 if (seq_num >= ((start_win + TWOPOW11) &
0596 (MAX_TID_VALUE - 1)) &&
0597 seq_num < start_win) {
0598 ret = -1;
0599 goto done;
0600 }
0601 } else if ((seq_num < start_win) ||
0602 (seq_num >= (start_win + TWOPOW11))) {
0603 ret = -1;
0604 goto done;
0605 }
0606 }
0607
0608
0609
0610
0611
0612 if (pkt_type == PKT_TYPE_BAR)
0613 seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1);
0614
0615 if (((end_win < start_win) &&
0616 (seq_num < start_win) && (seq_num > end_win)) ||
0617 ((end_win > start_win) && ((seq_num > end_win) ||
0618 (seq_num < start_win)))) {
0619 end_win = seq_num;
0620 if (((end_win - win_size) + 1) >= 0)
0621 start_win = (end_win - win_size) + 1;
0622 else
0623 start_win = (MAX_TID_VALUE - (win_size - end_win)) + 1;
0624 mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
0625 }
0626
0627 if (pkt_type != PKT_TYPE_BAR) {
0628 if (seq_num >= start_win)
0629 pkt_index = seq_num - start_win;
0630 else
0631 pkt_index = (seq_num+MAX_TID_VALUE) - start_win;
0632
0633 if (tbl->rx_reorder_ptr[pkt_index]) {
0634 ret = -1;
0635 goto done;
0636 }
0637
0638 tbl->rx_reorder_ptr[pkt_index] = payload;
0639 }
0640
0641
0642
0643
0644
0645 mwifiex_11n_scan_and_dispatch(priv, tbl);
0646
0647 done:
0648 if (!tbl->timer_context.timer_is_set ||
0649 prev_start_win != tbl->start_win)
0650 mwifiex_11n_rxreorder_timer_restart(tbl);
0651 return ret;
0652 }
0653
0654
0655
0656
0657
0658
0659 void
0660 mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
0661 u8 type, int initiator)
0662 {
0663 struct mwifiex_rx_reorder_tbl *tbl;
0664 struct mwifiex_tx_ba_stream_tbl *ptx_tbl;
0665 struct mwifiex_ra_list_tbl *ra_list;
0666 u8 cleanup_rx_reorder_tbl;
0667 int tid_down;
0668
0669 if (type == TYPE_DELBA_RECEIVE)
0670 cleanup_rx_reorder_tbl = (initiator) ? true : false;
0671 else
0672 cleanup_rx_reorder_tbl = (initiator) ? false : true;
0673
0674 mwifiex_dbg(priv->adapter, EVENT, "event: DELBA: %pM tid=%d initiator=%d\n",
0675 peer_mac, tid, initiator);
0676
0677 if (cleanup_rx_reorder_tbl) {
0678 tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
0679 peer_mac);
0680 if (!tbl) {
0681 mwifiex_dbg(priv->adapter, EVENT,
0682 "event: TID, TA not found in table\n");
0683 return;
0684 }
0685 mwifiex_del_rx_reorder_entry(priv, tbl);
0686 } else {
0687 ptx_tbl = mwifiex_get_ba_tbl(priv, tid, peer_mac);
0688 if (!ptx_tbl) {
0689 mwifiex_dbg(priv->adapter, EVENT,
0690 "event: TID, RA not found in table\n");
0691 return;
0692 }
0693
0694 tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
0695 ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, peer_mac);
0696 if (ra_list) {
0697 ra_list->amsdu_in_ampdu = false;
0698 ra_list->ba_status = BA_SETUP_NONE;
0699 }
0700 spin_lock_bh(&priv->tx_ba_stream_tbl_lock);
0701 mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl);
0702 spin_unlock_bh(&priv->tx_ba_stream_tbl_lock);
0703 }
0704 }
0705
0706
0707
0708
0709
0710
0711
0712 int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
0713 struct host_cmd_ds_command *resp)
0714 {
0715 struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp;
0716 int tid, win_size;
0717 struct mwifiex_rx_reorder_tbl *tbl;
0718 uint16_t block_ack_param_set;
0719
0720 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set);
0721
0722 tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
0723 >> BLOCKACKPARAM_TID_POS;
0724
0725
0726
0727
0728 if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) {
0729 mwifiex_dbg(priv->adapter, ERROR, "ADDBA RSP: failed %pM tid=%d)\n",
0730 add_ba_rsp->peer_mac_addr, tid);
0731
0732 tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
0733 add_ba_rsp->peer_mac_addr);
0734 if (tbl)
0735 mwifiex_del_rx_reorder_entry(priv, tbl);
0736
0737 return 0;
0738 }
0739
0740 win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
0741 >> BLOCKACKPARAM_WINSIZE_POS;
0742
0743 tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
0744 add_ba_rsp->peer_mac_addr);
0745 if (tbl) {
0746 if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
0747 priv->add_ba_param.rx_amsdu &&
0748 (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
0749 tbl->amsdu = true;
0750 else
0751 tbl->amsdu = false;
0752 }
0753
0754 mwifiex_dbg(priv->adapter, CMD,
0755 "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n",
0756 add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size);
0757
0758 return 0;
0759 }
0760
0761
0762
0763
0764
0765 void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,
0766 struct host_cmd_ds_11n_batimeout *event)
0767 {
0768 struct host_cmd_ds_11n_delba delba;
0769
0770 memset(&delba, 0, sizeof(struct host_cmd_ds_11n_delba));
0771 memcpy(delba.peer_mac_addr, event->peer_mac_addr, ETH_ALEN);
0772
0773 delba.del_ba_param_set |=
0774 cpu_to_le16((u16) event->tid << DELBA_TID_POS);
0775 delba.del_ba_param_set |= cpu_to_le16(
0776 (u16) event->origninator << DELBA_INITIATOR_POS);
0777 delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT);
0778 mwifiex_send_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba, false);
0779 }
0780
0781
0782
0783
0784
0785 void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
0786 {
0787 struct mwifiex_rx_reorder_tbl *del_tbl_ptr, *tmp_node;
0788
0789 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0790 list_for_each_entry_safe(del_tbl_ptr, tmp_node,
0791 &priv->rx_reorder_tbl_ptr, list) {
0792 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0793 mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);
0794 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0795 }
0796 INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
0797 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0798
0799 mwifiex_reset_11n_rx_seq_num(priv);
0800 }
0801
0802
0803
0804
0805 void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
0806 {
0807 struct mwifiex_private *priv;
0808 struct mwifiex_rx_reorder_tbl *tbl;
0809 int i;
0810
0811 for (i = 0; i < adapter->priv_num; i++) {
0812 priv = adapter->priv[i];
0813 if (!priv)
0814 continue;
0815
0816 spin_lock_bh(&priv->rx_reorder_tbl_lock);
0817 list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
0818 tbl->flags = flags;
0819 spin_unlock_bh(&priv->rx_reorder_tbl_lock);
0820 }
0821
0822 return;
0823 }
0824
0825
0826
0827 static void mwifiex_update_ampdu_rxwinsize(struct mwifiex_adapter *adapter,
0828 bool coex_flag)
0829 {
0830 u8 i;
0831 u32 rx_win_size;
0832 struct mwifiex_private *priv;
0833
0834 dev_dbg(adapter->dev, "Update rxwinsize %d\n", coex_flag);
0835
0836 for (i = 0; i < adapter->priv_num; i++) {
0837 if (!adapter->priv[i])
0838 continue;
0839 priv = adapter->priv[i];
0840 rx_win_size = priv->add_ba_param.rx_win_size;
0841 if (coex_flag) {
0842 if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
0843 priv->add_ba_param.rx_win_size =
0844 MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
0845 if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
0846 priv->add_ba_param.rx_win_size =
0847 MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
0848 if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
0849 priv->add_ba_param.rx_win_size =
0850 MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE;
0851 } else {
0852 if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
0853 priv->add_ba_param.rx_win_size =
0854 MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
0855 if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
0856 priv->add_ba_param.rx_win_size =
0857 MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
0858 if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
0859 priv->add_ba_param.rx_win_size =
0860 MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE;
0861 }
0862
0863 if (adapter->coex_win_size && adapter->coex_rx_win_size)
0864 priv->add_ba_param.rx_win_size =
0865 adapter->coex_rx_win_size;
0866
0867 if (rx_win_size != priv->add_ba_param.rx_win_size) {
0868 if (!priv->media_connected)
0869 continue;
0870 for (i = 0; i < MAX_NUM_TID; i++)
0871 mwifiex_11n_delba(priv, i);
0872 }
0873 }
0874 }
0875
0876
0877
0878 void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter)
0879 {
0880 u8 i;
0881 struct mwifiex_private *priv;
0882 u8 count = 0;
0883
0884 for (i = 0; i < adapter->priv_num; i++) {
0885 if (adapter->priv[i]) {
0886 priv = adapter->priv[i];
0887 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
0888 if (priv->media_connected)
0889 count++;
0890 }
0891 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
0892 if (priv->bss_started)
0893 count++;
0894 }
0895 }
0896 if (count >= MWIFIEX_BSS_COEX_COUNT)
0897 break;
0898 }
0899 if (count >= MWIFIEX_BSS_COEX_COUNT)
0900 mwifiex_update_ampdu_rxwinsize(adapter, true);
0901 else
0902 mwifiex_update_ampdu_rxwinsize(adapter, false);
0903 }
0904
0905
0906
0907 void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
0908 u8 *event_buf, u16 len)
0909 {
0910 struct mwifiex_ie_types_rxba_sync *tlv_rxba = (void *)event_buf;
0911 u16 tlv_type, tlv_len;
0912 struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
0913 u8 i, j;
0914 u16 seq_num, tlv_seq_num, tlv_bitmap_len;
0915 int tlv_buf_left = len;
0916 int ret;
0917 u8 *tmp;
0918
0919 mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:",
0920 event_buf, len);
0921 while (tlv_buf_left >= sizeof(*tlv_rxba)) {
0922 tlv_type = le16_to_cpu(tlv_rxba->header.type);
0923 tlv_len = le16_to_cpu(tlv_rxba->header.len);
0924 if (tlv_type != TLV_TYPE_RXBA_SYNC) {
0925 mwifiex_dbg(priv->adapter, ERROR,
0926 "Wrong TLV id=0x%x\n", tlv_type);
0927 return;
0928 }
0929
0930 tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num);
0931 tlv_bitmap_len = le16_to_cpu(tlv_rxba->bitmap_len);
0932 mwifiex_dbg(priv->adapter, INFO,
0933 "%pM tid=%d seq_num=%d bitmap_len=%d\n",
0934 tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num,
0935 tlv_bitmap_len);
0936
0937 rx_reor_tbl_ptr =
0938 mwifiex_11n_get_rx_reorder_tbl(priv, tlv_rxba->tid,
0939 tlv_rxba->mac);
0940 if (!rx_reor_tbl_ptr) {
0941 mwifiex_dbg(priv->adapter, ERROR,
0942 "Can not find rx_reorder_tbl!");
0943 return;
0944 }
0945
0946 for (i = 0; i < tlv_bitmap_len; i++) {
0947 for (j = 0 ; j < 8; j++) {
0948 if (tlv_rxba->bitmap[i] & (1 << j)) {
0949 seq_num = (MAX_TID_VALUE - 1) &
0950 (tlv_seq_num + i * 8 + j);
0951
0952 mwifiex_dbg(priv->adapter, ERROR,
0953 "drop packet,seq=%d\n",
0954 seq_num);
0955
0956 ret = mwifiex_11n_rx_reorder_pkt
0957 (priv, seq_num, tlv_rxba->tid,
0958 tlv_rxba->mac, 0, NULL);
0959
0960 if (ret)
0961 mwifiex_dbg(priv->adapter,
0962 ERROR,
0963 "Fail to drop packet");
0964 }
0965 }
0966 }
0967
0968 tlv_buf_left -= (sizeof(*tlv_rxba) + tlv_len);
0969 tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba);
0970 tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp;
0971 }
0972 }