OSDN Git Service

wifi: iwlwifi: mvm: add some new MLD ops
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 28 Mar 2023 07:58:45 +0000 (10:58 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 30 Mar 2023 10:07:52 +0000 (12:07 +0200)
Add MLD version of bss_info_changed/switch_vif_chanctx/
config_iface_filter and conf_tx() callbacks.

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104948.9c83c253d610.Ibf2006be9ece87896c17cb43dfe3654ac73d81ff@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/sta.h

index b730b60..dae5e1b 100644 (file)
@@ -2433,9 +2433,8 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
                IWL_ERR(mvm, "Failed to config FW to work HE!\n");
 }
 
-static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm,
-                                 struct ieee80211_vif *vif,
-                                 u32 duration_override)
+void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                          u32 duration_override)
 {
        u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
        u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
@@ -2461,6 +2460,82 @@ static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm,
                                        min_duration, 500, false);
 }
 
+/* Handle association common part to MLD and non-MLD modes */
+void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
+                                           struct ieee80211_vif *vif,
+                                           u64 changes)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       int ret;
+
+       /* The firmware tracks the MU-MIMO group on its own.
+        * However, on HW restart we should restore this data.
+        */
+       if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
+           (changes & BSS_CHANGED_MU_GROUPS) && vif->bss_conf.mu_mimo_owner) {
+               ret = iwl_mvm_update_mu_groups(mvm, vif);
+               if (ret)
+                       IWL_ERR(mvm,
+                               "failed to update VHT MU_MIMO groups\n");
+       }
+
+       iwl_mvm_recalc_multicast(mvm);
+
+       /* reset rssi values */
+       mvmvif->bf_data.ave_beacon_signal = 0;
+
+       iwl_mvm_bt_coex_vif_change(mvm);
+       iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT,
+                           IEEE80211_SMPS_AUTOMATIC);
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_UMAC_SCAN))
+               iwl_mvm_config_scan(mvm);
+}
+
+/* Execute the common part for MLD and non-MLD modes */
+void iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
+                                            struct ieee80211_vif *vif,
+                                            u64 changes)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       int ret;
+
+       if (changes & BSS_CHANGED_BEACON_INFO) {
+               /* We received a beacon from the associated AP so
+                * remove the session protection.
+                */
+               iwl_mvm_stop_session_protection(mvm, vif);
+
+               iwl_mvm_sf_update(mvm, vif, false);
+               WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
+       }
+
+       if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS |
+                      /* Send power command on every beacon change,
+                       * because we may have not enabled beacon abort yet.
+                       */
+                      BSS_CHANGED_BEACON_INFO)) {
+               ret = iwl_mvm_power_update_mac(mvm);
+               if (ret)
+                       IWL_ERR(mvm, "failed to update power mode\n");
+       }
+
+       if (changes & BSS_CHANGED_CQM) {
+               IWL_DEBUG_MAC80211(mvm, "cqm info_changed\n");
+               /* reset cqm events tracking */
+               mvmvif->bf_data.last_cqm_event = 0;
+               if (mvmvif->bf_data.bf_enabled) {
+                       ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
+                       if (ret)
+                               IWL_ERR(mvm,
+                                       "failed to update CQM thresholds\n");
+               }
+       }
+
+       if (changes & BSS_CHANGED_BANDWIDTH)
+               iwl_mvm_apply_fw_smps_request(vif);
+}
+
 static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                             struct ieee80211_vif *vif,
                                             struct ieee80211_bss_conf *bss_conf,
@@ -2623,67 +2698,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                        vif->addr);
                }
 
