@@ -450,9 +450,9 @@ static void iwl_mvm_wowlan_get_rsc_v5_data(struct ieee80211_hw *hw,
450
450
}
451
451
452
452
static int iwl_mvm_wowlan_config_rsc_tsc (struct iwl_mvm * mvm ,
453
- struct ieee80211_vif * vif )
453
+ struct ieee80211_vif * vif ,
454
+ struct iwl_mvm_vif_link_info * mvm_link )
454
455
{
455
- struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 (vif );
456
456
int ver = iwl_fw_lookup_cmd_ver (mvm -> fw , WOWLAN_TSC_RSC_PARAM ,
457
457
IWL_FW_CMD_VER_UNKNOWN );
458
458
int ret ;
@@ -470,7 +470,7 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
470
470
for (i = 0 ; i < ARRAY_SIZE (data .rsc -> mcast_key_id_map ); i ++ )
471
471
data .rsc -> mcast_key_id_map [i ] =
472
472
IWL_MCAST_KEY_MAP_INVALID ;
473
- data .rsc -> sta_id = cpu_to_le32 (mvmvif -> deflink . ap_sta_id );
473
+ data .rsc -> sta_id = cpu_to_le32 (mvm_link -> ap_sta_id );
474
474
475
475
ieee80211_iter_keys (mvm -> hw , vif ,
476
476
iwl_mvm_wowlan_get_rsc_v5_data ,
@@ -494,7 +494,7 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
494
494
if (ver == 4 ) {
495
495
size = sizeof (* data .rsc_tsc );
496
496
data .rsc_tsc -> sta_id =
497
- cpu_to_le32 (mvmvif -> deflink . ap_sta_id );
497
+ cpu_to_le32 (mvm_link -> ap_sta_id );
498
498
} else {
499
499
/* ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN */
500
500
size = sizeof (data .rsc_tsc -> params );
@@ -668,10 +668,9 @@ static int iwl_mvm_send_patterns_v1(struct iwl_mvm *mvm,
668
668
}
669
669
670
670
static int iwl_mvm_send_patterns (struct iwl_mvm * mvm ,
671
- struct ieee80211_vif * vif ,
671
+ struct iwl_mvm_vif_link_info * mvm_link ,
672
672
struct cfg80211_wowlan * wowlan )
673
673
{
674
- struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 (vif );
675
674
struct iwl_wowlan_patterns_cmd * pattern_cmd ;
676
675
struct iwl_host_cmd cmd = {
677
676
.id = WOWLAN_PATTERNS ,
@@ -693,7 +692,7 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
693
692
694
693
pattern_cmd -> n_patterns = wowlan -> n_patterns ;
695
694
if (ver >= 3 )
696
- pattern_cmd -> sta_id = mvmvif -> deflink . ap_sta_id ;
695
+ pattern_cmd -> sta_id = mvm_link -> ap_sta_id ;
697
696
698
697
for (i = 0 ; i < wowlan -> n_patterns ; i ++ ) {
699
698
int mask_len = DIV_ROUND_UP (wowlan -> patterns [i ].pattern_len , 8 );
@@ -730,7 +729,8 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
730
729
struct iwl_time_quota_data * quota ;
731
730
u32 status ;
732
731
733
- if (WARN_ON_ONCE (iwl_mvm_is_cdb_supported (mvm )))
732
+ if (WARN_ON_ONCE (iwl_mvm_is_cdb_supported (mvm ) ||
733
+ ieee80211_vif_is_mld (vif )))
734
734
return - EINVAL ;
735
735
736
736
/* add back the PHY */
@@ -987,7 +987,8 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
987
987
}
988
988
989
989
static int iwl_mvm_wowlan_config_key_params (struct iwl_mvm * mvm ,
990
- struct ieee80211_vif * vif )
990
+ struct ieee80211_vif * vif ,
991
+ struct iwl_mvm_vif_link_info * mvm_link )
991
992
{
992
993
bool unified = fw_has_capa (& mvm -> fw -> ucode_capa ,
993
994
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG );
@@ -1016,7 +1017,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
1016
1017
return - EIO ;
1017
1018
}
1018
1019
1019
- ret = iwl_mvm_wowlan_config_rsc_tsc (mvm , vif );
1020
+ ret = iwl_mvm_wowlan_config_rsc_tsc (mvm , vif , mvm_link );
1020
1021
if (ret )
1021
1022
return ret ;
1022
1023
@@ -1030,7 +1031,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
1030
1031
if (ver == 2 ) {
1031
1032
size = sizeof (tkip_data .tkip );
1032
1033
tkip_data .tkip .sta_id =
1033
- cpu_to_le32 (mvmvif -> deflink . ap_sta_id );
1034
+ cpu_to_le32 (mvm_link -> ap_sta_id );
1034
1035
} else if (ver == 1 || ver == IWL_FW_CMD_VER_UNKNOWN ) {
1035
1036
size = sizeof (struct iwl_wowlan_tkip_params_cmd_ver_1 );
1036
1037
} else {
@@ -1079,7 +1080,7 @@ static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
1079
1080
kek_kck_cmd .kek_len = cpu_to_le16 (mvmvif -> rekey_data .kek_len );
1080
1081
kek_kck_cmd .replay_ctr = mvmvif -> rekey_data .replay_ctr ;
1081
1082
kek_kck_cmd .akm = cpu_to_le32 (mvmvif -> rekey_data .akm );
1082
- kek_kck_cmd .sta_id = cpu_to_le32 (mvmvif -> deflink . ap_sta_id );
1083
+ kek_kck_cmd .sta_id = cpu_to_le32 (mvm_link -> ap_sta_id );
1083
1084
1084
1085
if (cmd_ver == 4 ) {
1085
1086
cmd_size = sizeof (struct iwl_wowlan_kek_kck_material_cmd_v4 );
@@ -1112,6 +1113,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
1112
1113
struct cfg80211_wowlan * wowlan ,
1113
1114
struct iwl_wowlan_config_cmd * wowlan_config_cmd ,
1114
1115
struct ieee80211_vif * vif , struct iwl_mvm_vif * mvmvif ,
1116
+ struct iwl_mvm_vif_link_info * mvm_link ,
1115
1117
struct ieee80211_sta * ap_sta )
1116
1118
{
1117
1119
int ret ;
@@ -1130,7 +1132,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
1130
1132
return ret ;
1131
1133
}
1132
1134
1133
- ret = iwl_mvm_wowlan_config_key_params (mvm , vif );
1135
+ ret = iwl_mvm_wowlan_config_key_params (mvm , vif , mvm_link );
1134
1136
if (ret )
1135
1137
return ret ;
1136
1138
@@ -1142,7 +1144,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
1142
1144
1143
1145
if (fw_has_api (& mvm -> fw -> ucode_capa ,
1144
1146
IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE ))
1145
- ret = iwl_mvm_send_patterns (mvm , vif , wowlan );
1147
+ ret = iwl_mvm_send_patterns (mvm , mvm_link , wowlan );
1146
1148
else
1147
1149
ret = iwl_mvm_send_patterns_v1 (mvm , wowlan );
1148
1150
if (ret )
@@ -1223,6 +1225,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1223
1225
struct ieee80211_vif * vif = NULL ;
1224
1226
struct iwl_mvm_vif * mvmvif = NULL ;
1225
1227
struct ieee80211_sta * ap_sta = NULL ;
1228
+ struct iwl_mvm_vif_link_info * mvm_link ;
1226
1229
struct iwl_d3_manager_config d3_cfg_cmd_data = {
1227
1230
/*
1228
1231
* Program the minimum sleep time to 10 seconds, as many
@@ -1237,7 +1240,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1237
1240
.data [0 ] = & d3_cfg_cmd_data ,
1238
1241
.len [0 ] = sizeof (d3_cfg_cmd_data ),
1239
1242
};
1240
- int ret ;
1243
+ int ret , primary_link ;
1241
1244
int len __maybe_unused ;
1242
1245
bool unified_image = fw_has_capa (& mvm -> fw -> ucode_capa ,
1243
1246
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG );
@@ -1251,21 +1254,44 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1251
1254
return - EINVAL ;
1252
1255
}
1253
1256
1257
+ vif = iwl_mvm_get_bss_vif (mvm );
1258
+ if (IS_ERR_OR_NULL (vif ))
1259
+ return 1 ;
1260
+
1261
+ if (ieee80211_vif_is_mld (vif ) && vif -> cfg .assoc ) {
1262
+ /*
1263
+ * Select the 'best' link. May need to revisit, it seems
1264
+ * better to not optimize for throughput but rather range,
1265
+ * reliability and power here - and select 2.4 GHz ...
1266
+ */
1267
+ primary_link =
1268
+ iwl_mvm_mld_get_primary_link (mvm , vif ,
1269
+ vif -> active_links );
1270
+
1271
+ if (WARN_ONCE (primary_link < 0 , "no primary link in 0x%x\n" ,
1272
+ vif -> active_links ))
1273
+ primary_link = __ffs (vif -> active_links );
1274
+
1275
+ ret = ieee80211_set_active_links (vif , BIT (primary_link ));
1276
+ if (ret )
1277
+ return ret ;
1278
+ } else {
1279
+ primary_link = 0 ;
1280
+ }
1281
+
1254
1282
mutex_lock (& mvm -> mutex );
1255
1283
1256
1284
set_bit (IWL_MVM_STATUS_IN_D3 , & mvm -> status );
1257
1285
1258
1286
synchronize_net ();
1259
1287
1260
- vif = iwl_mvm_get_bss_vif (mvm );
1261
- if (IS_ERR_OR_NULL (vif )) {
1262
- ret = 1 ;
1263
- goto out_noreset ;
1264
- }
1265
-
1266
1288
mvmvif = iwl_mvm_vif_from_mac80211 (vif );
1267
1289
1268
- if (mvmvif -> deflink .ap_sta_id == IWL_MVM_INVALID_STA ) {
1290
+ mvm_link = mvmvif -> link [primary_link ];
1291
+ if (WARN_ON_ONCE (!mvm_link ))
1292
+ return - EINVAL ;
1293
+
1294
+ if (mvm_link -> ap_sta_id == IWL_MVM_INVALID_STA ) {
1269
1295
/* if we're not associated, this must be netdetect */
1270
1296
if (!wowlan -> nd_config ) {
1271
1297
ret = 1 ;
@@ -1281,10 +1307,10 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1281
1307
} else {
1282
1308
struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
1283
1309
1284
- wowlan_config_cmd .sta_id = mvmvif -> deflink . ap_sta_id ;
1310
+ wowlan_config_cmd .sta_id = mvm_link -> ap_sta_id ;
1285
1311
1286
1312
ap_sta = rcu_dereference_protected (
1287
- mvm -> fw_id_to_mac_id [mvmvif -> deflink . ap_sta_id ],
1313
+ mvm -> fw_id_to_mac_id [mvm_link -> ap_sta_id ],
1288
1314
lockdep_is_held (& mvm -> mutex ));
1289
1315
if (IS_ERR_OR_NULL (ap_sta )) {
1290
1316
ret = - EINVAL ;
@@ -1296,7 +1322,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
1296
1322
if (ret )
1297
1323
goto out_noreset ;
1298
1324
ret = iwl_mvm_wowlan_config (mvm , wowlan , & wowlan_config_cmd ,
1299
- vif , mvmvif , ap_sta );
1325
+ vif , mvmvif , mvm_link , ap_sta );
1300
1326
if (ret )
1301
1327
goto out ;
1302
1328
@@ -2846,6 +2872,9 @@ iwl_mvm_choose_query_wakeup_reasons(struct iwl_mvm *mvm,
2846
2872
u8 sta_id = mvm -> net_detect ? IWL_MVM_INVALID_STA :
2847
2873
mvmvif -> deflink .ap_sta_id ;
2848
2874
2875
+ /* bug - FW with MLO has status notification */
2876
+ WARN_ON (ieee80211_vif_is_mld (vif ));
2877
+
2849
2878
d3_data -> status = iwl_mvm_send_wowlan_get_status (mvm , sta_id );
2850
2879
}
2851
2880
0 commit comments