mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-03 20:34:23 -04:00
ath11k: Add support for STA to handle beacon miss
When AP goes down without any indication to STA, firmware detects missing beacon, and sends wmi roam event with reason BEACON_MISS to the host. Added support for STA mode to trigger disassociation from AP, on receiving this event from firmware. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01717-QCAHKSWPL_SILICONZ-1 Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Lavanya Suresh <lavaks@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/1614340859-28867-1-git-send-email-lavaks@codeaurora.org
This commit is contained in:
committed by
Kalle Valo
parent
f277eb0500
commit
26f6979237
@@ -34,6 +34,7 @@
|
||||
#define ATH11K_PRB_RSP_DROP_THRESHOLD ((ATH11K_TX_MGMT_TARGET_MAX_SUPPORT_WMI * 3) / 4)
|
||||
|
||||
#define ATH11K_INVALID_HW_MAC_ID 0xFF
|
||||
#define ATH11K_CONNECTION_LOSS_HZ (3 * HZ)
|
||||
|
||||
extern unsigned int ath11k_frame_mode;
|
||||
|
||||
@@ -235,6 +236,7 @@ struct ath11k_vif {
|
||||
u32 aid;
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct cfg80211_bitrate_mask bitrate_mask;
|
||||
struct delayed_work connection_loss_work;
|
||||
int num_legacy_stations;
|
||||
int rtscts_prot_mode;
|
||||
int txpower;
|
||||
|
||||
@@ -829,6 +829,75 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);
|
||||
}
|
||||
|
||||
static void ath11k_mac_handle_beacon_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct sk_buff *skb = data;
|
||||
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
||||
struct ath11k_vif *arvif = (void *)vif->drv_priv;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
if (!ether_addr_equal(mgmt->bssid, vif->bss_conf.bssid))
|
||||
return;
|
||||
|
||||
cancel_delayed_work(&arvif->connection_loss_work);
|
||||
}
|
||||
|
||||
void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb)
|
||||
{
|
||||
ieee80211_iterate_active_interfaces_atomic(ar->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
ath11k_mac_handle_beacon_iter,
|
||||
skb);
|
||||
}
|
||||
|
||||
static void ath11k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
u32 *vdev_id = data;
|
||||
struct ath11k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ieee80211_hw *hw = ar->hw;
|
||||
|
||||
if (arvif->vdev_id != *vdev_id)
|
||||
return;
|
||||
|
||||
if (!arvif->is_up)
|
||||
return;
|
||||
|
||||
ieee80211_beacon_loss(vif);
|
||||
|
||||
/* Firmware doesn't report beacon loss events repeatedly. If AP probe
|
||||
* (done by mac80211) succeeds but beacons do not resume then it
|
||||
* doesn't make sense to continue operation. Queue connection loss work
|
||||
* which can be cancelled when beacon is received.
|
||||
*/
|
||||
ieee80211_queue_delayed_work(hw, &arvif->connection_loss_work,
|
||||
ATH11K_CONNECTION_LOSS_HZ);
|
||||
}
|
||||
|
||||
void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id)
|
||||
{
|
||||
ieee80211_iterate_active_interfaces_atomic(ar->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
ath11k_mac_handle_beacon_miss_iter,
|
||||
&vdev_id);
|
||||
}
|
||||
|
||||
static void ath11k_mac_vif_sta_connection_loss_work(struct work_struct *work)
|
||||
{
|
||||
struct ath11k_vif *arvif = container_of(work, struct ath11k_vif,
|
||||
connection_loss_work.work);
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
|
||||
if (!arvif->is_up)
|
||||
return;
|
||||
|
||||
ieee80211_connection_loss(vif);
|
||||
}
|
||||
|
||||
static void ath11k_peer_assoc_h_basic(struct ath11k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
@@ -1760,7 +1829,7 @@ static void ath11k_bss_disassoc(struct ieee80211_hw *hw,
|
||||
|
||||
arvif->is_up = false;
|
||||
|
||||
/* TODO: cancel connection_loss_work */
|
||||
cancel_delayed_work_sync(&arvif->connection_loss_work);
|
||||
}
|
||||
|
||||
static u32 ath11k_mac_get_rate_hw_value(int bitrate)
|
||||
@@ -4615,10 +4684,8 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
arvif->vif = vif;
|
||||
|
||||
INIT_LIST_HEAD(&arvif->list);
|
||||
|
||||
/* Should we initialize any worker to handle connection loss indication
|
||||
* from firmware in sta mode?
|
||||
*/
|
||||
INIT_DELAYED_WORK(&arvif->connection_loss_work,
|
||||
ath11k_mac_vif_sta_connection_loss_work);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
|
||||
arvif->bitrate_mask.control[i].legacy = 0xffffffff;
|
||||
@@ -4827,6 +4894,8 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
cancel_delayed_work_sync(&arvif->connection_loss_work);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n",
|
||||
|
||||
@@ -150,4 +150,6 @@ int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
|
||||
u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
|
||||
enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw);
|
||||
enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher);
|
||||
void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb);
|
||||
void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id);
|
||||
#endif
|
||||
|
||||
@@ -6171,10 +6171,8 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Pending handle beacon implementation
|
||||
*if (ieee80211_is_beacon(hdr->frame_control))
|
||||
* ath11k_mac_handle_beacon(ar, skb);
|
||||
*/
|
||||
if (ieee80211_is_beacon(hdr->frame_control))
|
||||
ath11k_mac_handle_beacon(ar, skb);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MGMT,
|
||||
"event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
|
||||
@@ -6393,10 +6391,7 @@ static void ath11k_roam_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
|
||||
switch (roam_ev.reason) {
|
||||
case WMI_ROAM_REASON_BEACON_MISS:
|
||||
/* TODO: Pending beacon miss and connection_loss_work
|
||||
* implementation
|
||||
* ath11k_mac_handle_beacon_miss(ar, vdev_id);
|
||||
*/
|
||||
ath11k_mac_handle_beacon_miss(ar, roam_ev.vdev_id);
|
||||
break;
|
||||
case WMI_ROAM_REASON_BETTER_AP:
|
||||
case WMI_ROAM_REASON_LOW_RSSI:
|
||||
|
||||
Reference in New Issue
Block a user