wifi: iwlwifi: mvm: implement key link switching
authorJohannes Berg <johannes.berg@intel.com>
Sun, 16 Apr 2023 12:47:36 +0000 (15:47 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 17 Apr 2023 07:53:25 +0000 (09:53 +0200)
Implement switching keys from one set of firmware station IDs
to another set, during link switch.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230416154301.c6a777dd5e47.I693f7fd7c52fe8b51a58af69d45488511367f49e@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

index a8ab354..8853821 100644 (file)
@@ -97,6 +97,59 @@ static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
        return flags;
 }
 
+struct iwl_mvm_sta_key_update_data {
+       struct ieee80211_sta *sta;
+       u32 old_sta_mask;
+       u32 new_sta_mask;
+       int err;
+};
+
+static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif,
+                                      struct ieee80211_sta *sta,
+                                      struct ieee80211_key_conf *key,
+                                      void *_data)
+{
+       u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
+       struct iwl_mvm_sta_key_update_data *data = _data;
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       struct iwl_sec_key_cmd cmd = {
+               .action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
+               .u.modify.old_sta_mask = cpu_to_le32(data->old_sta_mask),
+               .u.modify.new_sta_mask = cpu_to_le32(data->new_sta_mask),
+               .u.modify.key_id = cpu_to_le32(key->keyidx),
+               .u.modify.key_flags =
+                       cpu_to_le32(iwl_mvm_get_sec_flags(mvm, vif, sta, key)),
+       };
+       int err;
+
+       /* only need to do this for pairwise keys (link_id == -1) */
+       if (sta != data->sta || key->link_id >= 0)
+               return;
+
+       err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cmd), &cmd);
+
+       if (err)
+               data->err = err;
+}
+
+int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_sta *sta,
+                               u32 old_sta_mask,
+                               u32 new_sta_mask)
+{
+       struct iwl_mvm_sta_key_update_data data = {
+               .sta = sta,
+               .old_sta_mask = old_sta_mask,
+               .new_sta_mask = new_sta_mask,
+       };
+
+       ieee80211_iter_keys_rcu(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
+                               &data);
+       return data.err;
+}
+
 static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
                                 u32 key_flags, u32 keyidx, u32 flags)
 {
index 36d83e2..6543673 100644 (file)
@@ -994,6 +994,7 @@ static int iwl_mvm_mld_update_sta_baids(struct iwl_mvm *mvm,
 }
 
 static int iwl_mvm_mld_update_sta_resources(struct iwl_mvm *mvm,
+                                           struct ieee80211_vif *vif,
                                            struct ieee80211_sta *sta,
                                            u32 old_sta_mask,
                                            u32 new_sta_mask)
@@ -1006,6 +1007,12 @@ static int iwl_mvm_mld_update_sta_resources(struct iwl_mvm *mvm,
        if (ret)
                return ret;
 
+       ret = iwl_mvm_mld_update_sta_keys(mvm, vif, sta,
+                                         old_sta_mask,
+                                         new_sta_mask);
+       if (ret)
+               return ret;
+
        return iwl_mvm_mld_update_sta_baids(mvm, old_sta_mask, new_sta_mask);
 }
 
@@ -1045,7 +1052,7 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
        }
 
        if (sta_mask_to_rem) {
-               ret = iwl_mvm_mld_update_sta_resources(mvm, sta,
+               ret = iwl_mvm_mld_update_sta_resources(mvm, vif, sta,
                                                       current_sta_mask,
                                                       current_sta_mask &
                                                        ~sta_mask_to_rem);
@@ -1123,7 +1130,7 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
        }
 
        if (sta_mask_added) {
-               ret = iwl_mvm_mld_update_sta_resources(mvm, sta,
+               ret = iwl_mvm_mld_update_sta_resources(mvm, vif, sta,
                                                       current_sta_mask,
                                                       current_sta_mask |
                                                        sta_mask_added);
index 29a87d1..203eb72 100644 (file)
@@ -2332,6 +2332,11 @@ void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
                               struct ieee80211_vif *vif,
                               struct iwl_mvm_vif_link_info *link,
                               unsigned int link_id);
+int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_sta *sta,
+                               u32 old_sta_mask,
+                               u32 new_sta_mask);
 
 int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm,
                            struct iwl_rfi_lut_entry *rfi_table);