提交 26f69792 编写于 作者: L Lavanya Suresh 提交者: Kalle Valo

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: NLavanya Suresh <lavaks@codeaurora.org>
Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1614340859-28867-1-git-send-email-lavaks@codeaurora.org
上级 f277eb05
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define ATH11K_PRB_RSP_DROP_THRESHOLD ((ATH11K_TX_MGMT_TARGET_MAX_SUPPORT_WMI * 3) / 4) #define ATH11K_PRB_RSP_DROP_THRESHOLD ((ATH11K_TX_MGMT_TARGET_MAX_SUPPORT_WMI * 3) / 4)
#define ATH11K_INVALID_HW_MAC_ID 0xFF #define ATH11K_INVALID_HW_MAC_ID 0xFF
#define ATH11K_CONNECTION_LOSS_HZ (3 * HZ)
extern unsigned int ath11k_frame_mode; extern unsigned int ath11k_frame_mode;
...@@ -235,6 +236,7 @@ struct ath11k_vif { ...@@ -235,6 +236,7 @@ struct ath11k_vif {
u32 aid; u32 aid;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
struct cfg80211_bitrate_mask bitrate_mask; struct cfg80211_bitrate_mask bitrate_mask;
struct delayed_work connection_loss_work;
int num_legacy_stations; int num_legacy_stations;
int rtscts_prot_mode; int rtscts_prot_mode;
int txpower; int txpower;
......
...@@ -829,6 +829,75 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif, ...@@ -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); 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, static void ath11k_peer_assoc_h_basic(struct ath11k *ar,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
...@@ -1760,7 +1829,7 @@ static void ath11k_bss_disassoc(struct ieee80211_hw *hw, ...@@ -1760,7 +1829,7 @@ static void ath11k_bss_disassoc(struct ieee80211_hw *hw,
arvif->is_up = false; 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) 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, ...@@ -4615,10 +4684,8 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
arvif->vif = vif; arvif->vif = vif;
INIT_LIST_HEAD(&arvif->list); INIT_LIST_HEAD(&arvif->list);
INIT_DELAYED_WORK(&arvif->connection_loss_work,
/* Should we initialize any worker to handle connection loss indication ath11k_mac_vif_sta_connection_loss_work);
* from firmware in sta mode?
*/
for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) { for (i = 0; i < ARRAY_SIZE(arvif->bitrate_mask.control); i++) {
arvif->bitrate_mask.control[i].legacy = 0xffffffff; arvif->bitrate_mask.control[i].legacy = 0xffffffff;
...@@ -4827,6 +4894,8 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw, ...@@ -4827,6 +4894,8 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
int ret; int ret;
int i; int i;
cancel_delayed_work_sync(&arvif->connection_loss_work);
mutex_lock(&ar->conf_mutex); mutex_lock(&ar->conf_mutex);
ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n", 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); ...@@ -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); 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 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); 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 #endif
...@@ -6171,10 +6171,8 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb) ...@@ -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))
*if (ieee80211_is_beacon(hdr->frame_control)) ath11k_mac_handle_beacon(ar, skb);
* ath11k_mac_handle_beacon(ar, skb);
*/
ath11k_dbg(ab, ATH11K_DBG_MGMT, ath11k_dbg(ab, ATH11K_DBG_MGMT,
"event mgmt rx skb %pK len %d ftype %02x stype %02x\n", "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) ...@@ -6393,10 +6391,7 @@ static void ath11k_roam_event(struct ath11k_base *ab, struct sk_buff *skb)
switch (roam_ev.reason) { switch (roam_ev.reason) {
case WMI_ROAM_REASON_BEACON_MISS: case WMI_ROAM_REASON_BEACON_MISS:
/* TODO: Pending beacon miss and connection_loss_work ath11k_mac_handle_beacon_miss(ar, roam_ev.vdev_id);
* implementation
* ath11k_mac_handle_beacon_miss(ar, vdev_id);
*/
break; break;
case WMI_ROAM_REASON_BETTER_AP: case WMI_ROAM_REASON_BETTER_AP:
case WMI_ROAM_REASON_LOW_RSSI: case WMI_ROAM_REASON_LOW_RSSI:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册