wifi: ath12k: identify assoc link vif in station mode

In MLO scenario, for station mode interface, WCN7850 firmware requests
the assoc link vdev to get started before any other link vdevs starts.
Firmware internally checks assoc_link field of
wmi_vdev_start_mlo_params.flags when the first vdev starts. And if the
check fails firmware crashes.

Current connection flow guarantees the assoc link vdev gets started
first (at assoc stage only one link vdev is created/started, i.e. the
assoc link vdev), however the assoc_link flag is never set, resulting
in WCN7850 firmware crash.

Note ath12k_link_sta structure already has is_assoc_link flag, and it
is properly set for assoc link. However we can not use it because it
won't be available before peer gets created, which is too late for vdev
starts.

So add a new flag 'is_sta_assoc_link' in ath12k_link_vif structure and
set it when deflink vdev is created. This is valid because we always
use deflink as the assoc link. This flag is passed to firmware vdev
starts to avoid firmware crash. Also verify the link vif/sta pair has
the same settings when creating link sta.

Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00284-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00209-QCAHKSWPL_SILICONZ-1

Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
Link: https://patch.msgid.link/20250409-ath12k-wcn7850-mlo-support-v2-4-3801132ca2c3@quicinc.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
Baochen Qiang
2025-04-09 10:26:37 +08:00
committed by Jeff Johnson
parent 32f7b19668
commit 0cd46d1f36
2 changed files with 19 additions and 0 deletions

View File

@@ -314,6 +314,9 @@ struct ath12k_link_vif {
spinlock_t link_stats_lock; /* Protects updates to link_stats */
u8 current_cntdown_counter;
/* only used in station mode */
bool is_sta_assoc_link;
};
struct ath12k_vif {

View File

@@ -3477,6 +3477,8 @@ static struct ath12k_link_vif *ath12k_mac_assign_link_vif(struct ath12k_hw *ah,
*/
if (!ahvif->links_map && link_id != ATH12K_DEFAULT_SCAN_LINK) {
arvif = &ahvif->deflink;
if (vif->type == NL80211_IFTYPE_STATION)
arvif->is_sta_assoc_link = true;
} else {
arvif = (struct ath12k_link_vif *)
kzalloc(sizeof(struct ath12k_link_vif), GFP_KERNEL);
@@ -5867,6 +5869,17 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
* link sta
*/
if (sta->mlo) {
/* For station mode, arvif->is_sta_assoc_link has been set when
* vdev starts. Make sure the arvif/arsta pair have same setting
*/
if (vif->type == NL80211_IFTYPE_STATION &&
!arsta->arvif->is_sta_assoc_link) {
ath12k_hw_warn(ah, "failed to verify assoc link setting with link id %u\n",
link_id);
ret = -EINVAL;
goto exit;
}
arsta->is_assoc_link = true;
ahsta->assoc_link_id = link_id;
}
@@ -9123,6 +9136,9 @@ ath12k_mac_mlo_get_vdev_args(struct ath12k_link_vif *arvif,
* link vdevs which are advertised as partners below
*/
ml_arg->link_add = true;
ml_arg->assoc_link = arvif->is_sta_assoc_link;
partner_info = ml_arg->partner_info;
links = ahvif->links_map;