iwlwifi: mvm: add CSA absent time event for clients
[cascardo/linux.git] / drivers / net / wireless / iwlwifi / mvm / mac80211.c
index 6098eaf..ac1cef6 100644 (file)
@@ -2796,8 +2796,8 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
 
        switch (vif->type) {
        case NL80211_IFTYPE_AP:
-               /* Unless it's a CSA flow we have nothing to do here */
-               if (vif->csa_active) {
+               /* only needed if we're switching chanctx (i.e. during CSA) */
+               if (switching_chanctx) {
                        mvmvif->ap_ibss_active = true;
                        break;
                }
@@ -2847,7 +2847,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
                iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
        }
 
-       if (vif->csa_active && vif->type == NL80211_IFTYPE_STATION) {
+       if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
                struct iwl_mvm_sta *mvmsta;
 
                mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
@@ -2891,7 +2891,6 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct ieee80211_vif *disabled_vif = NULL;
-       struct iwl_mvm_sta *mvmsta;
 
        lockdep_assert_held(&mvm->mutex);
 
@@ -2906,7 +2905,7 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
                break;
        case NL80211_IFTYPE_AP:
                /* This part is triggered only during CSA */
-               if (!vif->csa_active || !mvmvif->ap_ibss_active)
+               if (!switching_chanctx || !mvmvif->ap_ibss_active)
                        goto out;
 
                mvmvif->csa_countdown = false;
@@ -2925,12 +2924,6 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
 
                disabled_vif = vif;
 
-               mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
-                                                         mvmvif->ap_sta_id);
-
-               if (!WARN_ON(!mvmsta))
-                       iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, true);
-
                iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
                break;
        default:
@@ -3166,7 +3159,8 @@ 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;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       u32 apply_time;
        int ret;
 
        mutex_lock(&mvm->mutex);
@@ -3187,7 +3181,6 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
 
                rcu_assign_pointer(mvm->csa_vif, vif);
 
-               mvmvif = iwl_mvm_vif_from_mac80211(vif);
                if (WARN_ONCE(mvmvif->csa_countdown,
                              "Previous CSA countdown didn't complete")) {
                        ret = -EBUSY;
@@ -3195,11 +3188,26 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
                }
 
                break;
+       case NL80211_IFTYPE_STATION:
+               apply_time = chsw->timestamp +
+                       (vif->bss_conf.beacon_int * chsw->count * 1024);
+
+               if (chsw->block_tx)
+                       iwl_mvm_csa_client_absent(mvm, vif);
+
+               iwl_mvm_schedule_csa_period(mvm, vif,
+                                           IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT,
+                                           apply_time);
+               break;
        default:
                break;
        }
 
-       ret = 0;
+       mvmvif->ps_disabled = true;
+
+       ret = iwl_mvm_power_update_ps(mvm);
+       if (ret)
+               goto out_unlock;
 
 out_unlock:
        mutex_unlock(&mvm->mutex);
@@ -3207,6 +3215,24 @@ out_unlock:
        return ret;
 }
 
+static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       int ret;
+
+       mutex_lock(&mvm->mutex);
+
+       mvmvif->ps_disabled = false;
+
+       ret = iwl_mvm_power_update_ps(mvm);
+
+       mutex_unlock(&mvm->mutex);
+
+       return ret;
+}
+
 static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
                              struct ieee80211_vif *vif, u32 queues, bool drop)
 {
@@ -3300,6 +3326,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
        .set_tim = iwl_mvm_set_tim,
 
        .pre_channel_switch = iwl_mvm_pre_channel_switch,
+       .post_channel_switch = iwl_mvm_post_channel_switch,
 
        .tdls_channel_switch = iwl_mvm_tdls_channel_switch,
        .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,