|
@@ -26,11 +26,50 @@
|
|
#include "11n.h"
|
|
#include "11n.h"
|
|
#include "11n_rxreorder.h"
|
|
#include "11n_rxreorder.h"
|
|
|
|
|
|
|
|
+/* This function will dispatch amsdu packet and forward it to kernel/upper
|
|
|
|
+ * layer.
|
|
|
|
+ */
|
|
|
|
+static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
|
|
|
|
+ struct sk_buff *skb)
|
|
|
|
+{
|
|
|
|
+ struct rxpd *local_rx_pd = (struct rxpd *)(skb->data);
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (le16_to_cpu(local_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) {
|
|
|
|
+ struct sk_buff_head list;
|
|
|
|
+ struct sk_buff *rx_skb;
|
|
|
|
+
|
|
|
|
+ __skb_queue_head_init(&list);
|
|
|
|
+
|
|
|
|
+ skb_pull(skb, le16_to_cpu(local_rx_pd->rx_pkt_offset));
|
|
|
|
+ skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
|
|
|
|
+
|
|
|
|
+ ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
|
|
|
|
+ priv->wdev->iftype, 0, false);
|
|
|
|
+
|
|
|
|
+ while (!skb_queue_empty(&list)) {
|
|
|
|
+ rx_skb = __skb_dequeue(&list);
|
|
|
|
+ ret = mwifiex_recv_packet(priv, rx_skb);
|
|
|
|
+ if (ret == -1)
|
|
|
|
+ dev_err(priv->adapter->dev,
|
|
|
|
+ "Rx of A-MSDU failed");
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return -1;
|
|
|
|
+}
|
|
|
|
+
|
|
/* This function will process the rx packet and forward it to kernel/upper
|
|
/* This function will process the rx packet and forward it to kernel/upper
|
|
* layer.
|
|
* layer.
|
|
*/
|
|
*/
|
|
static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload)
|
|
static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload)
|
|
{
|
|
{
|
|
|
|
+ int ret = mwifiex_11n_dispatch_amsdu_pkt(priv, payload);
|
|
|
|
+
|
|
|
|
+ if (!ret)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
|
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
|
return mwifiex_handle_uap_rx_forward(priv, payload);
|
|
return mwifiex_handle_uap_rx_forward(priv, payload);
|
|
|
|
|
|
@@ -406,8 +445,11 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
|
|
>> BLOCKACKPARAM_TID_POS;
|
|
>> BLOCKACKPARAM_TID_POS;
|
|
add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT);
|
|
add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT);
|
|
block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
|
|
block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
|
|
- /* We donot support AMSDU inside AMPDU, hence reset the bit */
|
|
|
|
- block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK;
|
|
|
|
|
|
+
|
|
|
|
+ /* If we don't support AMSDU inside AMPDU, reset the bit */
|
|
|
|
+ if (!priv->add_ba_param.rx_amsdu ||
|
|
|
|
+ (priv->aggr_prio_tbl[tid].amsdu == BA_STREAM_NOT_ALLOWED))
|
|
|
|
+ block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK;
|
|
block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS;
|
|
block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS;
|
|
add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set);
|
|
add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set);
|
|
win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set)
|
|
win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set)
|
|
@@ -468,6 +510,12 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
|
|
mwifiex_11n_dispatch_pkt(priv, payload);
|
|
mwifiex_11n_dispatch_pkt(priv, payload);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
|
|
|
|
+ mwifiex_11n_dispatch_pkt(priv, payload);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
start_win = tbl->start_win;
|
|
start_win = tbl->start_win;
|
|
win_size = tbl->win_size;
|
|
win_size = tbl->win_size;
|
|
end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
|
|
end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
|
|
@@ -627,6 +675,17 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
|
|
win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
|
|
win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK)
|
|
>> BLOCKACKPARAM_WINSIZE_POS;
|
|
>> BLOCKACKPARAM_WINSIZE_POS;
|
|
|
|
|
|
|
|
+ tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid,
|
|
|
|
+ add_ba_rsp->peer_mac_addr);
|
|
|
|
+ if (tbl) {
|
|
|
|
+ if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) &&
|
|
|
|
+ priv->add_ba_param.rx_amsdu &&
|
|
|
|
+ (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED))
|
|
|
|
+ tbl->amsdu = true;
|
|
|
|
+ else
|
|
|
|
+ tbl->amsdu = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
dev_dbg(priv->adapter->dev,
|
|
dev_dbg(priv->adapter->dev,
|
|
"cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n",
|
|
"cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n",
|
|
add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size);
|
|
add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size);
|