-               /*
-                * The firmware tracks the MU-MIMO group on its own.
-                * However, on HW restart we should restore this data.
-                */
-               if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
-                   (changes & BSS_CHANGED_MU_GROUPS) && vif->bss_conf.mu_mimo_owner) {
-                       ret = iwl_mvm_update_mu_groups(mvm, vif);
-                       if (ret)
-                               IWL_ERR(mvm,
-                                       "failed to update VHT MU_MIMO groups\n");
-               }
-
-               iwl_mvm_recalc_multicast(mvm);
-
-               /* reset rssi values */
-               mvmvif->bf_data.ave_beacon_signal = 0;
-
-               iwl_mvm_bt_coex_vif_change(mvm);
-               iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT,
-                                   IEEE80211_SMPS_AUTOMATIC);
-               if (fw_has_capa(&mvm->fw->ucode_capa,
-                               IWL_UCODE_TLV_CAPA_UMAC_SCAN))
-                       iwl_mvm_config_scan(mvm);
-       }
-
-       if (changes & BSS_CHANGED_BEACON_INFO) {
-               /*
-                * We received a beacon from the associated AP so
-                * remove the session protection.
-                */
-               iwl_mvm_stop_session_protection(mvm, vif);
-
-               iwl_mvm_sf_update(mvm, vif, false);
-               WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
+               iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
        }
 
-       if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS |
-                      /*
-                       * Send power command on every beacon change,
-                       * because we may have not enabled beacon abort yet.
-                       */
-                      BSS_CHANGED_BEACON_INFO)) {
-               ret = iwl_mvm_power_update_mac(mvm);
-               if (ret)
-                       IWL_ERR(mvm, "failed to update power mode\n");
-       }
-
-       if (changes & BSS_CHANGED_CQM) {
-               IWL_DEBUG_MAC80211(mvm, "cqm info_changed\n");
-               /* reset cqm events tracking */
-               mvmvif->bf_data.last_cqm_event = 0;
-               if (mvmvif->bf_data.bf_enabled) {
-                       ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
-                       if (ret)
-                               IWL_ERR(mvm,
-                                       "failed to update CQM thresholds\n");
-               }
-       }
-
-       if (changes & BSS_CHANGED_BANDWIDTH)
-               iwl_mvm_apply_fw_smps_request(vif);
+       iwl_mvm_bss_info_changed_station_common(mvm, vif, changes);
 }
 
 bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
@@ -2968,6 +2986,22 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
                                     struct ieee80211_bss_conf *bss_conf,
                                     u64 changes)
 {
+       struct iwl_mvm_bss_info_changed_ops callbacks = {
+               .bss_info_changed_sta = iwl_mvm_bss_info_changed_station,
+               .bss_info_changed_ap_ibss = iwl_mvm_bss_info_changed_ap_ibss,
+       };
+
+       iwl_mvm_bss_info_changed_common(hw, vif, bss_conf, &callbacks,
+                                       changes);
+}
+
+void
+iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_bss_conf *bss_conf,
+                               struct iwl_mvm_bss_info_changed_ops *callbacks,
+                               u64 changes)
+{
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
        mutex_lock(&mvm->mutex);
@@ -2977,11 +3011,12 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
 
        switch (vif->type) {
        case NL80211_IFTYPE_STATION:
-               iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes);
+               callbacks->bss_info_changed_sta(mvm, vif, bss_conf, changes);
                break;
        case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_ADHOC:
-               iwl_mvm_bss_info_changed_ap_ibss(mvm, vif, bss_conf, changes);
+               callbacks->bss_info_changed_ap_ibss(mvm, vif, bss_conf,
+                                                   changes);
                break;
        case NL80211_IFTYPE_MONITOR:
                if (changes & BSS_CHANGED_MU_GROUPS)
@@ -4762,12 +4797,13 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
 
 static int
 iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
-                               struct ieee80211_vif_chanctx_switch *vifs)
+                               struct ieee80211_vif_chanctx_switch *vifs,
+                               struct iwl_mvm_switch_vif_chanctx_ops *ops)
 {
        int ret;
 
        mutex_lock(&mvm->mutex);
-       __iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
+       ops->__unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
        __iwl_mvm_remove_chanctx(mvm, vifs[0].old_ctx);
 
        ret = __iwl_mvm_add_chanctx(mvm, vifs[0].new_ctx);
@@ -4776,7 +4812,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
                goto out_reassign;
        }
 
