diff mbox series

[v2,12/22] wifi: rtw88: Detect beacon loss with chips other than 8822c

Message ID a60666a1-88e6-4e84-ae9b-ac2eb903dd01@gmail.com
State New
Headers show
Series wifi: rtw88: Add support for RTL8821AU and RTL8812AU | expand

Commit Message

Bitterblue Smith Oct. 11, 2024, 8:52 p.m. UTC
The driver is supposed to avoid entering LPS (power saving) when there
is beacon loss, but only RTL8822C detects the beacon loss (because it
has beacon filtering in the firmware).

Detect beacon loss with the other chips by checking if we received less
than half the expected number of beacons in the last 2-second interval.

This gets rid of the occasional "failed to get tx report from firmware"
warnings with RTL8821AU. It may also avoid some disconnections.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
v2:
 - Move beacon loss checking to separate function.
 - Move variable declaration to the top.
---
 drivers/net/wireless/realtek/rtw88/main.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
diff mbox series

Patch

diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index e6f985a92019..65d20ad02667 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -202,6 +202,21 @@  static void rtw_vif_watch_dog_iter(void *data, struct ieee80211_vif *vif)
 	rtwvif->stats.rx_cnt = 0;
 }
 
+static void rtw_sw_beacon_loss_check(struct rtw_dev *rtwdev,
+				     struct rtw_vif *rtwvif, int received_beacons)
+{
+	int watchdog_delay = 2000000 / 1024; /* TU */
+	int beacon_int, expected_beacons;
+
+	if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER) || !rtwvif)
+		return;
+
+	beacon_int = rtwvif_to_vif(rtwvif)->bss_conf.beacon_int;
+	expected_beacons = DIV_ROUND_UP(watchdog_delay, beacon_int);
+
+	rtwdev->beacon_loss = received_beacons < expected_beacons / 2;
+}
+
 /* process TX/RX statistics periodically for hardware,
  * the information helps hardware to enhance performance
  */
@@ -212,6 +227,7 @@  static void rtw_watch_dog_work(struct work_struct *work)
 	struct rtw_traffic_stats *stats = &rtwdev->stats;
 	struct rtw_watch_dog_iter_data data = {};
 	bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
+	int received_beacons = rtwdev->dm_info.cur_pkt_count.num_bcn_pkt;
 	u32 tx_unicast_mbps, rx_unicast_mbps;
 	bool ps_active;
 
@@ -270,6 +286,8 @@  static void rtw_watch_dog_work(struct work_struct *work)
 	 */
 	rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data);
 
+	rtw_sw_beacon_loss_check(rtwdev, data.rtwvif, received_beacons);
+
 	/* fw supports only one station associated to enter lps, if there are
 	 * more than two stations associated to the AP, then we can not enter
 	 * lps, because fw does not handle the overlapped beacon interval