diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-03-21 19:02:04 +0100 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-03-21 19:02:04 +0100 |
commit | 49c0ca17ee8dd3530f688052d4eb2ae6d3e55119 (patch) | |
tree | 251a4c566723b60505234a18ed864763ad0d0506 /drivers/net/wireless/mwifiex | |
parent | Merge branch 'bcmgenet-next' (diff) | |
parent | brcmfmac: fallback to mimo_bw_cap for older firmwares (diff) | |
download | linux-49c0ca17ee8dd3530f688052d4eb2ae6d3e55119.tar.xz linux-49c0ca17ee8dd3530f688052d4eb2ae6d3e55119.zip |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r-- | drivers/net/wireless/mwifiex/11n.c | 51 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/11n.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/11n_rxreorder.c | 144 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cmdevt.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/fw.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/ioctl.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/pcie.c | 26 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/pcie.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmd.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmdresp.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_rx.c | 21 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/uap_cmd.c | 20 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/uap_event.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/uap_txrx.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 37 |
17 files changed, 284 insertions, 117 deletions
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index d9c65b60cd72..d14ead8beca8 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -159,28 +159,34 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, int tid; struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; + u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) & SSN_MASK); - tid = (le16_to_cpu(add_ba_rsp->block_ack_param_set) - & IEEE80211_ADDBA_PARAM_TID_MASK) - >> BLOCKACKPARAM_TID_POS; - if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { - tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, - add_ba_rsp->peer_mac_addr); - if (tx_ba_tbl) { - dev_dbg(priv->adapter->dev, "info: BA stream complete\n"); - tx_ba_tbl->ba_status = BA_SETUP_COMPLETE; - } else { - dev_err(priv->adapter->dev, "BA stream not created\n"); - } - } else { + tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) + >> BLOCKACKPARAM_TID_POS; + if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, TYPE_DELBA_SENT, true); if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) priv->aggr_prio_tbl[tid].ampdu_ap = BA_STREAM_NOT_ALLOWED; + return 0; + } + + tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr); + if (tx_ba_tbl) { + dev_dbg(priv->adapter->dev, "info: BA stream complete\n"); + tx_ba_tbl->ba_status = BA_SETUP_COMPLETE; + if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) && + priv->add_ba_param.tx_amsdu && + (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) + tx_ba_tbl->amsdu = true; + else + tx_ba_tbl->amsdu = false; + } else { + dev_err(priv->adapter->dev, "BA stream not created\n"); } return 0; @@ -540,6 +546,7 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) u32 tx_win_size = priv->add_ba_param.tx_win_size; static u8 dialog_tok; int ret; + u16 block_ack_param_set; dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid); @@ -558,10 +565,16 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE; } - add_ba_req.block_ack_param_set = cpu_to_le16( - (u16) ((tid << BLOCKACKPARAM_TID_POS) | - tx_win_size << BLOCKACKPARAM_WINSIZE_POS | - IMMEDIATE_BLOCK_ACK)); + block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) | + tx_win_size << BLOCKACKPARAM_WINSIZE_POS | + IMMEDIATE_BLOCK_ACK); + + /* enable AMSDU inside AMPDU */ + if (priv->add_ba_param.tx_amsdu && + (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) + block_ack_param_set |= BLOCKACKPARAM_AMSDU_SUPP_MASK; + + add_ba_req.block_ack_param_set = cpu_to_le16(block_ack_param_set); add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout); ++dialog_tok; @@ -676,6 +689,7 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "data: %s tid=%d\n", __func__, rx_reo_tbl->tid); memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); + rx_reo_tbl->amsdu = tx_ba_tsr_tbl->amsdu; rx_reo_tbl++; count++; if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) @@ -731,5 +745,8 @@ void mwifiex_set_ba_params(struct mwifiex_private *priv) MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; } + priv->add_ba_param.tx_amsdu = true; + priv->add_ba_param.rx_amsdu = true; + return; } diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 12bb6acbdd58..40b007a00f4b 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -76,6 +76,20 @@ mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv, return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; } +/* This function checks whether AMSDU is allowed for BA stream. */ +static inline u8 +mwifiex_is_amsdu_in_ampdu_allowed(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, int tid) +{ + struct mwifiex_tx_ba_stream_tbl *tx_tbl; + + tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); + if (tx_tbl) + return tx_tbl->amsdu; + + return false; +} + /* This function checks whether AMPDU is allowed or not for a particular TID. */ static inline u8 mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index c3323c492614..0c3571f830b0 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -26,6 +26,56 @@ #include "11n.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 + * layer. + */ +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) + return mwifiex_handle_uap_rx_forward(priv, payload); + + return mwifiex_process_rx_packet(priv, payload); +} + /* * This function dispatches all packets in the Rx reorder table until the * start window. @@ -35,8 +85,9 @@ * circular buffer. */ static void -mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, - struct mwifiex_rx_reorder_tbl *tbl, int start_win) +mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, + struct mwifiex_rx_reorder_tbl *tbl, + int start_win) { int pkt_to_send, i; void *rx_tmp_ptr; @@ -54,12 +105,8 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, tbl->rx_reorder_ptr[i] = NULL; } spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - if (rx_tmp_ptr) { - if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) - mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); - else - mwifiex_process_rx_packet(priv, rx_tmp_ptr); - } + if (rx_tmp_ptr) + mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); } spin_lock_irqsave(&priv->rx_pkt_lock, flags); @@ -101,11 +148,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, rx_tmp_ptr = tbl->rx_reorder_ptr[i]; tbl->rx_reorder_ptr[i] = NULL; spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - - if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) - mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); - else - mwifiex_process_rx_packet(priv, rx_tmp_ptr); + mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); } spin_lock_irqsave(&priv->rx_pkt_lock, flags); @@ -135,12 +178,13 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv, struct mwifiex_rx_reorder_tbl *tbl) { unsigned long flags; + int start_win; if (!tbl) return; - mwifiex_11n_dispatch_pkt(priv, tbl, (tbl->start_win + tbl->win_size) & - (MAX_TID_VALUE - 1)); + start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1); + mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); del_timer_sync(&tbl->timer_context.timer); @@ -228,17 +272,17 @@ mwifiex_flush_data(unsigned long context) { struct reorder_tmr_cnxt *ctx = (struct reorder_tmr_cnxt *) context; - int start_win; + int start_win, seq_num; - start_win = mwifiex_11n_find_last_seq_num(ctx->ptr); + seq_num = mwifiex_11n_find_last_seq_num(ctx->ptr); - if (start_win < 0) + if (seq_num < 0) return; - dev_dbg(ctx->priv->adapter->dev, "info: flush data %d\n", start_win); - mwifiex_11n_dispatch_pkt(ctx->priv, ctx->ptr, - (ctx->ptr->start_win + start_win + 1) & - (MAX_TID_VALUE - 1)); + dev_dbg(ctx->priv->adapter->dev, "info: flush data %d\n", seq_num); + start_win = (ctx->ptr->start_win + seq_num + 1) & (MAX_TID_VALUE - 1); + mwifiex_11n_dispatch_pkt_until_start_win(ctx->priv, ctx->ptr, + start_win); } /* @@ -267,7 +311,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, */ tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); if (tbl) { - mwifiex_11n_dispatch_pkt(priv, tbl, seq_num); + mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, seq_num); return; } /* if !tbl then create one */ @@ -401,8 +445,11 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, >> BLOCKACKPARAM_TID_POS; add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); 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; 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) @@ -459,14 +506,16 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); if (!tbl) { - if (pkt_type != PKT_TYPE_BAR) { - if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) - mwifiex_handle_uap_rx_forward(priv, payload); - else - mwifiex_process_rx_packet(priv, payload); - } + if (pkt_type != PKT_TYPE_BAR) + mwifiex_11n_dispatch_pkt(priv, payload); return 0; } + + if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) { + mwifiex_11n_dispatch_pkt(priv, payload); + return 0; + } + start_win = tbl->start_win; win_size = tbl->win_size; end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); @@ -520,7 +569,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, start_win = (end_win - win_size) + 1; else start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; - mwifiex_11n_dispatch_pkt(priv, tbl, start_win); + mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); } if (pkt_type != PKT_TYPE_BAR) { @@ -611,16 +660,7 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, * Check if we had rejected the ADDBA, if yes then do not create * the stream */ - if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { - win_size = (block_ack_param_set & - IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) - >> BLOCKACKPARAM_WINSIZE_POS; - - dev_dbg(priv->adapter->dev, - "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); - } else { + if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n", add_ba_rsp->peer_mac_addr, tid); @@ -628,8 +668,28 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, add_ba_rsp->peer_mac_addr); if (tbl) mwifiex_del_rx_reorder_entry(priv, tbl); + + return 0; } + win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) + >> 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, + "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); + return 0; } diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 51ce99cfcfb9..21ee27ab7b74 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1158,9 +1158,10 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; enum ieee80211_band band; + struct mwifiex_adapter *adapter = priv->adapter; if (!priv->media_connected) { - dev_err(priv->adapter->dev, + dev_err(adapter->dev, "Can not set Tx data rate in disconnected state\n"); return -EINVAL; } @@ -1181,9 +1182,16 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, /* Fill HT MCS rates */ bitmap_rates[2] = mask->control[band].ht_mcs[0]; - if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) + if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; + /* Fill VHT MCS rates */ + if (adapter->fw_api_ver == MWIFIEX_FW_V15) { + bitmap_rates[10] = mask->control[band].vht_mcs[0]; + if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) + bitmap_rates[11] = mask->control[band].vht_mcs[1]; + } + return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG, HostCmd_ACT_GEN_SET, 0, bitmap_rates, true); } @@ -2092,10 +2100,10 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, else ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; - if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; + if (adapter->user_dev_mcs_support == HT_STREAM_2X2) + ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT; else - ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); + ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 14e05c9f4663..b41155829220 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -1502,6 +1502,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, } adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); + adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff; adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 39cb3542f79c..b485dc1ae5eb 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -202,6 +202,11 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR +#define GET_RXSTBC(x) (x & IEEE80211_HT_CAP_RX_STBC) +#define MWIFIEX_RX_STBC1 0x0100 +#define MWIFIEX_RX_STBC12 0x0200 +#define MWIFIEX_RX_STBC123 0x0300 + /* dev_cap bitmap * BIT * 0-16 reserved @@ -515,6 +520,8 @@ enum P2P_MODES { #define ACT_TDLS_CREATE 0x01 #define ACT_TDLS_CONFIG 0x02 +#define MWIFIEX_FW_V15 15 + struct mwifiex_ie_types_header { __le16 type; __le16 len; @@ -1103,6 +1110,7 @@ struct mwifiex_rate_scope { __le16 hr_dsss_rate_bitmap; __le16 ofdm_rate_bitmap; __le16 ht_mcs_rate_bitmap[8]; + __le16 vht_mcs_rate_bitmap[8]; } __packed; struct mwifiex_rate_drop_pattern { diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 1fb2212079ae..ee494db54060 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -177,6 +177,7 @@ struct mwifiex_ds_rx_reorder_tbl { struct mwifiex_ds_tx_ba_stream_tbl { u16 tid; u8 ra[ETH_ALEN]; + u8 amsdu; }; #define DBG_CMD_NUM 5 diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index f0289c12e041..a67f7da12b30 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -116,7 +116,7 @@ enum { #define MWIFIEX_TYPE_DATA 0 #define MWIFIEX_TYPE_EVENT 3 -#define MAX_BITMAP_RATES_SIZE 10 +#define MAX_BITMAP_RATES_SIZE 18 #define MAX_CHANNEL_BAND_BG 14 #define MAX_CHANNEL_BAND_A 165 @@ -192,6 +192,8 @@ struct mwifiex_add_ba_param { u32 tx_win_size; u32 rx_win_size; u32 timeout; + u8 tx_amsdu; + u8 rx_amsdu; }; struct mwifiex_tx_aggr { @@ -560,6 +562,7 @@ struct mwifiex_tx_ba_stream_tbl { int tid; u8 ra[ETH_ALEN]; enum mwifiex_ba_status ba_status; + u8 amsdu; }; struct mwifiex_rx_reorder_tbl; @@ -579,6 +582,7 @@ struct mwifiex_rx_reorder_tbl { int win_size; void **rx_reorder_ptr; struct reorder_tmr_cnxt timer_context; + u8 amsdu; u8 flags; }; @@ -802,6 +806,7 @@ struct mwifiex_adapter { atomic_t pending_bridged_pkts; struct semaphore *card_sem; bool ext_scan; + u8 fw_api_ver; u8 fw_key_api_major_ver, fw_key_api_minor_ver; }; diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 9f1683b5f28f..57c353a94b29 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -327,6 +327,30 @@ static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter) return; } +static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, + u32 max_delay_loop_cnt) +{ + struct pcie_service_card *card = adapter->card; + u8 *buffer; + u32 sleep_cookie, count; + + for (count = 0; count < max_delay_loop_cnt; count++) { + buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN; + sleep_cookie = *(u32 *)buffer; + + if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) { + dev_dbg(adapter->dev, + "sleep cookie found at count %d\n", count); + break; + } + usleep_range(20, 30); + } + + if (count >= max_delay_loop_cnt) + dev_dbg(adapter->dev, + "max count reached while accessing sleep cookie\n"); +} + /* This function wakes up the card by reading fw_status register. */ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) { @@ -1539,6 +1563,8 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) "Write register failed\n"); return -1; } + mwifiex_delay_for_sleep_cookie(adapter, + MWIFIEX_MAX_DELAY_COUNT); while (reg->sleep_cookie && (count++ < 10) && mwifiex_pcie_ok_to_access_hw(adapter)) usleep_range(50, 60); diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h index 193af75bf582..e8ec561f8a64 100644 --- a/drivers/net/wireless/mwifiex/pcie.h +++ b/drivers/net/wireless/mwifiex/pcie.h @@ -97,6 +97,8 @@ #define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD 256 /* FW awake cookie after FW ready */ #define FW_AWAKE_COOKIE (0xAA55AA55) +#define MWIFIEX_DEF_SLEEP_COOKIE 0xBEEFBEEF +#define MWIFIEX_MAX_DELAY_COUNT 5 struct mwifiex_pcie_card_reg { u16 cmd_addr_lo; diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 4315a3ba3b92..e3cac1495cc7 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -185,6 +185,13 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, i++) rate_scope->ht_mcs_rate_bitmap[i] = cpu_to_le16(pbitmap_rates[2 + i]); + if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { + for (i = 0; + i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); + i++) + rate_scope->vht_mcs_rate_bitmap[i] = + cpu_to_le16(pbitmap_rates[10 + i]); + } } else { rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(priv->bitmap_rates[0]); @@ -195,6 +202,13 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, i++) rate_scope->ht_mcs_rate_bitmap[i] = cpu_to_le16(priv->bitmap_rates[2 + i]); + if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { + for (i = 0; + i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); + i++) + rate_scope->vht_mcs_rate_bitmap[i] = + cpu_to_le16(priv->bitmap_rates[10 + i]); + } } rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index a8f7d545e22a..bfebb0144df5 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -304,6 +304,15 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, priv->bitmap_rates[2 + i] = le16_to_cpu(rate_scope-> ht_mcs_rate_bitmap[i]); + + if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { + for (i = 0; i < ARRAY_SIZE(rate_scope-> + vht_mcs_rate_bitmap); + i++) + priv->bitmap_rates[10 + i] = + le16_to_cpu(rate_scope-> + vht_mcs_rate_bitmap[i]); + } break; /* Add RATE_DROP tlv here */ } diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index b6aa958bd6e4..ed26387eccf5 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -201,26 +201,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, return ret; } - if (rx_pkt_type == PKT_TYPE_AMSDU) { - struct sk_buff_head list; - struct sk_buff *rx_skb; - - __skb_queue_head_init(&list); - - skb_pull(skb, rx_pkt_offset); - skb_trim(skb, 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(adapter->dev, "Rx of A-MSDU failed"); - } - return 0; - } else if (rx_pkt_type == PKT_TYPE_MGMT) { + if (rx_pkt_type == PKT_TYPE_MGMT) { ret = mwifiex_process_mgmt_packet(priv, skb); if (ret) dev_err(adapter->dev, "Rx of mgmt packet failed"); diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index a6a6a53cda40..9be6544bdded 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -159,6 +159,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, struct cfg80211_ap_settings *params) { const u8 *ht_ie; + u16 cap_info; if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) return; @@ -168,6 +169,25 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, if (ht_ie) { memcpy(&bss_cfg->ht_cap, ht_ie + 2, sizeof(struct ieee80211_ht_cap)); + cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info); + memset(&bss_cfg->ht_cap.mcs, 0, + priv->adapter->number_of_antenna); + switch (GET_RXSTBC(cap_info)) { + case MWIFIEX_RX_STBC1: + /* HT_CAP 1X1 mode */ + memset(&bss_cfg->ht_cap.mcs, 0xff, 1); + break; + case MWIFIEX_RX_STBC12: /* fall through */ + case MWIFIEX_RX_STBC123: + /* HT_CAP 2X2 mode */ + memset(&bss_cfg->ht_cap.mcs, 0xff, 2); + break; + default: + dev_warn(priv->adapter->dev, + "Unsupported RX-STBC, default to 2x2\n"); + memset(&bss_cfg->ht_cap.mcs, 0xff, 2); + break; + } priv->ap_11n_enabled = 1; } else { memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap)); diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index ae50e916d8f2..92e77a398ecf 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -166,6 +166,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) mwifiex_11n_ba_stream_timeout(priv, ba_timeout); } break; + case EVENT_EXT_SCAN_REPORT: + dev_dbg(adapter->dev, "event: EXT_SCAN Report\n"); + if (adapter->ext_scan) + return mwifiex_handle_event_ext_scan_report(priv, + adapter->event_skb->data); + break; default: dev_dbg(adapter->dev, "event: unknown event id: %#x\n", eventcause); diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 3c74eb254927..9a56bc61cb1d 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -284,27 +284,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, return 0; } - if (le16_to_cpu(uap_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(uap_rx_pd->rx_pkt_offset)); - skb_trim(skb, le16_to_cpu(uap_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) - dev_err(adapter->dev, - "AP:Rx A-MSDU failed"); - } - - return 0; - } else if (rx_pkt_type == PKT_TYPE_MGMT) { + if (rx_pkt_type == PKT_TYPE_MGMT) { ret = mwifiex_process_mgmt_packet(priv, skb); if (ret) dev_err(adapter->dev, "Rx of mgmt packet failed"); diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 1c5f2b66f057..0a7cc742aed7 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -37,8 +37,8 @@ /* Offset for TOS field in the IP header */ #define IPTOS_OFFSET 5 -static bool enable_tx_amsdu; -module_param(enable_tx_amsdu, bool, 0644); +static bool disable_tx_amsdu; +module_param(disable_tx_amsdu, bool, 0644); /* WMM information IE */ static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, @@ -413,7 +413,13 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) continue; for (i = 0; i < MAX_NUM_TID; ++i) { - priv->aggr_prio_tbl[i].amsdu = priv->tos_to_tid_inv[i]; + if (!disable_tx_amsdu && + adapter->tx_buf_size > MWIFIEX_TX_DATA_BUF_SIZE_2K) + priv->aggr_prio_tbl[i].amsdu = + priv->tos_to_tid_inv[i]; + else + priv->aggr_prio_tbl[i].amsdu = + BA_STREAM_NOT_ALLOWED; priv->aggr_prio_tbl[i].ampdu_ap = priv->tos_to_tid_inv[i]; priv->aggr_prio_tbl[i].ampdu_user = @@ -1247,13 +1253,22 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) if (!ptr->is_11n_enabled || mwifiex_is_ba_stream_setup(priv, ptr, tid) || - priv->wps.session_enable || - ((priv->sec_info.wpa_enabled || - priv->sec_info.wpa2_enabled) && - !priv->wpa_is_gtk_set)) { - mwifiex_send_single_packet(priv, ptr, ptr_index, flags); - /* ra_list_spinlock has been freed in - mwifiex_send_single_packet() */ + priv->wps.session_enable) { + if (ptr->is_11n_enabled && + mwifiex_is_ba_stream_setup(priv, ptr, tid) && + mwifiex_is_amsdu_in_ampdu_allowed(priv, ptr, tid) && + mwifiex_is_amsdu_allowed(priv, tid) && + mwifiex_is_11n_aggragation_possible(priv, ptr, + adapter->tx_buf_size)) + mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); + /* ra_list_spinlock has been freed in + * mwifiex_11n_aggregate_pkt() + */ + else + mwifiex_send_single_packet(priv, ptr, ptr_index, flags); + /* ra_list_spinlock has been freed in + * mwifiex_send_single_packet() + */ } else { if (mwifiex_is_ampdu_allowed(priv, ptr, tid) && ptr->ba_pkt_count > ptr->ba_packet_thr) { @@ -1268,7 +1283,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) mwifiex_send_delba(priv, tid_del, ra, 1); } } - if (enable_tx_amsdu && mwifiex_is_amsdu_allowed(priv, tid) && + if (mwifiex_is_amsdu_allowed(priv, tid) && mwifiex_is_11n_aggragation_possible(priv, ptr, adapter->tx_buf_size)) mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); |