-       ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
+       ret = ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
                                           true);
        if (ret) {
                IWL_ERR(mvm,
@@ -4799,8 +4835,8 @@ out_reassign:
                goto out_restart;
        }
 
-       if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
-                                        true)) {
+       if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
+                                     true)) {
                IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
                goto out_restart;
        }
@@ -4819,14 +4855,15 @@ out:
 
 static int
 iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
-                                   struct ieee80211_vif_chanctx_switch *vifs)
+                                   struct ieee80211_vif_chanctx_switch *vifs,
+                                   struct iwl_mvm_switch_vif_chanctx_ops *ops)
 {
        int ret;
 
        mutex_lock(&mvm->mutex);
-       __iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
+       ops->__unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
 
-       ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
+       ret = ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
                                           true);
        if (ret) {
                IWL_ERR(mvm,
@@ -4837,8 +4874,8 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
        goto out;
 
 out_reassign:
-       if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
-                                        true)) {
+       if (ops->__assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
+                                     true)) {
                IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
                goto out_restart;
        }
@@ -4855,10 +4892,13 @@ out:
        return ret;
 }
 
-static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
-                                     struct ieee80211_vif_chanctx_switch *vifs,
-                                     int n_vifs,
-                                     enum ieee80211_chanctx_switch_mode mode)
+/* Execute the common part for both MLD and non-MLD modes */
+int
+iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
+                                 struct ieee80211_vif_chanctx_switch *vifs,
+                                 int n_vifs,
+                                 enum ieee80211_chanctx_switch_mode mode,
+                                 struct iwl_mvm_switch_vif_chanctx_ops *ops)
 {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        int ret;
@@ -4869,10 +4909,10 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
 
        switch (mode) {
        case CHANCTX_SWMODE_SWAP_CONTEXTS:
-               ret = iwl_mvm_switch_vif_chanctx_swap(mvm, vifs);
+               ret = iwl_mvm_switch_vif_chanctx_swap(mvm, vifs, ops);
                break;
        case CHANCTX_SWMODE_REASSIGN_VIF:
-               ret = iwl_mvm_switch_vif_chanctx_reassign(mvm, vifs);
+               ret = iwl_mvm_switch_vif_chanctx_reassign(mvm, vifs, ops);
                break;
        default:
                ret = -EOPNOTSUPP;
@@ -4882,6 +4922,19 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
        return ret;
 }
 
+static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
+                                     struct ieee80211_vif_chanctx_switch *vifs,
+                                     int n_vifs,
+                                     enum ieee80211_chanctx_switch_mode mode)
+{
+       struct iwl_mvm_switch_vif_chanctx_ops ops = {
+               .__assign_vif_chanctx = __iwl_mvm_assign_vif_chanctx,
+               .__unassign_vif_chanctx = __iwl_mvm_unassign_vif_chanctx,
+       };
+
+       return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops);
+}
+
 static int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw)
 {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
index 36c87d7..9d97098 100644 (file)
@@ -369,12 +369,239 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
                                            &callbacks);
 }
 
