@@ -5890,6 +5890,211 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
58905890 return ret ;
58915891}
58925892
5893+ static bool ath12k_mac_is_freq_on_mac (struct ath12k_hw_mode_freq_range_arg * freq_range ,
5894+ u32 freq , u8 mac_id )
5895+ {
5896+ return (freq >= freq_range [mac_id ].low_2ghz_freq &&
5897+ freq <= freq_range [mac_id ].high_2ghz_freq ) ||
5898+ (freq >= freq_range [mac_id ].low_5ghz_freq &&
5899+ freq <= freq_range [mac_id ].high_5ghz_freq );
5900+ }
5901+
5902+ static bool
5903+ ath12k_mac_2_freq_same_mac_in_freq_range (struct ath12k_base * ab ,
5904+ struct ath12k_hw_mode_freq_range_arg * freq_range ,
5905+ u32 freq_link1 , u32 freq_link2 )
5906+ {
5907+ u8 i ;
5908+
5909+ for (i = 0 ; i < MAX_RADIOS ; i ++ ) {
5910+ if (ath12k_mac_is_freq_on_mac (freq_range , freq_link1 , i ) &&
5911+ ath12k_mac_is_freq_on_mac (freq_range , freq_link2 , i ))
5912+ return true;
5913+ }
5914+
5915+ return false;
5916+ }
5917+
5918+ static bool ath12k_mac_is_hw_dbs_capable (struct ath12k_base * ab )
5919+ {
5920+ return test_bit (WMI_TLV_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT ,
5921+ ab -> wmi_ab .svc_map ) &&
5922+ ab -> wmi_ab .hw_mode_info .support_dbs ;
5923+ }
5924+
5925+ static bool ath12k_mac_2_freq_same_mac_in_dbs (struct ath12k_base * ab ,
5926+ u32 freq_link1 , u32 freq_link2 )
5927+ {
5928+ struct ath12k_hw_mode_freq_range_arg * freq_range ;
5929+
5930+ if (!ath12k_mac_is_hw_dbs_capable (ab ))
5931+ return true;
5932+
5933+ freq_range = ab -> wmi_ab .hw_mode_info .freq_range_caps [ATH12K_HW_MODE_DBS ];
5934+ return ath12k_mac_2_freq_same_mac_in_freq_range (ab , freq_range ,
5935+ freq_link1 , freq_link2 );
5936+ }
5937+
5938+ static bool ath12k_mac_is_hw_sbs_capable (struct ath12k_base * ab )
5939+ {
5940+ return test_bit (WMI_TLV_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT ,
5941+ ab -> wmi_ab .svc_map ) &&
5942+ ab -> wmi_ab .hw_mode_info .support_sbs ;
5943+ }
5944+
5945+ static bool ath12k_mac_2_freq_same_mac_in_sbs (struct ath12k_base * ab ,
5946+ u32 freq_link1 , u32 freq_link2 )
5947+ {
5948+ struct ath12k_hw_mode_info * info = & ab -> wmi_ab .hw_mode_info ;
5949+ struct ath12k_hw_mode_freq_range_arg * sbs_uppr_share ;
5950+ struct ath12k_hw_mode_freq_range_arg * sbs_low_share ;
5951+ struct ath12k_hw_mode_freq_range_arg * sbs_range ;
5952+
5953+ if (!ath12k_mac_is_hw_sbs_capable (ab ))
5954+ return true;
5955+
5956+ if (ab -> wmi_ab .sbs_lower_band_end_freq ) {
5957+ sbs_uppr_share = info -> freq_range_caps [ATH12K_HW_MODE_SBS_UPPER_SHARE ];
5958+ sbs_low_share = info -> freq_range_caps [ATH12K_HW_MODE_SBS_LOWER_SHARE ];
5959+
5960+ return ath12k_mac_2_freq_same_mac_in_freq_range (ab , sbs_low_share ,
5961+ freq_link1 , freq_link2 ) ||
5962+ ath12k_mac_2_freq_same_mac_in_freq_range (ab , sbs_uppr_share ,
5963+ freq_link1 , freq_link2 );
5964+ }
5965+
5966+ sbs_range = info -> freq_range_caps [ATH12K_HW_MODE_SBS ];
5967+ return ath12k_mac_2_freq_same_mac_in_freq_range (ab , sbs_range ,
5968+ freq_link1 , freq_link2 );
5969+ }
5970+
5971+ static bool ath12k_mac_freqs_on_same_mac (struct ath12k_base * ab ,
5972+ u32 freq_link1 , u32 freq_link2 )
5973+ {
5974+ return ath12k_mac_2_freq_same_mac_in_dbs (ab , freq_link1 , freq_link2 ) &&
5975+ ath12k_mac_2_freq_same_mac_in_sbs (ab , freq_link1 , freq_link2 );
5976+ }
5977+
5978+ static int ath12k_mac_mlo_sta_set_link_active (struct ath12k_base * ab ,
5979+ enum wmi_mlo_link_force_reason reason ,
5980+ enum wmi_mlo_link_force_mode mode ,
5981+ u8 * mlo_vdev_id_lst ,
5982+ u8 num_mlo_vdev ,
5983+ u8 * mlo_inactive_vdev_lst ,
5984+ u8 num_mlo_inactive_vdev )
5985+ {
5986+ struct wmi_mlo_link_set_active_arg param = {0 };
5987+ u32 entry_idx , entry_offset , vdev_idx ;
5988+ u8 vdev_id ;
5989+
5990+ param .reason = reason ;
5991+ param .force_mode = mode ;
5992+
5993+ for (vdev_idx = 0 ; vdev_idx < num_mlo_vdev ; vdev_idx ++ ) {
5994+ vdev_id = mlo_vdev_id_lst [vdev_idx ];
5995+ entry_idx = vdev_id / 32 ;
5996+ entry_offset = vdev_id % 32 ;
5997+ if (entry_idx >= WMI_MLO_LINK_NUM_SZ ) {
5998+ ath12k_warn (ab , "Invalid entry_idx %d num_mlo_vdev %d vdev %d" ,
5999+ entry_idx , num_mlo_vdev , vdev_id );
6000+ return - EINVAL ;
6001+ }
6002+ param .vdev_bitmap [entry_idx ] |= 1 << entry_offset ;
6003+ /* update entry number if entry index changed */
6004+ if (param .num_vdev_bitmap < entry_idx + 1 )
6005+ param .num_vdev_bitmap = entry_idx + 1 ;
6006+ }
6007+
6008+ ath12k_dbg (ab , ATH12K_DBG_MAC ,
6009+ "num_vdev_bitmap %d vdev_bitmap[0] = 0x%x, vdev_bitmap[1] = 0x%x" ,
6010+ param .num_vdev_bitmap , param .vdev_bitmap [0 ], param .vdev_bitmap [1 ]);
6011+
6012+ if (mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE ) {
6013+ for (vdev_idx = 0 ; vdev_idx < num_mlo_inactive_vdev ; vdev_idx ++ ) {
6014+ vdev_id = mlo_inactive_vdev_lst [vdev_idx ];
6015+ entry_idx = vdev_id / 32 ;
6016+ entry_offset = vdev_id % 32 ;
6017+ if (entry_idx >= WMI_MLO_LINK_NUM_SZ ) {
6018+ ath12k_warn (ab , "Invalid entry_idx %d num_mlo_vdev %d vdev %d" ,
6019+ entry_idx , num_mlo_inactive_vdev , vdev_id );
6020+ return - EINVAL ;
6021+ }
6022+ param .inactive_vdev_bitmap [entry_idx ] |= 1 << entry_offset ;
6023+ /* update entry number if entry index changed */
6024+ if (param .num_inactive_vdev_bitmap < entry_idx + 1 )
6025+ param .num_inactive_vdev_bitmap = entry_idx + 1 ;
6026+ }
6027+
6028+ ath12k_dbg (ab , ATH12K_DBG_MAC ,
6029+ "num_vdev_bitmap %d inactive_vdev_bitmap[0] = 0x%x, inactive_vdev_bitmap[1] = 0x%x" ,
6030+ param .num_inactive_vdev_bitmap ,
6031+ param .inactive_vdev_bitmap [0 ],
6032+ param .inactive_vdev_bitmap [1 ]);
6033+ }
6034+
6035+ if (mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_LINK_NUM ||
6036+ mode == WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM ) {
6037+ param .num_link_entry = 1 ;
6038+ param .link_num [0 ].num_of_link = num_mlo_vdev - 1 ;
6039+ }
6040+
6041+ return ath12k_wmi_send_mlo_link_set_active_cmd (ab , & param );
6042+ }
6043+
6044+ static int ath12k_mac_mlo_sta_update_link_active (struct ath12k_base * ab ,
6045+ struct ieee80211_hw * hw ,
6046+ struct ath12k_vif * ahvif )
6047+ {
6048+ u8 mlo_vdev_id_lst [IEEE80211_MLD_MAX_NUM_LINKS ] = {0 };
6049+ u32 mlo_freq_list [IEEE80211_MLD_MAX_NUM_LINKS ] = {0 };
6050+ unsigned long links = ahvif -> links_map ;
6051+ enum wmi_mlo_link_force_reason reason ;
6052+ struct ieee80211_chanctx_conf * conf ;
6053+ enum wmi_mlo_link_force_mode mode ;
6054+ struct ieee80211_bss_conf * info ;
6055+ struct ath12k_link_vif * arvif ;
6056+ u8 num_mlo_vdev = 0 ;
6057+ u8 link_id ;
6058+
6059+ for_each_set_bit (link_id , & links , IEEE80211_MLD_MAX_NUM_LINKS ) {
6060+ arvif = wiphy_dereference (hw -> wiphy , ahvif -> link [link_id ]);
6061+ /* make sure vdev is created on this device */
6062+ if (!arvif || !arvif -> is_created || arvif -> ar -> ab != ab )
6063+ continue ;
6064+
6065+ info = ath12k_mac_get_link_bss_conf (arvif );
6066+ conf = wiphy_dereference (hw -> wiphy , info -> chanctx_conf );
6067+ mlo_freq_list [num_mlo_vdev ] = conf -> def .chan -> center_freq ;
6068+
6069+ mlo_vdev_id_lst [num_mlo_vdev ] = arvif -> vdev_id ;
6070+ num_mlo_vdev ++ ;
6071+ }
6072+
6073+ /* It is not allowed to activate more links than a single device
6074+ * supported. Something goes wrong if we reach here.
6075+ */
6076+ if (num_mlo_vdev > ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE ) {
6077+ WARN_ON_ONCE (1 );
6078+ return - EINVAL ;
6079+ }
6080+
6081+ /* if 2 links are established and both link channels fall on the
6082+ * same hardware MAC, send command to firmware to deactivate one
6083+ * of them.
6084+ */
6085+ if (num_mlo_vdev == 2 &&
6086+ ath12k_mac_freqs_on_same_mac (ab , mlo_freq_list [0 ],
6087+ mlo_freq_list [1 ])) {
6088+ mode = WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM ;
6089+ reason = WMI_MLO_LINK_FORCE_REASON_NEW_CONNECT ;
6090+ return ath12k_mac_mlo_sta_set_link_active (ab , reason , mode ,
6091+ mlo_vdev_id_lst , num_mlo_vdev ,
6092+ NULL , 0 );
6093+ }
6094+
6095+ return 0 ;
6096+ }
6097+
58936098static int ath12k_mac_op_sta_state (struct ieee80211_hw * hw ,
58946099 struct ieee80211_vif * vif ,
58956100 struct ieee80211_sta * sta ,
@@ -5899,10 +6104,12 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
58996104 struct ath12k_vif * ahvif = ath12k_vif_to_ahvif (vif );
59006105 struct ath12k_sta * ahsta = ath12k_sta_to_ahsta (sta );
59016106 struct ath12k_hw * ah = ath12k_hw_to_ah (hw );
6107+ struct ath12k_base * prev_ab = NULL , * ab ;
59026108 struct ath12k_link_vif * arvif ;
59036109 struct ath12k_link_sta * arsta ;
59046110 unsigned long valid_links ;
5905- u8 link_id = 0 ;
6111+ u8 link_id = 0 , i ;
6112+ struct ath12k * ar ;
59066113 int ret ;
59076114
59086115 lockdep_assert_wiphy (hw -> wiphy );
@@ -5997,6 +6204,24 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
59976204 }
59986205 }
59996206
6207+ if (ieee80211_vif_is_mld (vif ) && vif -> type == NL80211_IFTYPE_STATION &&
6208+ old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED ) {
6209+ for_each_ar (ah , ar , i ) {
6210+ ab = ar -> ab ;
6211+ if (prev_ab == ab )
6212+ continue ;
6213+
6214+ ret = ath12k_mac_mlo_sta_update_link_active (ab , hw , ahvif );
6215+ if (ret ) {
6216+ ath12k_warn (ab ,
6217+ "failed to update link active state on connect %d\n" ,
6218+ ret );
6219+ goto exit ;
6220+ }
6221+
6222+ prev_ab = ab ;
6223+ }
6224+ }
60006225 /* IEEE80211_STA_NONE -> IEEE80211_STA_NOTEXIST:
60016226 * Remove the station from driver (handle ML sta here since that
60026227 * needs special handling. Normal sta will be handled in generic
0 commit comments