Skip to content

Commit

Permalink
ath11k: Add support for STA to handle beacon miss
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Lavanya Suresh authored and Kalle Valo committed Mar 9, 2021
1 parent f277eb0 commit 26f6979
Showing 4 changed files with 81 additions and 13 deletions.
2 changes: 2 additions & 0 deletions drivers/net/wireless/ath/ath11k/core.h
Original file line number Diff line number Diff line change
@@ -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;
79 changes: 74 additions & 5 deletions drivers/net/wireless/ath/ath11k/mac.c
Original file line number Diff line number Diff line change
@@ -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",
2 changes: 2 additions & 0 deletions drivers/net/wireless/ath/ath11k/mac.h
Original file line number Diff line number Diff line change
@@ -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
11 changes: 3 additions & 8 deletions drivers/net/wireless/ath/ath11k/wmi.c
Original file line number Diff line number Diff line change
@@ -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:

0 comments on commit 26f6979

Please sign in to comment.