+static void
+iwl_mvm_mld_bss_info_changed_station(struct iwl_mvm *mvm,
+                                    struct ieee80211_vif *vif,
+                                    struct ieee80211_bss_conf *bss_conf,
+                                    u64 changes)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       int ret;
+       u32 link_changes = 0;
+       bool has_he = vif->bss_conf.he_support &&
+                         !iwlwifi_mod_params.disable_11ax;
+       bool has_eht = vif->bss_conf.eht_support &&
+                         !iwlwifi_mod_params.disable_11be;
+
+       if (changes & BSS_CHANGED_ASSOC && vif->cfg.assoc &&
+           (has_he || has_eht)) {
+               IWL_DEBUG_MAC80211(mvm, "Associated in HE mode\n");
+               link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
+       }
+
+       /* Update MU EDCA params */
+       if (changes & BSS_CHANGED_QOS && vif->cfg.assoc &&
+           (has_he || has_eht))
+               link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS;
+
+       /* Update EHT Puncturing info */
+       if (changes & BSS_CHANGED_EHT_PUNCTURING && vif->cfg.assoc && has_eht)
+               link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS;
+
+       if (link_changes) {
+               ret = iwl_mvm_link_changed(mvm, vif, link_changes, true);
+               if (ret)
+                       IWL_ERR(mvm, "failed to update link\n");
+       }
+
+       ret = iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
+       if (ret)
+               IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
+
+       memcpy(mvmvif->deflink.bssid, bss_conf->bssid, ETH_ALEN);
+       mvmvif->associated = vif->cfg.assoc;
+
+       if (changes & BSS_CHANGED_ASSOC) {
+               if (vif->cfg.assoc) {
+                       /* clear statistics to get clean beacon counter */
+                       iwl_mvm_request_statistics(mvm, true);
+                       memset(&mvmvif->deflink.beacon_stats, 0,
+                              sizeof(mvmvif->deflink.beacon_stats));
+
+                       if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
+                                     &mvm->status) &&
+                           !vif->bss_conf.dtim_period) {
+                               /* If we're not restarting and still haven't
+                                * heard a beacon (dtim period unknown) then
+                                * make sure we still have enough minimum time
+                                * remaining in the time event, since the auth
+                                * might actually have taken quite a while
+                                * (especially for SAE) and so the remaining
+                                * time could be small without us having heard
+                                * a beacon yet.
+                                */
+                               iwl_mvm_protect_assoc(mvm, vif, 0);
+                       }
+
+                       iwl_mvm_sf_update(mvm, vif, false);
+                       iwl_mvm_power_vif_assoc(mvm, vif);
+                       if (vif->p2p) {
+                               iwl_mvm_update_smps(mvm, vif,
+                                                   IWL_MVM_SMPS_REQ_PROT,
+                                                   IEEE80211_SMPS_DYNAMIC);
+                       }
+               } else if (mvmvif->deflink.ap_sta_id != IWL_MVM_INVALID_STA) {
+                       iwl_mvm_mei_host_disassociated(mvm);
+                       /* If update fails - SF might be running in associated
+                        * mode while disassociated - which is forbidden.
+                        */
+                       ret = iwl_mvm_sf_update(mvm, vif, false);
+                       WARN_ONCE(ret &&
+                                 !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+                                           &mvm->status),
+                                 "Failed to update SF upon disassociation\n");
+
+                       /* If we get an assert during the connection (after the
+                        * station has been added, but before the vif is set
+                        * to associated), mac80211 will re-add the station and
+                        * then configure the vif. Since the vif is not
+                        * associated, we would remove the station here and
+                        * this would fail the recovery.
+                        */
+                       if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
+                                     &mvm->status)) {
+                               /* first remove remaining keys */
+                               iwl_mvm_sec_key_remove_ap(mvm, vif);
+
+                               /* Remove AP station now that
+                                * the MAC is unassoc
+                                */
+                               ret = iwl_mvm_mld_rm_sta_id(mvm, vif,
+                                                           mvmvif->deflink.ap_sta_id);
+                               if (ret)
+                                       IWL_ERR(mvm,
+                                               "failed to remove AP station\n");
+
+                               mvmvif->deflink.ap_sta_id = IWL_MVM_INVALID_STA;
+                       }
+               }
+
+               iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
+       }
+
+       iwl_mvm_bss_info_changed_station_common(mvm, vif, changes);
+}
+
+static void
+iwl_mvm_mld_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
+                                    struct ieee80211_vif *vif,
+                                    struct ieee80211_bss_conf *bss_conf,
+                                    u64 changes)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       u32 link_changes = LINK_CONTEXT_MODIFY_PROTECT_FLAGS |
+                          LINK_CONTEXT_MODIFY_QOS_PARAMS;
+
+       /* Changes will be applied when the AP/IBSS is started */
+       if (!mvmvif->ap_ibss_active)
+               return;
+
+       if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
+                      BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS) &&
+                      iwl_mvm_link_changed(mvm, vif, link_changes, true))
+               IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
+
+       /* Need to send a new beacon template to the FW */
+       if (changes & BSS_CHANGED_BEACON &&
+           iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
+               IWL_WARN(mvm, "Failed updating beacon data\n");
+
+       if (changes & BSS_CHANGED_FTM_RESPONDER) {
+               int ret = iwl_mvm_ftm_start_responder(mvm, vif);
+
+               if (ret)
+                       IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
+                                ret);
+       }
+}
+
+static void iwl_mvm_mld_bss_info_changed(struct ieee80211_hw *hw,
+                                        struct ieee80211_vif *vif,
+                                        struct ieee80211_bss_conf *bss_conf,
+                                        u64 changes)
+{
+       struct iwl_mvm_bss_info_changed_ops callbacks = {
+               .bss_info_changed_sta = iwl_mvm_mld_bss_info_changed_station,
+               .bss_info_changed_ap_ibss =
+                       iwl_mvm_mld_bss_info_changed_ap_ibss,
+       };
+
+       iwl_mvm_bss_info_changed_common(hw, vif, bss_conf, &callbacks,
+                                       changes);
+}
+
+static int
+iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw,
+                              struct ieee80211_vif_chanctx_switch *vifs,
+                              int n_vifs,
+                              enum ieee80211_chanctx_switch_mode mode)
+{
+       struct iwl_mvm_switch_vif_chanctx_ops ops = {
+               .__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx,
+               .__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx,
+       };
+
+       return iwl_mvm_switch_vif_chanctx_common(hw, vifs, n_vifs, mode, &ops);
+}
+
+static void iwl_mvm_mld_config_iface_filter(struct ieee80211_hw *hw,
+                                           struct ieee80211_vif *vif,
+                                           unsigned int filter_flags,
+                                           unsigned int changed_flags)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+       /* We support only filter for probe requests */
+       if (!(changed_flags & FIF_PROBE_REQ))
+               return;
+
+       /* Supported only for p2p client interfaces */
+       if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc ||
+           !vif->p2p)
+               return;
+
+       mutex_lock(&mvm->mutex);
+       iwl_mvm_mld_mac_ctxt_changed(mvm, vif, false);
+       mutex_unlock(&mvm->mutex);
+}
+
+static int
+iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
+                       struct ieee80211_vif *vif,
+                       unsigned int link_id, u16 ac,
+                       const struct ieee80211_tx_queue_params *params)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       mvmvif->deflink.queue_params[ac] = *params;
+
+       /* No need to update right away, we'll get BSS_CHANGED_QOS
+        * The exception is P2P_DEVICE interface which needs immediate update.
+        */
+       if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
+               int ret;
+
+               mutex_lock(&mvm->mutex);
+               ret = iwl_mvm_link_changed(mvm, vif,
+                                          LINK_CONTEXT_MODIFY_QOS_PARAMS,
+                                          true);
+               mutex_unlock(&mvm->mutex);
+               return ret;
+       }
+       return 0;
+}
+
 const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
        .add_interface = iwl_mvm_mld_mac_add_interface,
        .remove_interface = iwl_mvm_mld_mac_remove_interface,
