These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / mwifiex / 11n.c
index 433bd68..c174e79 100644 (file)
@@ -42,7 +42,7 @@ int mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type,
                                        priv->wdev.wiphy->bands[radio_type];
 
        if (WARN_ON_ONCE(!sband)) {
-               dev_err(priv->adapter->dev, "Invalid radio type!\n");
+               mwifiex_dbg(priv->adapter, ERROR, "Invalid radio type!\n");
                return -EINVAL;
        }
 
@@ -156,7 +156,7 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
 int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
                              struct host_cmd_ds_command *resp)
 {
-       int tid;
+       int tid, tid_down;
        struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp;
        struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl;
        struct mwifiex_ra_list_tbl *ra_list;
@@ -167,7 +167,9 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
 
        tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
               >> BLOCKACKPARAM_TID_POS;
-       ra_list = mwifiex_wmm_get_ralist_node(priv, tid, add_ba_rsp->
+
+       tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+       ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, add_ba_rsp->
                peer_mac_addr);
        if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) {
                if (ra_list) {
@@ -184,7 +186,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
 
        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");
+               mwifiex_dbg(priv->adapter, EVENT, "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 &&
@@ -197,7 +199,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
                        ra_list->ba_status = BA_SETUP_COMPLETE;
                }
        } else {
-               dev_err(priv->adapter->dev, "BA stream not created\n");
+               mwifiex_dbg(priv->adapter, ERROR, "BA stream not created\n");
        }
 
        return 0;
@@ -224,7 +226,8 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
        tx_buf->action = cpu_to_le16(action);
        switch (action) {
        case HostCmd_ACT_GEN_SET:
-               dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", *buf_size);
+               mwifiex_dbg(priv->adapter, CMD,
+                           "cmd: set tx_buf=%d\n", *buf_size);
                tx_buf->buff_size = cpu_to_le16(*buf_size);
                break;
        case HostCmd_ACT_GEN_GET:
@@ -466,7 +469,8 @@ void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,
            mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl))
                return;
 
-       dev_dbg(priv->adapter->dev, "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl);
+       mwifiex_dbg(priv->adapter, INFO,
+                   "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl);
 
        list_del(&tx_ba_tsr_tbl->list);
 
@@ -528,13 +532,16 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
        struct mwifiex_tx_ba_stream_tbl *new_node;
        struct mwifiex_ra_list_tbl *ra_list;
        unsigned long flags;
+       int tid_down;
 
        if (!mwifiex_get_ba_tbl(priv, tid, ra)) {
                new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl),
                                   GFP_ATOMIC);
                if (!new_node)
                        return;
-               ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra);
+
+               tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+               ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, ra);
                if (ra_list) {
                        ra_list->ba_status = ba_status;
                        ra_list->amsdu_in_ampdu = false;
@@ -563,7 +570,7 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
        unsigned long flags;
        u16 block_ack_param_set;
 
-       dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid);
+       mwifiex_dbg(priv->adapter, CMD, "cmd: %s: tid %d\n", __func__, tid);
 
        if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
            ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
@@ -575,9 +582,9 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
                sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
                if (!sta_ptr) {
                        spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-                       dev_warn(priv->adapter->dev,
-                                "BA setup with unknown TDLS peer %pM!\n",
-                               peer_mac);
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "BA setup with unknown TDLS peer %pM!\n",
+                                   peer_mac);
                        return -1;
                }
                if (sta_ptr->is_11ac_enabled)
@@ -640,6 +647,30 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
        return ret;
 }
 
+/*
+ * This function sends delba to specific tid
+ */
+void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
+{
+       struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+
+       if (list_empty(&priv->rx_reorder_tbl_ptr)) {
+               dev_dbg(priv->adapter->dev,
+                       "mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n");
+               return;
+       }
+
+       list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
+               if (rx_reor_tbl_ptr->tid == tid) {
+                       dev_dbg(priv->adapter->dev,
+                               "Send delba to tid=%d, %pM\n",
+                               tid, rx_reor_tbl_ptr->ta);
+                       mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0);
+                       return;
+               }
+       }
+}
+
 /*
  * This function handles the command response of a delete BA request.
  */
@@ -706,8 +737,8 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
        spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
        list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) {
                rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid;
-               dev_dbg(priv->adapter->dev, "data: %s tid=%d\n",
-                       __func__, rx_reo_tbl->tid);
+               mwifiex_dbg(priv->adapter, DATA, "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++;
@@ -812,3 +843,72 @@ u8 mwifiex_get_sec_chan_offset(int chan)
 
        return sec_offset;
 }
+
+/* This function will send DELBA to entries in the priv's
+ * Tx BA stream table
+ */
+static void
+mwifiex_send_delba_txbastream_tbl(struct mwifiex_private *priv, u8 tid)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_tx_ba_stream_tbl *tx_ba_stream_tbl_ptr;
+
+       if (list_empty(&priv->tx_ba_stream_tbl_ptr))
+               return;
+
+       list_for_each_entry(tx_ba_stream_tbl_ptr,
+                           &priv->tx_ba_stream_tbl_ptr, list) {
+               if (tx_ba_stream_tbl_ptr->ba_status == BA_SETUP_COMPLETE) {
+                       if (tid == tx_ba_stream_tbl_ptr->tid) {
+                               dev_dbg(adapter->dev,
+                                       "Tx:Send delba to tid=%d, %pM\n", tid,
+                                       tx_ba_stream_tbl_ptr->ra);
+                               mwifiex_send_delba(priv,
+                                                  tx_ba_stream_tbl_ptr->tid,
+                                                  tx_ba_stream_tbl_ptr->ra, 1);
+                               return;
+                       }
+               }
+       }
+}
+
+/* This function updates all the tx_win_size
+ */
+void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *adapter)
+{
+       u8 i;
+       u32 tx_win_size;
+       struct mwifiex_private *priv;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (!adapter->priv[i])
+                       continue;
+               priv = adapter->priv[i];
+               tx_win_size = priv->add_ba_param.tx_win_size;
+
+               if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
+                       priv->add_ba_param.tx_win_size =
+                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
+
+               if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
+                       priv->add_ba_param.tx_win_size =
+                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
+
+               if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
+                       priv->add_ba_param.tx_win_size =
+                               MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE;
+
+               if (adapter->coex_win_size) {
+                       if (adapter->coex_tx_win_size)
+                               priv->add_ba_param.tx_win_size =
+                                       adapter->coex_tx_win_size;
+               }
+
+               if (tx_win_size != priv->add_ba_param.tx_win_size) {
+                       if (!priv->media_connected)
+                               continue;
+                       for (i = 0; i < MAX_NUM_TID; i++)
+                               mwifiex_send_delba_txbastream_tbl(priv, i);
+               }
+       }
+}