@@ -454,37 +454,41 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
454
454
}
455
455
456
456
static void
457
- iwl_mvm_mld_bss_info_changed_station (struct iwl_mvm * mvm ,
458
- struct ieee80211_vif * vif ,
459
- struct ieee80211_bss_conf * bss_conf ,
460
- u64 changes )
457
+ iwl_mvm_mld_link_info_changed_station (struct iwl_mvm * mvm ,
458
+ struct ieee80211_vif * vif ,
459
+ struct ieee80211_bss_conf * link_conf ,
460
+ u64 changes )
461
461
{
462
462
struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 (vif );
463
- int ret ;
463
+ bool has_he , has_eht ;
464
464
u32 link_changes = 0 ;
465
- bool has_he = vif -> bss_conf .he_support &&
466
- !iwlwifi_mod_params .disable_11ax ;
467
- bool has_eht = vif -> bss_conf .eht_support &&
468
- !iwlwifi_mod_params .disable_11be ;
465
+ int ret ;
466
+
467
+ if (WARN_ON_ONCE (!mvmvif -> link [link_conf -> link_id ]))
468
+ return ;
469
+
470
+ has_he = link_conf -> he_support && !iwlwifi_mod_params .disable_11ax ;
471
+ has_eht = link_conf -> eht_support && !iwlwifi_mod_params .disable_11be ;
469
472
470
- if (changes & BSS_CHANGED_ASSOC && vif -> cfg .assoc &&
471
- (has_he || has_eht )) {
473
+ /* Update EDCA params */
474
+ if (changes & BSS_CHANGED_QOS && vif -> cfg .assoc && link_conf -> qos )
475
+ link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS ;
476
+
477
+ if (changes & BSS_CHANGED_ERP_SLOT )
478
+ link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO ;
479
+
480
+ if (vif -> cfg .assoc && (has_he || has_eht )) {
472
481
IWL_DEBUG_MAC80211 (mvm , "Associated in HE mode\n" );
473
482
link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS ;
474
483
}
475
484
476
- /* Update MU EDCA params */
477
- if (changes & BSS_CHANGED_QOS && vif -> cfg .assoc &&
478
- (has_he || has_eht ))
479
- link_changes |= LINK_CONTEXT_MODIFY_QOS_PARAMS ;
480
-
481
485
/* Update EHT Puncturing info */
482
486
if (changes & BSS_CHANGED_EHT_PUNCTURING && vif -> cfg .assoc && has_eht )
483
487
link_changes |= LINK_CONTEXT_MODIFY_EHT_PARAMS ;
484
488
485
489
if (link_changes ) {
486
- ret = iwl_mvm_link_changed (mvm , vif , & vif -> bss_conf ,
487
- link_changes , true);
490
+ ret = iwl_mvm_link_changed (mvm , vif , link_conf , link_changes ,
491
+ true);
488
492
if (ret )
489
493
IWL_ERR (mvm , "failed to update link\n" );
490
494
}
@@ -493,85 +497,139 @@ iwl_mvm_mld_bss_info_changed_station(struct iwl_mvm *mvm,
493
497
if (ret )
494
498
IWL_ERR (mvm , "failed to update MAC %pM\n" , vif -> addr );
495
499
496
- memcpy (mvmvif -> deflink .bssid , bss_conf -> bssid , ETH_ALEN );
500
+ memcpy (mvmvif -> link [link_conf -> link_id ]-> bssid , link_conf -> bssid ,
501
+ ETH_ALEN );
502
+
503
+ iwl_mvm_bss_info_changed_station_common (mvm , vif , link_conf , changes );
504
+ }
505
+
506
+ static bool iwl_mvm_mld_vif_have_valid_ap_sta (struct iwl_mvm_vif * mvmvif )
507
+ {
508
+ int i ;
509
+
510
+ for_each_mvm_vif_valid_link (mvmvif , i ) {
511
+ if (mvmvif -> link [i ]-> ap_sta_id != IWL_MVM_INVALID_STA )
512
+ return true;
513
+ }
514
+
515
+ return false;
516
+ }
517
+
518
+ static void iwl_mvm_mld_vif_delete_all_stas (struct iwl_mvm * mvm ,
519
+ struct ieee80211_vif * vif )
520
+ {
521
+ struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 (vif );
522
+ int i , ret ;
523
+
524
+ if (test_bit (IWL_MVM_STATUS_IN_HW_RESTART , & mvm -> status ))
525
+ return ;
526
+
527
+ iwl_mvm_sec_key_remove_ap (mvm , vif );
528
+
529
+ for_each_mvm_vif_valid_link (mvmvif , i ) {
530
+ struct iwl_mvm_vif_link_info * link = mvmvif -> link [i ];
531
+
532
+ if (!link )
533
+ continue ;
534
+
535
+ ret = iwl_mvm_mld_rm_sta_id (mvm , vif , link -> ap_sta_id );
536
+ if (ret )
537
+ IWL_ERR (mvm , "failed to remove AP station\n" );
538
+
539
+ link -> ap_sta_id = IWL_MVM_INVALID_STA ;
540
+ }
541
+ }
542
+
543
+ static void iwl_mvm_mld_vif_cfg_changed_station (struct iwl_mvm * mvm ,
544
+ struct ieee80211_vif * vif ,
545
+ u64 changes )
546
+ {
547
+ struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 (vif );
548
+ struct ieee80211_bss_conf * link_conf ;
549
+ bool protect = false;
550
+ unsigned int i ;
551
+ int ret ;
552
+
553
+ ret = iwl_mvm_mld_mac_ctxt_changed (mvm , vif , false);
554
+ if (ret )
555
+ IWL_ERR (mvm , "failed to update MAC %pM\n" , vif -> addr );
556
+
497
557
mvmvif -> associated = vif -> cfg .assoc ;
498
558
499
- if (changes & BSS_CHANGED_ASSOC ) {
500
- if (vif -> cfg .assoc ) {
501
- /* clear statistics to get clean beacon counter */
502
- iwl_mvm_request_statistics (mvm , true);
503
- memset (& mvmvif -> deflink .beacon_stats , 0 ,
504
- sizeof (mvmvif -> deflink .beacon_stats ));
505
-
506
- if (!test_bit (IWL_MVM_STATUS_IN_HW_RESTART ,
507
- & mvm -> status ) &&
508
- !vif -> bss_conf .dtim_period ) {
509
- /* If we're not restarting and still haven't
510
- * heard a beacon (dtim period unknown) then
511
- * make sure we still have enough minimum time
512
- * remaining in the time event, since the auth
513
- * might actually have taken quite a while
514
- * (especially for SAE) and so the remaining
515
- * time could be small without us having heard
516
- * a beacon yet.
517
- */
518
- iwl_mvm_protect_assoc (mvm , vif , 0 );
519
- }
559
+ if (!(changes & BSS_CHANGED_ASSOC ))
560
+ return ;
561
+
562
+ if (vif -> cfg .assoc ) {
563
+ /* clear statistics to get clean beacon counter */
564
+ iwl_mvm_request_statistics (mvm , true);
565
+ iwl_mvm_sf_update (mvm , vif , false);
566
+ iwl_mvm_power_vif_assoc (mvm , vif );
567
+
568
+ for_each_mvm_vif_valid_link (mvmvif , i ) {
569
+ memset (& mvmvif -> link [i ]-> beacon_stats , 0 ,
570
+ sizeof (mvmvif -> link [i ]-> beacon_stats ));
520
571
521
- iwl_mvm_sf_update (mvm , vif , false);
522
- iwl_mvm_power_vif_assoc (mvm , vif );
523
572
if (vif -> p2p ) {
524
573
iwl_mvm_update_smps (mvm , vif ,
525
574
IWL_MVM_SMPS_REQ_PROT ,
526
- IEEE80211_SMPS_DYNAMIC , 0 );
575
+ IEEE80211_SMPS_DYNAMIC , i );
527
576
}
528
- } else if (mvmvif -> deflink .ap_sta_id != IWL_MVM_INVALID_STA ) {
529
- iwl_mvm_mei_host_disassociated (mvm );
530
- /* If update fails - SF might be running in associated
531
- * mode while disassociated - which is forbidden.
532
- */
533
- ret = iwl_mvm_sf_update (mvm , vif , false);
534
- WARN_ONCE (ret &&
535
- !test_bit (IWL_MVM_STATUS_HW_RESTART_REQUESTED ,
536
- & mvm -> status ),
537
- "Failed to update SF upon disassociation\n" );
538
-
539
- /* If we get an assert during the connection (after the
540
- * station has been added, but before the vif is set
541
- * to associated), mac80211 will re-add the station and
542
- * then configure the vif. Since the vif is not
543
- * associated, we would remove the station here and
544
- * this would fail the recovery.
577
+
578
+ rcu_read_lock ();
579
+ link_conf = rcu_dereference (vif -> link_conf [i ]);
580
+ if (link_conf && !link_conf -> dtim_period )
581
+ protect = true;
582
+ rcu_read_unlock ();
583
+ }
584
+
585
+ if (!test_bit (IWL_MVM_STATUS_IN_HW_RESTART , & mvm -> status ) &&
586
+ protect ) {
587
+ /* If we're not restarting and still haven't
588
+ * heard a beacon (dtim period unknown) then
589
+ * make sure we still have enough minimum time
590
+ * remaining in the time event, since the auth
591
+ * might actually have taken quite a while
592
+ * (especially for SAE) and so the remaining
593
+ * time could be small without us having heard
594
+ * a beacon yet.
545
595
*/
546
- if (!test_bit (IWL_MVM_STATUS_IN_HW_RESTART ,
547
- & mvm -> status )) {
548
- /* first remove remaining keys */
549
- iwl_mvm_sec_key_remove_ap (mvm , vif );
550
-
551
- /* Remove AP station now that
552
- * the MAC is unassoc
553
- */
554
- ret = iwl_mvm_mld_rm_sta_id (mvm , vif ,
555
- mvmvif -> deflink .ap_sta_id );
556
- if (ret )
557
- IWL_ERR (mvm ,
558
- "failed to remove AP station\n" );
559
-
560
- mvmvif -> deflink .ap_sta_id = IWL_MVM_INVALID_STA ;
561
- }
596
+ iwl_mvm_protect_assoc (mvm , vif , 0 );
562
597
}
563
598
564
- iwl_mvm_bss_info_changed_station_assoc (mvm , vif , changes );
599
+ iwl_mvm_sf_update (mvm , vif , false);
600
+
601
+ /* FIXME: need to decide about misbehaving AP handling */
602
+ iwl_mvm_power_vif_assoc (mvm , vif );
603
+ } else if (iwl_mvm_mld_vif_have_valid_ap_sta (mvmvif )) {
604
+ iwl_mvm_mei_host_disassociated (mvm );
605
+
606
+ /* If update fails - SF might be running in associated
607
+ * mode while disassociated - which is forbidden.
608
+ */
609
+ ret = iwl_mvm_sf_update (mvm , vif , false);
610
+ WARN_ONCE (ret &&
611
+ !test_bit (IWL_MVM_STATUS_HW_RESTART_REQUESTED ,
612
+ & mvm -> status ),
613
+ "Failed to update SF upon disassociation\n" );
614
+
615
+ /* If we get an assert during the connection (after the
616
+ * station has been added, but before the vif is set
617
+ * to associated), mac80211 will re-add the station and
618
+ * then configure the vif. Since the vif is not
619
+ * associated, we would remove the station here and
620
+ * this would fail the recovery.
621
+ */
622
+ iwl_mvm_mld_vif_delete_all_stas (mvm , vif );
565
623
}
566
624
567
- iwl_mvm_bss_info_changed_station_common (mvm , vif , & vif -> bss_conf , changes );
625
+ iwl_mvm_bss_info_changed_station_assoc (mvm , vif , changes );
568
626
}
569
627
570
628
static void
571
- iwl_mvm_mld_bss_info_changed_ap_ibss (struct iwl_mvm * mvm ,
572
- struct ieee80211_vif * vif ,
573
- struct ieee80211_bss_conf * bss_conf ,
574
- u64 changes )
629
+ iwl_mvm_mld_link_info_changed_ap_ibss (struct iwl_mvm * mvm ,
630
+ struct ieee80211_vif * vif ,
631
+ struct ieee80211_bss_conf * link_conf ,
632
+ u64 changes )
575
633
{
576
634
struct iwl_mvm_vif * mvmvif = iwl_mvm_vif_from_mac80211 (vif );
577
635
u32 link_changes = LINK_CONTEXT_MODIFY_PROTECT_FLAGS |
@@ -581,17 +639,22 @@ iwl_mvm_mld_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
581
639
if (!mvmvif -> ap_ibss_active )
582
640
return ;
583
641
642
+ if (link_conf -> he_support )
643
+ link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS ;
644
+
584
645
if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
585
- BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS ) &&
586
- iwl_mvm_link_changed (mvm , vif , & vif -> bss_conf ,
646
+ BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS |
647
+ BSS_CHANGED_HE_BSS_COLOR ) &&
648
+ iwl_mvm_link_changed (mvm , vif , link_conf ,
587
649
link_changes , true))
588
650
IWL_ERR (mvm , "failed to update MAC %pM\n" , vif -> addr );
589
651
590
652
/* Need to send a new beacon template to the FW */
591
653
if (changes & BSS_CHANGED_BEACON &&
592
- iwl_mvm_mac_ctxt_beacon_changed (mvm , vif , & vif -> bss_conf ))
654
+ iwl_mvm_mac_ctxt_beacon_changed (mvm , vif , link_conf ))
593
655
IWL_WARN (mvm , "Failed updating beacon data\n" );
594
656
657
+ /* FIXME: need to decide if we need FTM responder per link */
595
658
if (changes & BSS_CHANGED_FTM_RESPONDER ) {
596
659
int ret = iwl_mvm_ftm_start_responder (mvm , vif );
597
660
@@ -601,19 +664,58 @@ iwl_mvm_mld_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
601
664
}
602
665
}
603
666
604
- static void iwl_mvm_mld_bss_info_changed (struct ieee80211_hw * hw ,
605
- struct ieee80211_vif * vif ,
606
- struct ieee80211_bss_conf * bss_conf ,
607
- u64 changes )
667
+ static void iwl_mvm_mld_link_info_changed (struct ieee80211_hw * hw ,
668
+ struct ieee80211_vif * vif ,
669
+ struct ieee80211_bss_conf * link_conf ,
670
+ u64 changes )
671
+ {
672
+ struct iwl_mvm * mvm = IWL_MAC80211_GET_MVM (hw );
673
+
674
+ mutex_lock (& mvm -> mutex );
675
+
676
+ switch (vif -> type ) {
677
+ case NL80211_IFTYPE_STATION :
678
+ iwl_mvm_mld_link_info_changed_station (mvm , vif , link_conf ,
679
+ changes );
680
+ break ;
681
+ case NL80211_IFTYPE_AP :
682
+ case NL80211_IFTYPE_ADHOC :
683
+ iwl_mvm_mld_link_info_changed_ap_ibss (mvm , vif , link_conf ,
684
+ changes );
685
+ break ;
686
+ case NL80211_IFTYPE_MONITOR :
687
+ if (changes & BSS_CHANGED_MU_GROUPS )
688
+ iwl_mvm_update_mu_groups (mvm , vif );
689
+ break ;
690
+ default :
691
+ /* shouldn't happen */
692
+ WARN_ON_ONCE (1 );
693
+ }
694
+
695
+ if (changes & BSS_CHANGED_TXPOWER ) {
696
+ IWL_DEBUG_CALIB (mvm , "Changing TX Power to %d dBm\n" ,
697
+ link_conf -> txpower );
698
+ iwl_mvm_set_tx_power (mvm , vif , link_conf -> txpower );
699
+ }
700
+
701
+ mutex_unlock (& mvm -> mutex );
702
+ }
703
+
704
+ static void iwl_mvm_mld_vif_cfg_changed (struct ieee80211_hw * hw ,
705
+ struct ieee80211_vif * vif ,
706
+ u64 changes )
608
707
{
609
- struct iwl_mvm_bss_info_changed_ops callbacks = {
610
- .bss_info_changed_sta = iwl_mvm_mld_bss_info_changed_station ,
611
- .bss_info_changed_ap_ibss =
612
- iwl_mvm_mld_bss_info_changed_ap_ibss ,
613
- };
708
+ struct iwl_mvm * mvm = IWL_MAC80211_GET_MVM (hw );
614
709
615
- iwl_mvm_bss_info_changed_common (hw , vif , bss_conf , & callbacks ,
616
- changes );
710
+ mutex_lock (& mvm -> mutex );
711
+
712
+ if (changes & BSS_CHANGED_IDLE && !vif -> cfg .idle )
713
+ iwl_mvm_scan_stop (mvm , IWL_MVM_SCAN_SCHED , true);
714
+
715
+ if (vif -> type == NL80211_IFTYPE_STATION )
716
+ iwl_mvm_mld_vif_cfg_changed_station (mvm , vif , changes );
717
+
718
+ mutex_unlock (& mvm -> mutex );
617
719
}
618
720
619
721
static int
@@ -735,7 +837,8 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
735
837
.prepare_multicast = iwl_mvm_prepare_multicast ,
736
838
.configure_filter = iwl_mvm_configure_filter ,
737
839
.config_iface_filter = iwl_mvm_mld_config_iface_filter ,
738
- .bss_info_changed = iwl_mvm_mld_bss_info_changed ,
840
+ .link_info_changed = iwl_mvm_mld_link_info_changed ,
841
+ .vif_cfg_changed = iwl_mvm_mld_vif_cfg_changed ,
739
842
.hw_scan = iwl_mvm_mac_hw_scan ,
740
843
.cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan ,
741
844
.sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove ,
0 commit comments