@@ -5890,6 +5890,211 @@ static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
5890
5890
return ret ;
5891
5891
}
5892
5892
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
+
5893
6098
static int ath12k_mac_op_sta_state (struct ieee80211_hw * hw ,
5894
6099
struct ieee80211_vif * vif ,
5895
6100
struct ieee80211_sta * sta ,
@@ -5899,10 +6104,12 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
5899
6104
struct ath12k_vif * ahvif = ath12k_vif_to_ahvif (vif );
5900
6105
struct ath12k_sta * ahsta = ath12k_sta_to_ahsta (sta );
5901
6106
struct ath12k_hw * ah = ath12k_hw_to_ah (hw );
6107
+ struct ath12k_base * prev_ab = NULL , * ab ;
5902
6108
struct ath12k_link_vif * arvif ;
5903
6109
struct ath12k_link_sta * arsta ;
5904
6110
unsigned long valid_links ;
5905
- u8 link_id = 0 ;
6111
+ u8 link_id = 0 , i ;
6112
+ struct ath12k * ar ;
5906
6113
int ret ;
5907
6114
5908
6115
lockdep_assert_wiphy (hw -> wiphy );
@@ -5997,6 +6204,24 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
5997
6204
}
5998
6205
}
5999
6206
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
+ }
6000
6225
/* IEEE80211_STA_NONE -> IEEE80211_STA_NOTEXIST:
6001
6226
* Remove the station from driver (handle ML sta here since that
6002
6227
* needs special handling. Normal sta will be handled in generic
0 commit comments