+       .config_iface_filter = iwl_mvm_mld_config_iface_filter,
        .assign_vif_chanctx = iwl_mvm_mld_assign_vif_chanctx,
        .unassign_vif_chanctx = iwl_mvm_mld_unassign_vif_chanctx,
+       .switch_vif_chanctx = iwl_mvm_mld_switch_vif_chanctx,
        .join_ibss = iwl_mvm_mld_start_ap_ibss,
        .leave_ibss = iwl_mvm_mld_stop_ap_ibss,
        .sta_state = iwl_mvm_mld_mac_sta_state,
+       .conf_tx = iwl_mvm_mld_mac_conf_tx,
+       .bss_info_changed = iwl_mvm_mld_bss_info_changed,
 };
index 0e9c87b..16723d5 100644 (file)
@@ -536,6 +536,17 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        return ret;
 }
 
+int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                         u8 sta_id)
+{
+       int ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id);
+
+       lockdep_assert_held(&mvm->mutex);
+
+       RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL);
+       return ret;
+}
+
 static void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm,
                                              struct ieee80211_sta *sta,
                                              bool disable)
index 24884e1..2ea224a 100644 (file)
@@ -1789,6 +1789,48 @@ bool iwl_mvm_start_ap_ibss_common(struct ieee80211_hw *hw,
 void iwl_mvm_stop_ap_ibss_common(struct iwl_mvm *mvm,
                                 struct ieee80211_vif *vif);
 
+/* BSS Info */
+/**
+ * struct iwl_mvm_bss_info_changed_ops - callbacks for the bss_info_changed()
+ *
+ * Since the only difference between both MLD and
+ * non-MLD versions of bss_info_changed() is these function calls,
+ * each version will send its specific function calls to
+ * %iwl_mvm_bss_info_changed_common().
+ *
+ * @bss_info_changed_sta: pointer to the function that handles changes
+ *     in bss_info in sta mode
+ * @bss_info_changed_ap_ibss: pointer to the function that handles changes
+ *     in bss_info in ap and ibss modes
+ */
+struct iwl_mvm_bss_info_changed_ops {
+       void (*bss_info_changed_sta)(struct iwl_mvm *mvm,
+                                    struct ieee80211_vif *vif,
+                                    struct ieee80211_bss_conf *bss_conf,
+                                    u64 changes);
+       void (*bss_info_changed_ap_ibss)(struct iwl_mvm *mvm,
+                                        struct ieee80211_vif *vif,
+                                        struct ieee80211_bss_conf *bss_conf,
+                                        u64 changes);
+};
+
+void
+iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_bss_conf *bss_conf,
+                               struct iwl_mvm_bss_info_changed_ops *callbacks,
+                               u64 changes);
+void iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
+                                            struct ieee80211_vif *vif,
+                                            u64 changes);
+void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
+                                           struct ieee80211_vif *vif,
+                                           u64 changes);
+
+/*Session Protection */
+void iwl_mvm_protect_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                          u32 duration_override);
+
 /* Quota management */
 static inline size_t iwl_mvm_quota_cmd_size(struct iwl_mvm *mvm)
 {
@@ -2232,6 +2274,37 @@ static inline u8 iwl_mvm_phy_band_from_nl80211(enum nl80211_band band)
 void iwl_mvm_channel_switch_disconnect_wk(struct work_struct *wk);
 
 /* Channel Context */
+/**
+ * struct iwl_mvm_switch_vif_chanctx_ops - callbacks for switch_vif_chanctx()
+ *
+ * Since the only difference between both MLD and
+ * non-MLD versions of switch_vif_chanctx() is these function calls,
+ * each version will send its specific function calls to
+ * %iwl_mvm_switch_vif_chanctx_common().
+ *
+ * @__assign_vif_chanctx: pointer to the function that assigns a chanctx to
+ *     a given vif
+ * @__unassign_vif_chanctx: pointer to the function that unassigns a chanctx to
+ *     a given vif
+ */
+struct iwl_mvm_switch_vif_chanctx_ops {
+       int (*__assign_vif_chanctx)(struct iwl_mvm *mvm,
+                                   struct ieee80211_vif *vif,
+                                   struct ieee80211_chanctx_conf *ctx,
+                                   bool switching_chanctx);
+       void (*__unassign_vif_chanctx)(struct iwl_mvm *mvm,
+                                      struct ieee80211_vif *vif,
+                                      struct ieee80211_chanctx_conf *ctx,
+                                      bool switching_chanctx);
+};
+
+int
+iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
+                                 struct ieee80211_vif_chanctx_switch *vifs,
+                                 int n_vifs,
+                                 enum ieee80211_chanctx_switch_mode mode,
+                                 struct iwl_mvm_switch_vif_chanctx_ops *ops);
+
 bool __iwl_mvm_assign_vif_chanctx_common(struct iwl_mvm *mvm,
                                         struct ieee80211_vif *vif,
                                         struct ieee80211_chanctx_conf *ctx,
index fa64492..770516b 100644 (file)
@@ -631,6 +631,8 @@ int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta);
 int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta);
+int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+                         u8 sta_id);
 
 /* Queues */
 void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,