]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/iwlwifi/mvm/mac80211.c
iwlwifi: mvm: remove IWL_UCODE_TLV_API_CSA_FLOW
[karo-tx-linux.git] / drivers / net / wireless / iwlwifi / mvm / mac80211.c
index c85c0f12867af59123be70e8894d5e83ca692dfc..31a5b3f4266c3edaf26a05dfca208ddd2082f8ca 100644 (file)
@@ -323,7 +323,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
        hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
                                    IEEE80211_RADIOTAP_MCS_HAVE_STBC;
-       hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC;
+       hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
+               IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED;
        hw->rate_control_algorithm = "iwl-mvm-rs";
 
        /*
@@ -336,7 +337,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
        if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
-           IWL_UCODE_API(mvm->fw->ucode_ver) >= 9 &&
            !iwlwifi_mod_params.uapsd_disable) {
                hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
                hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
@@ -369,8 +369,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD)
                hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
 
-       if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_CSA_FLOW)
-               hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+       hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
        hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
        hw->wiphy->n_iface_combinations =
@@ -467,7 +466,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                mvm->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
                                    WIPHY_WOWLAN_DISCONNECT |
                                    WIPHY_WOWLAN_EAP_IDENTITY_REQ |
-                                   WIPHY_WOWLAN_RFKILL_RELEASE;
+                                   WIPHY_WOWLAN_RFKILL_RELEASE |
+                                   WIPHY_WOWLAN_NET_DETECT;
                if (!iwlwifi_mod_params.sw_crypto)
                        mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
                                             WIPHY_WOWLAN_GTK_REKEY_FAILURE |
@@ -476,6 +476,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                mvm->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS;
                mvm->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN;
                mvm->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN;
+               mvm->wowlan.max_nd_match_sets = IWL_SCAN_MAX_PROFILES;
                mvm->wowlan.tcp = &iwl_mvm_wowlan_tcp_support;
                hw->wiphy->wowlan = &mvm->wowlan;
        }
@@ -2574,9 +2575,15 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
 
        switch (vif->type) {
        case NL80211_IFTYPE_STATION:
-               /* Use aux roc framework (HS20) */
-               ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
-                                              vif, duration);
+               if (mvm->fw->ucode_capa.capa[0] &
+                   IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT) {
+                       /* Use aux roc framework (HS20) */
+                       ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
+                                                      vif, duration);
+                       goto out_unlock;
+               }
+               IWL_ERR(mvm, "hotspot not supported\n");
+               ret = -EINVAL;
                goto out_unlock;
        case NL80211_IFTYPE_P2P_DEVICE:
                /* handle below */
@@ -2847,6 +2854,25 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
        }
 
        if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
+               u32 duration = 2 * vif->bss_conf.beacon_int;
+
+               /* iwl_mvm_protect_session() reads directly from the
+                * device (the system time), so make sure it is
+                * available.
+                */
+               ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
+               if (ret)
+                       goto out_remove_binding;
+
+               /* Protect the session to make sure we hear the first
+                * beacon on the new channel.
+                */
+               iwl_mvm_protect_session(mvm, vif, duration, duration,
+                                       vif->bss_conf.beacon_int / 2,
+                                       true);
+
+               iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
+
                iwl_mvm_update_quotas(mvm, NULL);
        }
 
@@ -3143,6 +3169,20 @@ static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
 }
 #endif
 
+static void iwl_mvm_channel_switch(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif,
+                                  struct ieee80211_channel_switch *chsw)
+{
+       /* By implementing this operation, we prevent mac80211 from
+        * starting its own channel switch timer, so that we can call
+        * ieee80211_chswitch_done() ourselves at the right time
+        * (which is when the absence time event starts).
+        */
+
+       IWL_DEBUG_MAC80211(IWL_MAC80211_GET_MVM(hw),
+                          "dummy channel switch op\n");
+}
+
 static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
                                      struct ieee80211_vif *vif,
                                      struct ieee80211_channel_switch *chsw)
@@ -3192,6 +3232,12 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
 
                iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
                                            apply_time);
+               if (mvmvif->bf_data.bf_enabled) {
+                       ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
+                       if (ret)
+                               goto out_unlock;
+               }
+
                break;
        default:
                break;
@@ -3203,6 +3249,9 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
        if (ret)
                goto out_unlock;
 
+       /* we won't be on this channel any longer */
+       iwl_mvm_teardown_tdls_peers(mvm);
+
 out_unlock:
        mutex_unlock(&mvm->mutex);
 
@@ -3232,6 +3281,12 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
                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;
+
+               iwl_mvm_stop_session_protection(mvm, vif);
        }
 
        mvmvif->ps_disabled = false;
@@ -3336,6 +3391,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
 
        .set_tim = iwl_mvm_set_tim,
 
+       .channel_switch = iwl_mvm_channel_switch,
        .pre_channel_switch = iwl_mvm_pre_channel_switch,
        .post_channel_switch = iwl_mvm_post_channel_switch,