iwlwifi: mvm: make iwl_mvm_update_sta() an inline
[cascardo/linux.git] / drivers / net / wireless / intel / iwlwifi / mvm / sta.c
index e87473a..258a234 100644 (file)
@@ -588,9 +588,7 @@ int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid,
                        ret);
 
        /* Make sure the SCD wrptr is correctly set before reconfiguring */
-       iwl_trans_txq_enable(mvm->trans, queue, iwl_mvm_ac_to_tx_fifo[ac],
-                            cmd.sta_id, tid, LINK_QUAL_AGG_FRAME_LIMIT_DEF,
-                            ssn, wdg_timeout);
+       iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, wdg_timeout);
 
        /* Update the TID "owner" of the queue */
        spin_lock_bh(&mvm->queue_info_lock);
@@ -747,14 +745,14 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
                        .scd_queue = queue,
                        .action = SCD_CFG_DISABLE_QUEUE,
                };
-               u8 ac;
+               u8 txq_curr_ac;
 
                disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue);
 
                spin_lock_bh(&mvm->queue_info_lock);
-               ac = mvm->queue_info[queue].mac80211_ac;
+               txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
                cmd.sta_id = mvm->queue_info[queue].ra_sta_id;
-               cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[ac];
+               cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[txq_curr_ac];
                cmd.tid = mvm->queue_info[queue].txq_tid;
                spin_unlock_bh(&mvm->queue_info_lock);
 
@@ -850,6 +848,41 @@ out_err:
        return ret;
 }
 
+static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue)
+{
+       struct iwl_scd_txq_cfg_cmd cmd = {
+               .scd_queue = queue,
+               .action = SCD_CFG_UPDATE_QUEUE_TID,
+       };
+       s8 sta_id;
+       int tid;
+       unsigned long tid_bitmap;
+       int ret;
+
+       lockdep_assert_held(&mvm->mutex);
+
+       spin_lock_bh(&mvm->queue_info_lock);
+       sta_id = mvm->queue_info[queue].ra_sta_id;
+       tid_bitmap = mvm->queue_info[queue].tid_bitmap;
+       spin_unlock_bh(&mvm->queue_info_lock);
+
+       if (WARN(!tid_bitmap, "TXQ %d has no tids assigned to it\n", queue))
+               return;
+
+       /* Find any TID for queue */
+       tid = find_first_bit(&tid_bitmap, IWL_MAX_TID_COUNT + 1);
+       cmd.tid = tid;
+       cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];
+
+       ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd);
+       if (ret)
+               IWL_ERR(mvm, "Failed to update owner of TXQ %d (ret=%d)\n",
+                       queue, ret);
+       else
+               IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n",
+                                   queue, tid);
+}
+
 static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)
 {
        struct ieee80211_sta *sta;
@@ -1005,14 +1038,30 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
        /* Reconfigure queues requiring reconfiguation */
        for (queue = 0; queue < IWL_MAX_HW_QUEUES; queue++) {
                bool reconfig;
+               bool change_owner;
 
                spin_lock_bh(&mvm->queue_info_lock);
                reconfig = (mvm->queue_info[queue].status ==
                            IWL_MVM_QUEUE_RECONFIGURING);
+
+               /*
+                * We need to take into account a situation in which a TXQ was
+                * allocated to TID x, and then turned shared by adding TIDs y
+                * and z. If TID x becomes inactive and is removed from the TXQ,
+                * ownership must be given to one of the remaining TIDs.
+                * This is mainly because if TID x continues - a new queue can't
+                * be allocated for it as long as it is an owner of another TXQ.
+                */
+               change_owner = !(mvm->queue_info[queue].tid_bitmap &
+                                BIT(mvm->queue_info[queue].txq_tid)) &&
+                              (mvm->queue_info[queue].status ==
+                               IWL_MVM_QUEUE_SHARED);
                spin_unlock_bh(&mvm->queue_info_lock);
 
                if (reconfig)
                        iwl_mvm_unshare_queue(mvm, queue);
+               else if (change_owner)
+                       iwl_mvm_change_queue_owner(mvm, queue);
        }
 
        /* Go over all stations with deferred traffic */
@@ -1248,13 +1297,6 @@ err:
        return ret;
 }
 
-int iwl_mvm_update_sta(struct iwl_mvm *mvm,
-                      struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta)
-{
-       return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0);
-}
-
 int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
                      bool drain)
 {
@@ -1447,9 +1489,31 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
                ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
 
                /* If DQA is supported - the queues can be disabled now */
-               if (iwl_mvm_is_dqa_supported(mvm))
+               if (iwl_mvm_is_dqa_supported(mvm)) {
+                       u8 reserved_txq = mvm_sta->reserved_queue;
+                       enum iwl_mvm_queue_status *status;
+
                        iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
 
+                       /*
+                        * If no traffic has gone through the reserved TXQ - it
+                        * is still marked as IWL_MVM_QUEUE_RESERVED, and
+                        * should be manually marked as free again
+                        */
+                       spin_lock_bh(&mvm->queue_info_lock);
+                       status = &mvm->queue_info[reserved_txq].status;
+                       if (WARN((*status != IWL_MVM_QUEUE_RESERVED) &&
+                                (*status != IWL_MVM_QUEUE_FREE),
+                                "sta_id %d reserved txq %d status %d",
+                                mvm_sta->sta_id, reserved_txq, *status)) {
+                               spin_unlock_bh(&mvm->queue_info_lock);
+                               return -EINVAL;
+                       }
+
+                       *status = IWL_MVM_QUEUE_FREE;
+                       spin_unlock_bh(&mvm->queue_info_lock);
+               }
+
                if (vif->type == NL80211_IFTYPE_STATION &&
                    mvmvif->ap_sta_id == mvm_sta->sta_id) {
                        /* if associated - we can't remove the AP STA now */
@@ -1979,11 +2043,9 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                baid_data->baid = baid;
                baid_data->timeout = timeout;
                baid_data->last_rx = jiffies;
-               init_timer(&baid_data->session_timer);
-               baid_data->session_timer.function =
-                       iwl_mvm_rx_agg_session_expired;
-               baid_data->session_timer.data =
-                       (unsigned long)&mvm->baid_map[baid];
+               setup_timer(&baid_data->session_timer,
+                           iwl_mvm_rx_agg_session_expired,
+                           (unsigned long)&mvm->baid_map[baid]);
                baid_data->mvm = mvm;
                baid_data->tid = tid;
                baid_data->sta_id = mvm_sta->sta_id;