@@ -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)
{
@@ -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);
@@ -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);