wifi: ath12k: Extend beacon miss handling for MLO non-AP STA

Currently, ath12k_mac_handle_beacon_miss() does not handle the beacon
miss for the MLO case.

In MLO scenarios, the host fails to process the beacon miss because the
vdev_id comparison in ath12k_mac_handle_beacon_miss_iter() does not match.
This mismatch occurs since arvif always points to ahvif->deflink, which may
not correspond to the actual vdev_id associated with the event.

Fix this by retrieving arvif from vdev_id instead of ahvif->deflink which
will work for both MLO and Non-MLO case.

Also refactor the ath12k_mac_handle_beacon_miss(), by passing arvif
directly instead of vdev_id and remove ath12k_mac_handle_beacon_miss_iter()
which is no longer needed.

ath12k_mac_handle_beacon_miss() is called from ath12k_roam_event() for WCN
chipsets and ath12k_peer_sta_kickout_event() for QCN chipsets.

So, refactor the ath12k_roam_event() to pass arvif instead vdev_id to the
ath12k_mac_handle_beacon_miss() function to align with the
ath12k_peer_sta_kickout_event() and change the rcu_read_lock() to
guard(rcu)() in the same function ath12k_roam_event().

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00284-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1

Co-developed-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
Signed-off-by: Maharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250812111708.3686-4-maharaja.kennadyrajan@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
Maharaja Kennadyrajan 2025-08-12 16:47:08 +05:30 committed by Jeff Johnson
parent 9891fbd9d8
commit dcdb05a43d
3 changed files with 32 additions and 32 deletions

View File

@ -1822,22 +1822,16 @@ void ath12k_mac_handle_beacon(struct ath12k *ar, struct sk_buff *skb)
skb);
}
static void ath12k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
void ath12k_mac_handle_beacon_miss(struct ath12k *ar,
struct ath12k_link_vif *arvif)
{
u32 *vdev_id = data;
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif = &ahvif->deflink;
struct ieee80211_hw *hw;
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
if (!arvif->is_created || arvif->vdev_id != *vdev_id)
return;
if (!arvif->is_up)
if (!(arvif->is_created && arvif->is_up))
return;
ieee80211_beacon_loss(vif);
hw = ath12k_ar_to_hw(arvif->ar);
/* Firmware doesn't report beacon loss events repeatedly. If AP probe
* (done by mac80211) succeeds but beacons do not resume then it
@ -1848,14 +1842,6 @@ static void ath12k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
ATH12K_CONNECTION_LOSS_HZ);
}
void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id)
{
ieee80211_iterate_active_interfaces_atomic(ath12k_ar_to_hw(ar),
IEEE80211_IFACE_ITER_NORMAL,
ath12k_mac_handle_beacon_miss_iter,
&vdev_id);
}
static void ath12k_mac_vif_sta_connection_loss_work(struct work_struct *work)
{
struct ath12k_link_vif *arvif = container_of(work, struct ath12k_link_vif,

View File

@ -168,7 +168,8 @@ int ath12k_mac_rfkill_enable_radio(struct ath12k *ar, bool enable);
int ath12k_mac_rfkill_config(struct ath12k *ar);
int ath12k_mac_wait_tx_complete(struct ath12k *ar);
void ath12k_mac_handle_beacon(struct ath12k *ar, struct sk_buff *skb);
void ath12k_mac_handle_beacon_miss(struct ath12k *ar, u32 vdev_id);
void ath12k_mac_handle_beacon_miss(struct ath12k *ar,
struct ath12k_link_vif *arvif);
int ath12k_mac_vif_set_keepalive(struct ath12k_link_vif *arvif,
enum wmi_sta_keepalive_method method,
u32 interval);

View File

@ -7308,6 +7308,7 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff
struct ath12k_link_vif *arvif;
struct ieee80211_sta *sta;
struct ath12k_peer *peer;
unsigned int link_id;
struct ath12k *ar;
if (ath12k_pull_peer_sta_kickout_ev(ab, skb, &arg) != 0) {
@ -7336,11 +7337,23 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff
ar = arvif->ar;
sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar),
arg.mac_addr, NULL);
if (peer->mlo) {
sta = ieee80211_find_sta_by_link_addrs(ath12k_ar_to_hw(ar),
arg.mac_addr,
NULL, &link_id);
if (peer->link_id != link_id) {
ath12k_warn(ab,
"Spurious quick kickout for MLO STA %pM with invalid link_id, peer: %d, sta: %d\n",
arg.mac_addr, peer->link_id, link_id);
goto exit;
}
} else {
sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar),
arg.mac_addr, NULL);
}
if (!sta) {
ath12k_warn(ab, "Spurious quick kickout for STA %pM\n",
arg.mac_addr);
ath12k_warn(ab, "Spurious quick kickout for %sSTA %pM\n",
peer->mlo ? "MLO " : "", arg.mac_addr);
goto exit;
}
@ -7351,7 +7364,7 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff
switch (arg.reason) {
case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
if (arvif->ahvif->vif->type == NL80211_IFTYPE_STATION) {
ath12k_mac_handle_beacon_miss(ar, peer->vdev_id);
ath12k_mac_handle_beacon_miss(ar, arvif);
break;
}
fallthrough;
@ -7366,6 +7379,7 @@ static void ath12k_peer_sta_kickout_event(struct ath12k_base *ab, struct sk_buff
static void ath12k_roam_event(struct ath12k_base *ab, struct sk_buff *skb)
{
struct ath12k_link_vif *arvif;
struct wmi_roam_event roam_ev = {};
struct ath12k *ar;
u32 vdev_id;
@ -7384,21 +7398,22 @@ static void ath12k_roam_event(struct ath12k_base *ab, struct sk_buff *skb)
"wmi roam event vdev %u reason %d rssi %d\n",
vdev_id, roam_reason, roam_ev.rssi);
rcu_read_lock();
ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);
if (!ar) {
guard(rcu)();
arvif = ath12k_mac_get_arvif_by_vdev_id(ab, vdev_id);
if (!arvif) {
ath12k_warn(ab, "invalid vdev id in roam ev %d", vdev_id);
rcu_read_unlock();
return;
}
ar = arvif->ar;
if (roam_reason >= WMI_ROAM_REASON_MAX)
ath12k_warn(ab, "ignoring unknown roam event reason %d on vdev %i\n",
roam_reason, vdev_id);
switch (roam_reason) {
case WMI_ROAM_REASON_BEACON_MISS:
ath12k_mac_handle_beacon_miss(ar, vdev_id);
ath12k_mac_handle_beacon_miss(ar, arvif);
break;
case WMI_ROAM_REASON_BETTER_AP:
case WMI_ROAM_REASON_LOW_RSSI:
@ -7408,8 +7423,6 @@ static void ath12k_roam_event(struct ath12k_base *ab, struct sk_buff *skb)
roam_reason, vdev_id);
break;
}
rcu_read_unlock();
}
static void ath12k_chan_info_event(struct ath12k_base *ab, struct sk_buff *skb)