iwlwifi: mvm: simplify the channel switch flow for newer firmware
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 30 Jun 2019 12:40:19 +0000 (15:40 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 6 Sep 2019 12:31:19 +0000 (15:31 +0300)
Any firmware that supports the new channel switch flow is
able to close / re-open the queues when needed. It takes
into account the channel switch mode etc...
Don't open / close the queues or enable / disable beacon
abort before and after the channel switch in case the
firmware is able to do this by itself.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

index fe776e3..8fa3564 100644 (file)
@@ -1594,7 +1594,9 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
                RCU_INIT_POINTER(mvm->csa_vif, NULL);
                return;
        case NL80211_IFTYPE_STATION:
-               iwl_mvm_csa_client_absent(mvm, vif);
+               if (!fw_has_capa(&mvm->fw->ucode_capa,
+                                IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
+                       iwl_mvm_csa_client_absent(mvm, vif);
                cancel_delayed_work(&mvmvif->csa_work);
                ieee80211_chswitch_done(vif, true);
                break;
index 73302fe..b8d8250 100644 (file)
@@ -1326,15 +1326,20 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
                        goto out_unlock;
                }
 
-               iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
+               if (!fw_has_capa(&mvm->fw->ucode_capa,
+                                IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
+                       iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
 
                iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
 
-               ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
-               if (ret)
-                       goto out_unlock;
+               if (!fw_has_capa(&mvm->fw->ucode_capa,
+                                IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
+                       ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
+                       if (ret)
+                               goto out_unlock;
 
-               iwl_mvm_stop_session_protection(mvm, vif);
+                       iwl_mvm_stop_session_protection(mvm, vif);
+               }
        }
 
        mvmvif->ps_disabled = false;
@@ -4421,6 +4426,42 @@ static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm,
                                    0, sizeof(cmd), &cmd);
 }
 
+static int iwl_mvm_old_pre_chan_sw_sta(struct iwl_mvm *mvm,
+                                      struct ieee80211_vif *vif,
+                                      struct ieee80211_channel_switch *chsw)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       u32 apply_time;
+
+       /* Schedule the time event to a bit before beacon 1,
+        * to make sure we're in the new channel when the
+        * GO/AP arrives. In case count <= 1 immediately schedule the
+        * TE (this might result with some packet loss or connection
+        * loss).
+        */
+       if (chsw->count <= 1)
+               apply_time = 0;
+       else
+               apply_time = chsw->device_timestamp +
+                       ((vif->bss_conf.beacon_int * (chsw->count - 1) -
+                         IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
+
+       if (chsw->block_tx)
+               iwl_mvm_csa_client_absent(mvm, vif);
+
+       if (mvmvif->bf_data.bf_enabled) {
+               int ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
+
+               if (ret)
+                       return ret;
+       }
+
+       iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
+                                   apply_time);
+
+       return 0;
+}
+
 #define IWL_MAX_CSA_BLOCK_TX 1500
 static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
                                      struct ieee80211_vif *vif,
@@ -4429,7 +4470,6 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        struct ieee80211_vif *csa_vif;
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       u32 apply_time;
        int ret;
 
        mutex_lock(&mvm->mutex);
@@ -4473,21 +4513,7 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
 
                break;
        case NL80211_IFTYPE_STATION:
-               /* Schedule the time event to a bit before beacon 1,
-                * to make sure we're in the new channel when the
-                * GO/AP arrives. In case count <= 1 immediately schedule the
-                * TE (this might result with some packet loss or connection
-                * loss).
-                */
-               if (chsw->count <= 1)
-                       apply_time = 0;
-               else
-                       apply_time = chsw->device_timestamp +
-                               ((vif->bss_conf.beacon_int * (chsw->count - 1) -
-                                 IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
-
                if (chsw->block_tx) {
-                       iwl_mvm_csa_client_absent(mvm, vif);
                        /*
                         * In case of undetermined / long time with immediate
                         * quiet monitor status to gracefully disconnect
@@ -4499,19 +4525,14 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
                                                      msecs_to_jiffies(IWL_MAX_CSA_BLOCK_TX));
                }
 
-               if (mvmvif->bf_data.bf_enabled) {
-                       ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
+               if (!fw_has_capa(&mvm->fw->ucode_capa,
+                                IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
+                       ret = iwl_mvm_old_pre_chan_sw_sta(mvm, vif, chsw);
                        if (ret)
                                goto out_unlock;
-               }
-
-               if (fw_has_capa(&mvm->fw->ucode_capa,
-                               IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
+               } else {
                        iwl_mvm_schedule_client_csa(mvm, vif, chsw);
-               else
-                       iwl_mvm_schedule_csa_period(mvm, vif,
-                                                   vif->bss_conf.beacon_int,
-                                                   apply_time);
+               }
 
                mvmvif->csa_count = chsw->count;
                mvmvif->csa_misbehave = false;